[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 16/18] hw/block/nvme: Add injection of Offline/Read-Only zones
From: |
Dmitry Fomichev |
Subject: |
[PATCH 16/18] hw/block/nvme: Add injection of Offline/Read-Only zones |
Date: |
Tue, 16 Jun 2020 08:36:56 +0900 |
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 driver properties, "offline_zones"
and "rdonly_zones". User 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 drive zones.
Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
---
hw/block/nvme.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
hw/block/nvme.h | 2 ++
2 files changed, 48 insertions(+)
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 16780d5116..930f5f9d41 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2979,8 +2979,11 @@ static int nvme_init_zone_meta(NvmeCtrl *n,
NvmeNamespace *ns,
uint64_t capacity)
{
NvmeZone *zone;
+ Error *err;
uint64_t start = 0, zone_size = n->params.zone_size;
+ uint32_t rnd;
int i;
+ uint16_t zs;
ns->zone_array = g_malloc0(n->zone_array_size);
ns->exp_open_zones = g_malloc0(sizeof(NvmeZoneList));
@@ -3010,6 +3013,37 @@ static int nvme_init_zone_meta(NvmeCtrl *n,
NvmeNamespace *ns,
start += zone_size;
}
+ /* If required, make some zones Offline or Read Only */
+
+ for (i = 0; i < n->params.nr_offline_zones; i++) {
+ do {
+ qcrypto_random_bytes(&rnd, sizeof(rnd), &err);
+ rnd %= n->num_zones;
+ } while (rnd < n->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 < n->params.nr_rdonly_zones; i++) {
+ do {
+ qcrypto_random_bytes(&rnd, sizeof(rnd), &err);
+ rnd %= n->num_zones;
+ } while (rnd < n->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--;
+ }
+ }
+
return 0;
}
@@ -3062,6 +3096,16 @@ static void nvme_zoned_init_ctrl(NvmeCtrl *n, Error
**errp)
if (n->params.max_active_zones > nz) {
n->params.max_active_zones = nz;
}
+ if (n->params.max_open_zones < nz) {
+ if (n->params.nr_offline_zones > nz - n->params.max_open_zones) {
+ n->params.nr_offline_zones = nz - n->params.max_open_zones;
+ }
+ if (n->params.nr_rdonly_zones >
+ nz - n->params.max_open_zones - n->params.nr_offline_zones) {
+ n->params.nr_rdonly_zones =
+ nz - n->params.max_open_zones - n->params.nr_offline_zones;
+ }
+ }
if (n->params.zd_extension_size) {
if (n->params.zd_extension_size & 0x3f) {
error_setg(errp,
@@ -3453,6 +3497,8 @@ static Property nvme_props[] = {
DEFINE_PROP_UINT64("finish_rcmnd_delay", NvmeCtrl,
params.fzr_delay_usec, 0),
DEFINE_PROP_UINT64("finish_rcmnd_limit", NvmeCtrl, params.frl_usec, 0),
+ DEFINE_PROP_UINT32("offline_zones", NvmeCtrl, params.nr_offline_zones, 0),
+ DEFINE_PROP_UINT32("rdonly_zones", NvmeCtrl, params.nr_rdonly_zones, 0),
DEFINE_PROP_BOOL("zone_async_events", NvmeCtrl, params.zone_async_events,
true),
DEFINE_PROP_BOOL("cross_zone_read", NvmeCtrl, params.cross_zone_read,
true),
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index a9ac01434b..1726cc9d6e 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -23,6 +23,8 @@ typedef struct NvmeParams {
uint64_t zone_capacity;
int32_t max_active_zones;
int32_t max_open_zones;
+ uint32_t nr_offline_zones;
+ uint32_t nr_rdonly_zones;
uint32_t zd_extension_size;
uint64_t rzr_delay_usec;
uint64_t rrl_usec;
--
2.21.0
- [PATCH 04/18] hw/block/nvme: Add Commands Supported and Effects log, (continued)
- [PATCH 04/18] hw/block/nvme: Add Commands Supported and Effects log, Dmitry Fomichev, 2020/06/15
- [PATCH 07/18] hw/block/nvme: Add support for Namespace Types, Dmitry Fomichev, 2020/06/15
- [PATCH 09/18] hw/block/nvme: Define Zoned NS Command Set trace events, Dmitry Fomichev, 2020/06/15
- [PATCH 08/18] hw/block/nvme: Make Zoned NS Command Set definitions, Dmitry Fomichev, 2020/06/15
- [PATCH 10/18] hw/block/nvme: Support Zoned Namespace Command Set, Dmitry Fomichev, 2020/06/15
- [PATCH 11/18] hw/block/nvme: Introduce max active and open zone limits, Dmitry Fomichev, 2020/06/15
- [PATCH 12/18] hw/block/nvme: Simulate Zone Active excursions, Dmitry Fomichev, 2020/06/15
- [PATCH 13/18] hw/block/nvme: Set Finish/Reset Zone Recommended attributes, Dmitry Fomichev, 2020/06/15
- [PATCH 14/18] hw/block/nvme: Generate zone AENs, Dmitry Fomichev, 2020/06/15
- [PATCH 15/18] hw/block/nvme: Support Zone Descriptor Extensions, Dmitry Fomichev, 2020/06/15
- [PATCH 16/18] hw/block/nvme: Add injection of Offline/Read-Only zones,
Dmitry Fomichev <=
- [PATCH 18/18] hw/block/nvme: Document zoned parameters in usage text, Dmitry Fomichev, 2020/06/15
- [PATCH 17/18] hw/block/nvme: Use zone metadata file for persistence, Dmitry Fomichev, 2020/06/15