summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKlaus Jensen2021-01-11 13:52:40 +0100
committerKlaus Jensen2021-02-08 21:15:49 +0100
commit1b5804a80d8bd6ecb8910e864afb89049279df17 (patch)
tree3fd799fff2521c7afa81c3c3030f6aab4072e9eb
parenthw/block/nvme: fix for non-msix machines (diff)
downloadqemu-1b5804a80d8bd6ecb8910e864afb89049279df17.tar.gz
qemu-1b5804a80d8bd6ecb8910e864afb89049279df17.tar.xz
qemu-1b5804a80d8bd6ecb8910e864afb89049279df17.zip
hw/block/nvme: conditionally enable DULBE for zoned namespaces
The device uses the BDRV_BLOCK_ZERO flag to determine the "deallocated" status of logical blocks. Since the zoned namespaces command set specification defines that logical blocks SHALL be marked as deallocated when the zone is in the Empty or Offline states, DULBE can only be supported if the zone size is a multiple of the calculated deallocation granularity (reported in NPDG) which depends on the underlying block device cluster size (if applicable) or the configured discard_granularity. Reviewed-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
-rw-r--r--hw/block/nvme-ns.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c
index 838b15c064..9be170abb7 100644
--- a/hw/block/nvme-ns.c
+++ b/hw/block/nvme-ns.c
@@ -16,6 +16,7 @@
#include "qemu/units.h"
#include "qemu/cutils.h"
#include "qemu/log.h"
+#include "qemu/error-report.h"
#include "hw/block/block.h"
#include "hw/pci/pci.h"
#include "sysemu/sysemu.h"
@@ -227,6 +228,22 @@ static void nvme_ns_init_zoned(NvmeCtrl *n, NvmeNamespace *ns, int lba_index)
ns->id_ns.ncap = ns->id_ns.nsze;
ns->id_ns.nuse = ns->id_ns.ncap;
+ /*
+ * The device uses the BDRV_BLOCK_ZERO flag to determine the "deallocated"
+ * status of logical blocks. Since the spec defines that logical blocks
+ * SHALL be deallocated when then zone is in the Empty or Offline states,
+ * we can only support DULBE if the zone size is a multiple of the
+ * calculated NPDG.
+ */
+ if (ns->zone_size % (ns->id_ns.npdg + 1)) {
+ warn_report("the zone size (%"PRIu64" blocks) is not a multiple of "
+ "the calculated deallocation granularity (%d blocks); "
+ "DULBE support disabled",
+ ns->zone_size, ns->id_ns.npdg + 1);
+
+ ns->id_ns.nsfeat &= ~0x4;
+ }
+
ns->id_ns_zoned = id_ns_z;
}