Message ID | 20201019021726.12048-9-dmitry.fomichev@wdc.com |
---|---|
State | Superseded |
Headers | show |
Series | hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set | expand |
On Oct 19 11:17, Dmitry Fomichev wrote: > ZNS specification defines two zone conditions for the zones that no > longer can function properly, possibly because of flash wear or other > internal fault. It is useful to be able to "inject" a small number of > such zones for testing purposes. > > This commit defines two optional device properties, "offline_zones" > and "rdonly_zones". Users can assign non-zero values to these variables > to specify the number of zones to be initialized as Offline or > Read-Only. The actual number of injected zones may be smaller than the > requested amount - Read-Only and Offline counts are expected to be much > smaller than the total number of zones on a drive. > > Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com> > --- > hw/block/nvme-ns.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++ > hw/block/nvme-ns.h | 2 ++ > 2 files changed, 66 insertions(+) > > diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c > index 255ded2b43..d050f97909 100644 > --- a/hw/block/nvme-ns.c > +++ b/hw/block/nvme-ns.c > @@ -21,6 +21,7 @@ > #include "sysemu/sysemu.h" > #include "sysemu/block-backend.h" > #include "qapi/error.h" > +#include "crypto/random.h" > > #include "hw/qdev-properties.h" > #include "hw/qdev-core.h" > @@ -132,6 +133,32 @@ static int nvme_calc_zone_geometry(NvmeNamespace *ns, Error **errp) > return -1; > } > > + if (ns->params.zd_extension_size) { > + if (ns->params.zd_extension_size & 0x3f) { > + error_setg(errp, > + "zone descriptor extension size must be a multiple of 64B"); > + return -1; > + } > + if ((ns->params.zd_extension_size >> 6) > 0xff) { > + error_setg(errp, "zone descriptor extension size is too large"); > + return -1; > + } > + } Looks like this should have been added in the previous patch.
> -----Original Message----- > From: Klaus Jensen <its@irrelevant.dk> > Sent: Monday, October 19, 2020 7:43 AM > To: Dmitry Fomichev <Dmitry.Fomichev@wdc.com> > Cc: Keith Busch <kbusch@kernel.org>; Klaus Jensen > <k.jensen@samsung.com>; Kevin Wolf <kwolf@redhat.com>; Philippe > Mathieu-Daudé <philmd@redhat.com>; Maxim Levitsky > <mlevitsk@redhat.com>; Fam Zheng <fam@euphon.net>; Niklas Cassel > <Niklas.Cassel@wdc.com>; Damien Le Moal <Damien.LeMoal@wdc.com>; > qemu-block@nongnu.org; qemu-devel@nongnu.org; Alistair Francis > <Alistair.Francis@wdc.com>; Matias Bjorling <Matias.Bjorling@wdc.com> > Subject: Re: [PATCH v7 08/11] hw/block/nvme: Add injection of Offline/Read- > Only zones > > On Oct 19 11:17, Dmitry Fomichev wrote: > > ZNS specification defines two zone conditions for the zones that no > > longer can function properly, possibly because of flash wear or other > > internal fault. It is useful to be able to "inject" a small number of > > such zones for testing purposes. > > > > This commit defines two optional device properties, "offline_zones" > > and "rdonly_zones". Users can assign non-zero values to these variables > > to specify the number of zones to be initialized as Offline or > > Read-Only. The actual number of injected zones may be smaller than the > > requested amount - Read-Only and Offline counts are expected to be much > > smaller than the total number of zones on a drive. > > > > Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com> > > --- > > hw/block/nvme-ns.c | 64 > ++++++++++++++++++++++++++++++++++++++++++++++ > > hw/block/nvme-ns.h | 2 ++ > > 2 files changed, 66 insertions(+) > > > > diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c > > index 255ded2b43..d050f97909 100644 > > --- a/hw/block/nvme-ns.c > > +++ b/hw/block/nvme-ns.c > > @@ -21,6 +21,7 @@ > > #include "sysemu/sysemu.h" > > #include "sysemu/block-backend.h" > > #include "qapi/error.h" > > +#include "crypto/random.h" > > > > #include "hw/qdev-properties.h" > > #include "hw/qdev-core.h" > > @@ -132,6 +133,32 @@ static int > nvme_calc_zone_geometry(NvmeNamespace *ns, Error **errp) > > return -1; > > } > > > > + if (ns->params.zd_extension_size) { > > + if (ns->params.zd_extension_size & 0x3f) { > > + error_setg(errp, > > + "zone descriptor extension size must be a multiple of 64B"); > > + return -1; > > + } > > + if ((ns->params.zd_extension_size >> 6) > 0xff) { > > + error_setg(errp, "zone descriptor extension size is too large"); > > + return -1; > > + } > > + } > > Looks like this should have been added in the previous patch. Right, this belongs to ZDE patch.
diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c index 255ded2b43..d050f97909 100644 --- a/hw/block/nvme-ns.c +++ b/hw/block/nvme-ns.c @@ -21,6 +21,7 @@ #include "sysemu/sysemu.h" #include "sysemu/block-backend.h" #include "qapi/error.h" +#include "crypto/random.h" #include "hw/qdev-properties.h" #include "hw/qdev-core.h" @@ -132,6 +133,32 @@ static int nvme_calc_zone_geometry(NvmeNamespace *ns, Error **errp) return -1; } + if (ns->params.zd_extension_size) { + if (ns->params.zd_extension_size & 0x3f) { + error_setg(errp, + "zone descriptor extension size must be a multiple of 64B"); + return -1; + } + if ((ns->params.zd_extension_size >> 6) > 0xff) { + error_setg(errp, "zone descriptor extension size is too large"); + return -1; + } + } + + if (ns->params.max_open_zones < nz) { + if (ns->params.nr_offline_zones > nz - ns->params.max_open_zones) { + error_setg(errp, "offline_zones value %u is too large", + ns->params.nr_offline_zones); + return -1; + } + if (ns->params.nr_rdonly_zones > + nz - ns->params.max_open_zones - ns->params.nr_offline_zones) { + error_setg(errp, "rdonly_zones value %u is too large", + ns->params.nr_rdonly_zones); + return -1; + } + } + return 0; } @@ -140,7 +167,9 @@ static void nvme_init_zone_state(NvmeNamespace *ns) uint64_t start = 0, zone_size = ns->zone_size; uint64_t capacity = ns->num_zones * zone_size; NvmeZone *zone; + uint32_t rnd; int i; + uint16_t zs; ns->zone_array = g_malloc0(ns->zone_array_size); if (ns->params.zd_extension_size) { @@ -167,6 +196,37 @@ static void nvme_init_zone_state(NvmeNamespace *ns) zone->w_ptr = start; start += zone_size; } + + /* If required, make some zones Offline or Read Only */ + + for (i = 0; i < ns->params.nr_offline_zones; i++) { + do { + qcrypto_random_bytes(&rnd, sizeof(rnd), NULL); + rnd %= ns->num_zones; + } while (rnd < ns->params.max_open_zones); + zone = &ns->zone_array[rnd]; + zs = nvme_get_zone_state(zone); + if (zs != NVME_ZONE_STATE_OFFLINE) { + nvme_set_zone_state(zone, NVME_ZONE_STATE_OFFLINE); + } else { + i--; + } + } + + for (i = 0; i < ns->params.nr_rdonly_zones; i++) { + do { + qcrypto_random_bytes(&rnd, sizeof(rnd), NULL); + rnd %= ns->num_zones; + } while (rnd < ns->params.max_open_zones); + zone = &ns->zone_array[rnd]; + zs = nvme_get_zone_state(zone); + if (zs != NVME_ZONE_STATE_OFFLINE && + zs != NVME_ZONE_STATE_READ_ONLY) { + nvme_set_zone_state(zone, NVME_ZONE_STATE_READ_ONLY); + } else { + i--; + } + } } static int nvme_zoned_init_ns(NvmeCtrl *n, NvmeNamespace *ns, int lba_index, @@ -360,6 +420,10 @@ static Property nvme_ns_props[] = { DEFINE_PROP_UINT32("max_open", NvmeNamespace, params.max_open_zones, 0), DEFINE_PROP_UINT32("zone_descr_ext_size", NvmeNamespace, params.zd_extension_size, 0), + DEFINE_PROP_UINT32("offline_zones", NvmeNamespace, + params.nr_offline_zones, 0), + DEFINE_PROP_UINT32("rdonly_zones", NvmeNamespace, + params.nr_rdonly_zones, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h index 2d70a13701..d65d8b0930 100644 --- a/hw/block/nvme-ns.h +++ b/hw/block/nvme-ns.h @@ -37,6 +37,8 @@ typedef struct NvmeNamespaceParams { uint32_t max_active_zones; uint32_t max_open_zones; uint32_t zd_extension_size; + uint32_t nr_offline_zones; + uint32_t nr_rdonly_zones; } NvmeNamespaceParams; typedef struct NvmeNamespace {
ZNS specification defines two zone conditions for the zones that no longer can function properly, possibly because of flash wear or other internal fault. It is useful to be able to "inject" a small number of such zones for testing purposes. This commit defines two optional device properties, "offline_zones" and "rdonly_zones". Users can assign non-zero values to these variables to specify the number of zones to be initialized as Offline or Read-Only. The actual number of injected zones may be smaller than the requested amount - Read-Only and Offline counts are expected to be much smaller than the total number of zones on a drive. Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com> --- hw/block/nvme-ns.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++ hw/block/nvme-ns.h | 2 ++ 2 files changed, 66 insertions(+)