From: Dmitry Fomichev <dmitry.fomichev@wdc.com>
To: "Keith Busch" <kbusch@kernel.org>,
"Klaus Jensen" <k.jensen@samsung.com>,
"Kevin Wolf" <kwolf@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@redhat.com>,
"Max Reitz" <mreitz@redhat.com>,
"Maxim Levitsky" <mlevitsk@redhat.com>,
"Fam Zheng" <fam@euphon.net>
Cc: Niklas Cassel <niklas.cassel@wdc.com>,
Damien Le Moal <damien.lemoal@wdc.com>,
qemu-block@nongnu.org, Dmitry Fomichev <dmitry.fomichev@wdc.com>,
qemu-devel@nongnu.org,
Alistair Francis <alistair.francis@wdc.com>,
Matias Bjorling <matias.bjorling@wdc.com>
Subject: [PATCH v10 11/12] hw/block/nvme: Add injection of Offline/Read-Only zones
Date: Sat, 7 Nov 2020 08:43:04 +0900 [thread overview]
Message-ID: <20201106234305.21339-12-dmitry.fomichev@wdc.com> (raw)
In-Reply-To: <20201106234305.21339-1-dmitry.fomichev@wdc.com>
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>
Reviewed-by: Niklas Cassel <Niklas.Cassel@wdc.com>
---
hw/block/nvme-ns.h | 2 ++
hw/block/nvme-ns.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h
index 50a6a0e1ac..b30478e5d7 100644
--- a/hw/block/nvme-ns.h
+++ b/hw/block/nvme-ns.h
@@ -36,6 +36,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 {
diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c
index 85dc73cf06..5e4a6705cd 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"
@@ -145,6 +146,20 @@ static int nvme_calc_zone_geometry(NvmeNamespace *ns, Error **errp)
}
}
+ 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;
}
@@ -153,7 +168,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) {
@@ -180,6 +197,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,
@@ -353,6 +401,10 @@ static Property nvme_ns_props[] = {
params.max_open_zones, 0),
DEFINE_PROP_UINT32("zoned.descr_ext_size", NvmeNamespace,
params.zd_extension_size, 0),
+ DEFINE_PROP_UINT32("zoned.offline_zones", NvmeNamespace,
+ params.nr_offline_zones, 0),
+ DEFINE_PROP_UINT32("zoned.rdonly_zones", NvmeNamespace,
+ params.nr_rdonly_zones, 0),
DEFINE_PROP_END_OF_LIST(),
};
--
2.21.0
next prev parent reply other threads:[~2020-11-06 23:47 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-06 23:42 [PATCH v10 00/12] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set Dmitry Fomichev
2020-11-06 23:42 ` [PATCH v10 01/12] hw/block/nvme: Add Commands Supported and Effects log Dmitry Fomichev
2020-11-06 23:42 ` [PATCH v10 02/12] hw/block/nvme: Generate namespace UUIDs Dmitry Fomichev
2020-11-06 23:42 ` [PATCH v10 03/12] hw/block/nvme: Separate read and write handlers Dmitry Fomichev
2020-11-06 23:42 ` [PATCH v10 04/12] hw/block/nvme: Merge nvme_write_zeroes() with nvme_write() Dmitry Fomichev
2020-11-06 23:42 ` [PATCH v10 05/12] hw/block/nvme: Add support for Namespace Types Dmitry Fomichev
2020-11-06 23:42 ` [PATCH v10 06/12] hw/block/nvme: Support allocated CNS command variants Dmitry Fomichev
2020-11-12 20:43 ` Klaus Jensen
2020-11-06 23:43 ` [PATCH v10 07/12] block/nvme: Make ZNS-related definitions Dmitry Fomichev
2020-11-06 23:43 ` [PATCH v10 08/12] hw/block/nvme: Support Zoned Namespace Command Set Dmitry Fomichev
2020-11-06 23:43 ` [PATCH v10 09/12] hw/block/nvme: Introduce max active and open zone limits Dmitry Fomichev
2020-11-12 19:40 ` Klaus Jensen
2020-11-06 23:43 ` [PATCH v10 10/12] hw/block/nvme: Support Zone Descriptor Extensions Dmitry Fomichev
2020-11-06 23:43 ` Dmitry Fomichev [this message]
2020-11-06 23:43 ` [PATCH v10 12/12] hw/block/nvme: Document zoned parameters in usage text Dmitry Fomichev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201106234305.21339-12-dmitry.fomichev@wdc.com \
--to=dmitry.fomichev@wdc.com \
--cc=alistair.francis@wdc.com \
--cc=damien.lemoal@wdc.com \
--cc=fam@euphon.net \
--cc=k.jensen@samsung.com \
--cc=kbusch@kernel.org \
--cc=kwolf@redhat.com \
--cc=matias.bjorling@wdc.com \
--cc=mlevitsk@redhat.com \
--cc=mreitz@redhat.com \
--cc=niklas.cassel@wdc.com \
--cc=philmd@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).