[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 12/14] hw/block/nvme: Add injection of Offline/Read-Only zones
From: |
Dmitry Fomichev |
Subject: |
[PATCH v4 12/14] hw/block/nvme: Add injection of Offline/Read-Only zones |
Date: |
Thu, 24 Sep 2020 03:20:19 +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 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.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 cfa791aa72..4630be38d7 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -3402,8 +3402,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->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));
@@ -3434,6 +3437,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;
}
@@ -3484,6 +3518,16 @@ static void nvme_zoned_init_ctrl(NvmeCtrl *n, Error
**errp)
" adjusting", 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,
@@ -3916,6 +3960,8 @@ static Property nvme_props[] = {
params.zd_extension_size, 0),
DEFINE_PROP_UINT32("max_active", NvmeCtrl, params.max_active_zones, 0),
DEFINE_PROP_UINT32("max_open", NvmeCtrl, params.max_open_zones, 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("cross_zone_read", NvmeCtrl, params.cross_zone_read,
true),
DEFINE_PROP_UINT8("fill_pattern", NvmeCtrl, params.fill_pattern, 0),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index 0e82fca815..dea0c12792 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -25,6 +25,8 @@ typedef struct NvmeParams {
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;
} NvmeParams;
typedef struct NvmeAsyncEvent {
--
2.21.0
- Re: [PATCH v4 06/14] hw/block/nvme: Add support for active/inactive namespaces, (continued)
[PATCH v4 07/14] hw/block/nvme: Make Zoned NS Command Set definitions, Dmitry Fomichev, 2020/09/23
[PATCH v4 05/14] hw/block/nvme: Add support for Namespace Types, Dmitry Fomichev, 2020/09/23
[PATCH v4 08/14] hw/block/nvme: Define Zoned NS Command Set trace events, Dmitry Fomichev, 2020/09/23
[PATCH v4 10/14] hw/block/nvme: Introduce max active and open zone limits, Dmitry Fomichev, 2020/09/23
[PATCH v4 11/14] hw/block/nvme: Support Zone Descriptor Extensions, Dmitry Fomichev, 2020/09/23
[PATCH v4 09/14] hw/block/nvme: Support Zoned Namespace Command Set, Dmitry Fomichev, 2020/09/23
[PATCH v4 13/14] hw/block/nvme: Use zone metadata file for persistence, Dmitry Fomichev, 2020/09/23
[PATCH v4 12/14] hw/block/nvme: Add injection of Offline/Read-Only zones,
Dmitry Fomichev <=
[PATCH v4 14/14] hw/block/nvme: Document zoned parameters in usage text, Dmitry Fomichev, 2020/09/23
Re: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Klaus Jensen, 2020/09/24
- RE: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Dmitry Fomichev, 2020/09/27
- Re: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Klaus Jensen, 2020/09/28
- Re: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Keith Busch, 2020/09/28
- Re: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Damien Le Moal, 2020/09/28
- Re: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Klaus Jensen, 2020/09/29
- Re: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Damien Le Moal, 2020/09/29
- Re: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Keith Busch, 2020/09/29
- RE: [PATCH v4 00/14] hw/block/nvme: Support Namespace Types and Zoned Namespace Command Set, Dmitry Fomichev, 2020/09/29