From: Klaus Jensen <its@irrelevant.dk>
To: qemu-devel@nongnu.org
Cc: Fam Zheng <fam@euphon.net>, Kevin Wolf <kwolf@redhat.com>,
qemu-block@nongnu.org, Klaus Jensen <k.jensen@samsung.com>,
Max Reitz <mreitz@redhat.com>, Keith Busch <kbusch@kernel.org>,
Stefan Hajnoczi <stefanha@redhat.com>,
Klaus Jensen <its@irrelevant.dk>
Subject: [PATCH v3 8/9] hw/block/nvme: track and enforce zone resources
Date: Wed, 14 Oct 2020 13:31:21 +0200 [thread overview]
Message-ID: <20201014113122.388849-9-its@irrelevant.dk> (raw)
In-Reply-To: <20201014113122.388849-1-its@irrelevant.dk>
From: Klaus Jensen <k.jensen@samsung.com>
Track number of open/active resources.
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
docs/specs/nvme.txt | 6 ++++
hw/block/nvme-ns.h | 7 +++++
include/block/nvme.h | 2 ++
hw/block/nvme-ns.c | 25 +++++++++++++++--
hw/block/nvme.c | 66 +++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 102 insertions(+), 4 deletions(-)
diff --git a/docs/specs/nvme.txt b/docs/specs/nvme.txt
index 80cb34406255..03bb4d9516b4 100644
--- a/docs/specs/nvme.txt
+++ b/docs/specs/nvme.txt
@@ -14,6 +14,12 @@ The nvme device (-device nvme) emulates an NVM Express Controller.
zns.zcap; if the zone capacity is a power of two, the zone size will be
set to that, otherwise it will default to the next power of two.
+ `zns.mar`; Specifies the number of active resources available. This is a 0s
+ based value.
+
+ `zns.mor`; Specifies the number of open resources available. This is a 0s
+ based value.
+
Reference Specifications
------------------------
diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h
index a273e7f7ed4b..3d0269eef6f0 100644
--- a/hw/block/nvme-ns.h
+++ b/hw/block/nvme-ns.h
@@ -28,6 +28,8 @@ typedef struct NvmeNamespaceParams {
uint64_t zcap;
uint64_t zsze;
uint8_t zdes;
+ uint32_t mar;
+ uint32_t mor;
} zns;
} NvmeNamespaceParams;
@@ -58,6 +60,11 @@ typedef struct NvmeNamespace {
NvmeZone *zones;
NvmeZoneDescriptor *zd;
uint8_t *zde;
+
+ struct {
+ uint32_t open;
+ uint32_t active;
+ } resources;
} zns;
} NvmeNamespace;
diff --git a/include/block/nvme.h b/include/block/nvme.h
index aecefefd43b6..4ca5f3fb15eb 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -775,6 +775,8 @@ enum NvmeStatusCodes {
NVME_ZONE_IS_READ_ONLY = 0x01ba,
NVME_ZONE_IS_OFFLINE = 0x01bb,
NVME_ZONE_INVALID_WRITE = 0x01bc,
+ NVME_TOO_MANY_ACTIVE_ZONES = 0x01bd,
+ NVME_TOO_MANY_OPEN_ZONES = 0x01be,
NVME_INVALID_ZONE_STATE_TRANSITION = 0x01bf,
NVME_WRITE_FAULT = 0x0280,
NVME_UNRECOVERED_READ = 0x0281,
diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c
index 0922b67dd6d8..a01cc5eeb445 100644
--- a/hw/block/nvme-ns.c
+++ b/hw/block/nvme-ns.c
@@ -92,8 +92,8 @@ static void nvme_ns_init_zoned(NvmeNamespace *ns)
ns->zns.zde = g_malloc0_n(ns->zns.num_zones, nvme_ns_zdes_bytes(ns));
}
- id_ns_zns->mar = 0xffffffff;
- id_ns_zns->mor = 0xffffffff;
+ id_ns_zns->mar = cpu_to_le32(ns->params.zns.mar);
+ id_ns_zns->mor = cpu_to_le32(ns->params.zns.mor);
}
static void nvme_ns_init(NvmeNamespace *ns)
@@ -130,6 +130,11 @@ static void nvme_ns_init(NvmeNamespace *ns)
void nvme_ns_zns_init_zone_state(NvmeNamespace *ns)
{
+ ns->zns.resources.active = ns->params.zns.mar != 0xffffffff ?
+ ns->params.zns.mar + 1 : ns->zns.num_zones;
+ ns->zns.resources.open = ns->params.zns.mor != 0xffffffff ?
+ ns->params.zns.mor + 1 : ns->zns.num_zones;
+
for (int i = 0; i < ns->zns.num_zones; i++) {
NvmeZone *zone = &ns->zns.zones[i];
zone->zd = &ns->zns.zd[i];
@@ -148,9 +153,15 @@ void nvme_ns_zns_init_zone_state(NvmeNamespace *ns)
if (nvme_wp(zone) == nvme_zslba(zone) &&
!(zone->zd->za & NVME_ZA_ZDEV)) {
nvme_zs_set(zone, NVME_ZS_ZSE);
+ break;
}
- break;
+ if (ns->zns.resources.active) {
+ ns->zns.resources.active--;
+ break;
+ }
+
+ /* fallthrough */
case NVME_ZS_ZSIO:
case NVME_ZS_ZSEO:
@@ -207,6 +218,12 @@ static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp)
return -1;
}
+ if (ns->params.zns.mor > ns->params.zns.mar) {
+ error_setg(errp, "maximum open resources (zns.mor) must be less "
+ "than or equal to maximum active resources (zns.mar)");
+ return -1;
+ }
+
break;
default:
@@ -272,6 +289,8 @@ static Property nvme_ns_props[] = {
DEFINE_PROP_UINT64("zns.zcap", NvmeNamespace, params.zns.zcap, 0),
DEFINE_PROP_UINT64("zns.zsze", NvmeNamespace, params.zns.zsze, 0),
DEFINE_PROP_UINT8("zns.zdes", NvmeNamespace, params.zns.zdes, 0),
+ DEFINE_PROP_UINT32("zns.mar", NvmeNamespace, params.zns.mar, 0xffffffff),
+ DEFINE_PROP_UINT32("zns.mor", NvmeNamespace, params.zns.mor, 0xffffffff),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 947554c48b35..cc637b3a68e9 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1119,6 +1119,40 @@ static uint16_t nvme_zrm_transition(NvmeNamespace *ns, NvmeZone *zone,
switch (from) {
case NVME_ZS_ZSE:
+ switch (to) {
+ case NVME_ZS_ZSF:
+ case NVME_ZS_ZSRO:
+ case NVME_ZS_ZSO:
+ break;
+
+ case NVME_ZS_ZSC:
+ if (!ns->zns.resources.active) {
+ return NVME_TOO_MANY_ACTIVE_ZONES;
+ }
+
+ ns->zns.resources.active--;
+
+ break;
+
+ case NVME_ZS_ZSIO:
+ case NVME_ZS_ZSEO:
+ if (!ns->zns.resources.active) {
+ return NVME_TOO_MANY_ACTIVE_ZONES;
+ }
+
+ if (!ns->zns.resources.open) {
+ return NVME_TOO_MANY_OPEN_ZONES;
+ }
+
+ ns->zns.resources.active--;
+ ns->zns.resources.open--;
+
+ break;
+
+ default:
+ return NVME_INVALID_ZONE_STATE_TRANSITION | NVME_DNR;
+ }
+
break;
case NVME_ZS_ZSIO:
@@ -1137,7 +1171,13 @@ static uint16_t nvme_zrm_transition(NvmeNamespace *ns, NvmeZone *zone,
case NVME_ZS_ZSEO:
case NVME_ZS_ZSF:
case NVME_ZS_ZSRO:
+ ns->zns.resources.active++;
+
+ /* fallthrough */
+
case NVME_ZS_ZSC:
+ ns->zns.resources.open++;
+
break;
default:
@@ -1160,8 +1200,18 @@ static uint16_t nvme_zrm_transition(NvmeNamespace *ns, NvmeZone *zone,
case NVME_ZS_ZSF:
case NVME_ZS_ZSRO:
+ ns->zns.resources.active++;
+
+ break;
+
case NVME_ZS_ZSIO:
case NVME_ZS_ZSEO:
+ if (!ns->zns.resources.open) {
+ return NVME_TOO_MANY_OPEN_ZONES;
+ }
+
+ ns->zns.resources.open--;
+
break;
default:
@@ -1492,7 +1542,7 @@ static uint16_t nvme_zone_mgmt_send_all(NvmeCtrl *n, NvmeRequest *req)
NvmeZoneManagementSendCmd *send = (NvmeZoneManagementSendCmd *) &req->cmd;
NvmeNamespace *ns = req->ns;
NvmeZone *zone;
- int *countp = NULL;
+ int count, *countp = NULL;
uint16_t status = NVME_SUCCESS;
trace_pci_nvme_zone_mgmt_send_all(nvme_cid(req), nvme_nsid(ns), send->zsa);
@@ -1541,6 +1591,20 @@ static uint16_t nvme_zone_mgmt_send_all(NvmeCtrl *n, NvmeRequest *req)
break;
case NVME_CMD_ZONE_MGMT_SEND_OPEN:
+ count = 0;
+
+ for (int i = 0; i < ns->zns.num_zones; i++) {
+ zone = &ns->zns.zones[i];
+
+ if (nvme_zs(zone) == NVME_ZS_ZSC) {
+ count++;
+ }
+ }
+
+ if (count > ns->zns.resources.open) {
+ return NVME_TOO_MANY_OPEN_ZONES;
+ }
+
for (int i = 0; i < ns->zns.num_zones; i++) {
zone = &ns->zns.zones[i];
--
2.28.0
next prev parent reply other threads:[~2020-10-14 11:53 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-14 11:31 [PATCH v3 0/9] hw/block/nvme: zoned namespace command set Klaus Jensen
2020-10-14 11:31 ` [PATCH v3 1/9] hw/block/nvme: add commands supported and effects log page Klaus Jensen
2020-10-14 11:31 ` [PATCH v3 2/9] hw/block/nvme: add uuid namespace parameter Klaus Jensen
2020-10-14 11:31 ` [PATCH v3 3/9] hw/block/nvme: support namespace types Klaus Jensen
2020-10-14 11:31 ` [PATCH v3 4/9] hw/block/nvme: add basic read/write for zoned namespaces Klaus Jensen
2020-10-14 11:31 ` [PATCH v3 5/9] hw/block/nvme: add the zone management receive command Klaus Jensen
2020-10-14 11:31 ` [PATCH v3 6/9] hw/block/nvme: add the zone management send command Klaus Jensen
2020-10-14 11:31 ` [PATCH v3 7/9] hw/block/nvme: add the zone append command Klaus Jensen
2020-10-14 11:31 ` Klaus Jensen [this message]
2020-10-14 11:31 ` [PATCH v3 9/9] hw/block/nvme: allow open to close zone transitions by controller Klaus Jensen
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=20201014113122.388849-9-its@irrelevant.dk \
--to=its@irrelevant.dk \
--cc=fam@euphon.net \
--cc=k.jensen@samsung.com \
--cc=kbusch@kernel.org \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.