From nobody Tue Feb 10 22:16:04 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linux.dev ARC-Seal: i=1; a=rsa-sha256; t=1672689381; cv=none; d=zohomail.com; s=zohoarc; b=ndqR5GIOUjCfPt/rV/9dWqvOo4am4WmOSiyKQH1RGBmo5PlwiOGACTGNbMn3+UXXC6SsIiJjNvGPxbekvCa6ypic4LswkRtPdxUC4gEVGxAEUQB+g7Az1aztefmb9SS7fXUR0sOPuu1Akx/ZFfHCPAWAi6FrSYB4+ERoGCtDAVI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1672689381; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=RdOBA5DYYdMruHREGKhUjSzTLb2Irj4Oj7CAwbp6CoY=; b=IvkO8jPCQfwGwJRSbdEwpRSK0ZeNRDb90sat2l7plwoua9fZVj5uGiyglvUGgziSx/AdCpc3vGxOhmrkEKNkMmev2C7Vb7mGWMt0krGRFRCrbhsBDQFodZXfxFFeeUns29ykqN/lX3vM+liN8nzZVQv19Se5FmebfERTDOQy2x8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1672689381420163.80503150286881; Mon, 2 Jan 2023 11:56:21 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pCQuE-0005Cv-8m; Mon, 02 Jan 2023 14:55:34 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pCQu0-000527-53 for qemu-devel@nongnu.org; Mon, 02 Jan 2023 14:55:20 -0500 Received: from resqmta-h1p-028592.sys.comcast.net ([2001:558:fd02:2446::5]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pCQtv-0007g1-Mo for qemu-devel@nongnu.org; Mon, 02 Jan 2023 14:55:19 -0500 Received: from resomta-h1p-027919.sys.comcast.net ([96.102.179.208]) by resqmta-h1p-028592.sys.comcast.net with ESMTP id CMnupB6sxGwAVCQtqp12RN; Mon, 02 Jan 2023 19:55:10 +0000 Received: from localhost.localdomain ([71.205.181.50]) by resomta-h1p-027919.sys.comcast.net with ESMTPA id CQtMpowOQrMVsCQtWpVN6C; Mon, 02 Jan 2023 19:54:51 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1672689310; bh=RdOBA5DYYdMruHREGKhUjSzTLb2Irj4Oj7CAwbp6CoY=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=n2oDPQOAItpi4KkuUNUvo+9GeBAluuOUGNEEUuFdag537qOrsweL+vbVukdToUmJ0 OWbBSCk9NpNIkxcTLZT5KV/rdvJfno/MNEBn2M5mxxvF4zCDsKmWSoGEaF/6X2qTH5 S7OUaHRfea5pDWZbZLkZ+hf1XnjEtIU+FQkVmTk650gCiZblRrl0zCU6ne9lftg5kp I3pp5uft8b4y3LNz9uO+dJyx2OcqmOn/gEaHuQuXkpFSzFgpyadfGPmn941Gzpan9Y b1EVvPXmpWmHKkETf/JvZdQdD5J4+3j+8/3sNPQRc8kYd6oogm+RXPvSggwXamih8M JXdiXOCYR2Zrg== X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvhedrjedvgddufedvucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhephhgvlhhopehlohgtrghlhhhoshhtrdhlohgtrghlughomhgrihhnpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepjedprhgtphhtthhopehqvghmuhdquggvvhgvlhesnhhonhhgnhhurdhorhhgpdhrtghpthhtohepmhhitghhrggvlhdrkhhrohhprggtiigvkhesshholhhiughighhmrdgtohhmpdhrtghpthhtohepqhgvmhhuqdgslhhotghksehnohhnghhnuhdrohhrghdprhgtphhtthhopehksghushgthheskhgvrhhnvghlrdhorhhgpdhrtghpthhtohepihhtshesihhrrhgvlhgvvhgrnhhtrdgukhdprhgtphhtthhopehkfiholhhfsehrvgguhhgrthdrtghomhdprhgtphhtthhopehhrhgvihhtiiesrhgvughhrghtrdgtohhm X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: qemu-devel@nongnu.org Cc: Michael Kropaczek , qemu-block@nongnu.org, Keith Busch , Klaus Jensen , Kevin Wolf , Hanna Reitz Subject: [PATCH v5 2/2] hw/nvme: Support for Namespaces Management from guest OS - delete-ns Date: Mon, 2 Jan 2023 12:54:03 -0700 Message-Id: <20230102195403.461-3-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230102195403.461-1-jonathan.derrick@linux.dev> References: <20230102195403.461-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: softfail client-ip=2001:558:fd02:2446::5; envelope-from=jonathan.derrick@linux.dev; helo=resqmta-h1p-028592.sys.comcast.net X-Spam_score_int: -11 X-Spam_score: -1.2 X-Spam_bar: - X-Spam_report: (-1.2 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, SPF_HELO_PASS=-0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @comcastmailservice.net) X-ZM-MESSAGEID: 1672689382647100001 Content-Type: text/plain; charset="utf-8" From: Michael Kropaczek Added support for NVMEe NameSpaces Mangement allowing the guest OS to delete namespaces by issuing nvme delete-ns command. It is an extension to currently implemented Qemu nvme virtual device. Virtual devices representing namespaces will be created and/or deleted during Qemu's running session, at anytime. Signed-off-by: Michael Kropaczek --- docs/system/devices/nvme.rst | 9 ++-- hw/nvme/ctrl.c | 82 ++++++++++++++++++++++++++++++++---- hw/nvme/ns-backend.c | 5 +++ hw/nvme/ns.c | 71 +++++++++++++++++++++++++++++++ hw/nvme/nvme.h | 2 + hw/nvme/trace-events | 1 + include/block/nvme.h | 1 + 7 files changed, 159 insertions(+), 12 deletions(-) diff --git a/docs/system/devices/nvme.rst b/docs/system/devices/nvme.rst index 6b3bee5e5d..f19072f1bc 100644 --- a/docs/system/devices/nvme.rst +++ b/docs/system/devices/nvme.rst @@ -103,12 +103,12 @@ Parameters: =20 ``auto-ns-path=3D`` If specified indicates a support for dynamic management of nvme namespac= es - by means of nvme create-ns command. This path points + by means of nvme create-ns and nvme delete-ns commands. This path points to the storage area for backend images must exist. Additionally it requi= res that parameter `ns-subsys` must be specified whereas parameter `drive` must not. The legacy namespace backend is disabled, instead, a pair of files 'nvme__ns_.cfg' and 'nvme__ns_.img' - will refer to respective namespaces. The create-ns, attach-ns + will refer to respective namespaces. The create-ns, delete-ns, attach-ns and detach-ns commands, issued at the guest side, will make changes to those files accordingly. For each namespace exists an image file in raw format and a config file @@ -140,8 +140,9 @@ Please note that ``nvme-ns`` device is not required to = support of dynamic namespaces management feature. It is not prohibited to assign a such devic= e to ``nvme`` device specified to support dynamic namespace management if one h= as an use case to do so, however, it will only coexist and be out of the scop= e of -Namespaces Management. NsIds will be consistently managed, creation (creat= e-ns) -of a namespace will not allocate the NsId already being taken. If ``nvme-n= s`` +Namespaces Management. Deletion (delete-ns) will render an error for this +namespace. NsIds will be consistently managed, creation (create-ns) of +a namespace will not allocate the NsId already being taken. If ``nvme-ns`` device conflicts with previously created one by create-ns (the same NsId), it will break QEMU's start up. More than one of NVMe controllers associated with NVMe subsystem are suppo= rted. diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 5ed35d7cf4..e0fac3c151 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -144,12 +144,12 @@ * * - `auto-ns-path` * If specified indicates a support for dynamic management of nvme names= paces - * by means of nvme create-ns command. This path pointing + * by means of nvme create-ns and nvme delete-ns commands. This path poi= nting * to a storage area for backend images must exist. Additionally it requ= ires * that parameter `ns-subsys` must be specified whereas parameter `drive` * must not. The legacy namespace backend is disabled, instead, a pair of * files 'nvme__ns_.cfg' and 'nvme__ns_.= img' - * will refer to respective namespaces. The create-ns, attach-ns + * will refer to respective namespaces. The create-ns, delete-ns, attach= -ns * and detach-ns commands, issued at the guest side, will make changes to * those files accordingly. * For each namespace exists an image file in raw format and a config fi= le @@ -5702,17 +5702,13 @@ static uint16_t nvme_ns_mgmt_create(NvmeCtrl *n, Nv= meRequest *req, uint32_t nsid } =20 if (nvme_cfg_update(n, ns->size, NVME_NS_ALLOC_CHK)) { - /* place for delete-ns */ - error_setg(&local_err, "Insufficient capacity, an orphaned ns[%"PR= Iu32"] will be left behind", nsid); - error_report_err(local_err); + nvme_ns_delete(n, nsid, NULL); return NVME_NS_INSUFFICIENT_CAPAC | NVME_DNR; } (void)nvme_cfg_update(n, ns->size, NVME_NS_ALLOC); if (nvme_cfg_save(n)) { (void)nvme_cfg_update(n, ns->size, NVME_NS_DEALLOC); - /* place for delete-ns */ - error_setg(&local_err, "Cannot save conf file, an orphaned ns[%"PR= Iu32"] will be left behind", nsid); - error_report_err(local_err); + nvme_ns_delete(n, nsid, NULL); return NVME_INVALID_FIELD | NVME_DNR; } =20 @@ -5726,6 +5722,66 @@ fail: return NVME_SUCCESS; } =20 +static uint16_t nvme_ns_mgmt_delete(NvmeCtrl *n, uint32_t nsid) +{ + NvmeNamespace *ns =3D NULL; + uint16_t first =3D nsid; + uint16_t last =3D nsid; + uint16_t i; + uint64_t image_size; + Error *local_err =3D NULL; + + if (!nsid) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + if (!n->params.ns_directory) { + error_setg(&local_err, "delete-ns not supported if 'auto-ns-path' = is not specified"); + goto fail; + } else if (n->namespace.blkconf.blk) { + error_setg(&local_err, "delete-ns not supported if 'drive' is spec= ified"); + goto fail; + } + + if (nsid =3D=3D NVME_NSID_BROADCAST) { + first =3D 1; + last =3D NVME_MAX_NAMESPACES; + } + + for (i =3D first; i <=3D last; i++) { + ns =3D nvme_subsys_ns(n->subsys, (uint32_t)i); + if (n->params.ns_directory && ns && ns_auto_check(n, ns, (uint32_t= )i)) { + error_setg(&local_err, "ns[%"PRIu32"] cannot be deleted, confi= gured via '-device nvme-ns...'", i); + error_report_err(local_err); + if (first !=3D last) { + local_err =3D NULL; /* we are skipping */ + } + } else if (ns) { + image_size =3D ns->size; + nvme_ns_delete(n, (uint16_t)i, &local_err); + if (local_err) { + goto fail; + } + (void)nvme_cfg_update(n, image_size, NVME_NS_DEALLOC); + if (nvme_cfg_save(n)) { + error_setg(&local_err, "Could not save nvme-cfg"); + goto fail; + } + } else if (first =3D=3D last) { + return NVME_INVALID_FIELD | NVME_DNR; + } + } + +fail: + if (local_err) { + error_report_err(local_err); + return NVME_INVALID_FIELD | NVME_DNR; + } + + nvme_update_dmrsl(n); + return NVME_SUCCESS; +} + static uint16_t nvme_ns_mgmt(NvmeCtrl *n, NvmeRequest *req) { NvmeIdCtrl *id =3D &n->id_ctrl; @@ -5760,6 +5816,16 @@ static uint16_t nvme_ns_mgmt(NvmeCtrl *n, NvmeReques= t *req) return NVME_INVALID_FIELD | NVME_DNR; } break; + case NVME_NS_MANAGEMENT_DELETE: + switch (csi) { + case NVME_CSI_NVM: + return nvme_ns_mgmt_delete(n, nsid); + case NVME_CSI_ZONED: + /* fall through for now */ + default: + return NVME_INVALID_FIELD | NVME_DNR; + } + break; default: return NVME_INVALID_FIELD | NVME_DNR; } diff --git a/hw/nvme/ns-backend.c b/hw/nvme/ns-backend.c index 06de8f262c..57d0b695fa 100644 --- a/hw/nvme/ns-backend.c +++ b/hw/nvme/ns-backend.c @@ -71,6 +71,11 @@ void ns_blockdev_activate(BlockBackend *blk, uint64_t i= mage_size, Error **errp) errp); } =20 +void ns_blockdev_deactivate(BlockBackend *blk, Error **errp) +{ + ns_blockdev_activate(blk, 0, errp); +} + int ns_storage_path_check(NvmeCtrl *n, Error **errp) { return storage_path_check(n->params.ns_directory, n->params.serial, e= rrp); diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 06cc6c8c71..653d136eae 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -610,6 +610,77 @@ fail: return NULL; } =20 +static void nvme_ns_unrealize(DeviceState *dev); +void nvme_ns_delete(NvmeCtrl *n, uint32_t nsid, Error **errp) +{ + NvmeNamespace *ns =3D NULL; + NvmeSubsystem *subsys =3D n->subsys; + int i; + int ret =3D 0; + Error *local_err =3D NULL; + + trace_pci_nvme_ns_delete(nsid); + + if (n->cntlid > 0 && !n->subsys) { + error_setg(&local_err, "Secondary controller without subsystem "); + return; + } + + if (subsys) { + ns =3D nvme_subsys_ns(subsys, (uint32_t)nsid); + if (ns) { + if (ns->params.shared) { + for (i =3D 0; i < ARRAY_SIZE(subsys->ctrls); i++) { + NvmeCtrl *ctrl =3D subsys->ctrls[i]; + + if (ctrl && ctrl->namespaces[nsid]) { + ctrl->namespaces[nsid] =3D NULL; + ns->attached--; + } + } + } + subsys->namespaces[nsid] =3D NULL; + } + } + + if (!ns) { + ns =3D nvme_ns(n, (uint32_t)nsid); + if (ns) { + n->namespaces[nsid] =3D NULL; + ns->attached--; + } else { + error_setg(errp, "Namespace %d does not exist", nsid); + return; + } + } + + if (ns->attached > 0) { + error_setg(errp, "Could not detach all ns references for ns[%d], s= till %d left", nsid, ns->attached); + return; + } + + /* here is actual deletion */ + nvme_ns_unrealize(&ns->parent_obj); + qdev_unrealize(&ns->parent_obj); + ns_blockdev_deactivate(ns->blkconf.blk, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + ns_cfg_clear(ns); + ret =3D ns_cfg_save(n, ns, nsid); + if (ret =3D=3D -1) { + error_setg(errp, "Unable to save ns-cnf"); + return; + } else if (ret =3D=3D 1) { /* should not occur here, check and error = message prior to call to nvme_ns_delete() */ + return; + } + + /* disassociating refernces to the back-end and keeping it as preloade= d */ + ns->blkconf.blk =3D NULL; +} + int nvme_ns_setup(NvmeNamespace *ns, Error **errp) { if (nvme_ns_check_constraints(ns, errp)) { diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 4df57096ef..c7a782d7d1 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -280,6 +280,7 @@ void nvme_ns_shutdown(NvmeNamespace *ns); void nvme_ns_cleanup(NvmeNamespace *ns); void nvme_validate_flbas(uint8_t flbas, Error **errp); NvmeNamespace *nvme_ns_create(NvmeCtrl *n, uint32_t nsid, NvmeIdNsMgmt *id= _ns, Error **errp); +void nvme_ns_delete(NvmeCtrl *n, uint32_t nsid, Error **errp); =20 typedef struct NvmeAsyncEvent { QTAILQ_ENTRY(NvmeAsyncEvent) entry; @@ -581,6 +582,7 @@ static inline NvmeSecCtrlEntry *nvme_sctrl_for_cntlid(N= vmeCtrl *n, =20 BlockBackend *ns_blockdev_init(const char *file, Error **errp); void ns_blockdev_activate(BlockBackend *blk, uint64_t image_size, Error *= *errp); +void ns_blockdev_deactivate(BlockBackend *blk, Error **errp); int nvme_ns_backend_setup(NvmeCtrl *n, Error **errp); void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns); uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len, diff --git a/hw/nvme/trace-events b/hw/nvme/trace-events index 28b025ac42..0dd0c23208 100644 --- a/hw/nvme/trace-events +++ b/hw/nvme/trace-events @@ -79,6 +79,7 @@ pci_nvme_aer_masked(uint8_t type, uint8_t mask) "type 0x%= "PRIx8" mask 0x%"PRIx8" pci_nvme_aer_post_cqe(uint8_t typ, uint8_t info, uint8_t log_page) "type 0= x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8"" pci_nvme_ns_mgmt(uint16_t cid, uint32_t nsid, uint8_t sel, uint8_t csi, ui= nt8_t psdt) "cid %"PRIu16", nsid=3D%"PRIu32", sel=3D0x%"PRIx8", csi=3D0x%"P= RIx8", psdt=3D0x%"PRIx8"" pci_nvme_ns_create(uint16_t nsid, uint64_t nsze, uint64_t ncap, uint8_t fl= bas) "nsid %"PRIu16", nsze=3D%"PRIu64", ncap=3D%"PRIu64", flbas=3D%"PRIu8"" +pci_nvme_ns_delete(uint16_t nsid) "nsid %"PRIu16"" pci_nvme_ns_attachment(uint16_t cid, uint8_t sel) "cid %"PRIu16", sel=3D0x= %"PRIx8"" pci_nvme_ns_attachment_attach(uint16_t cntlid, uint32_t nsid) "cntlid=3D0x= %"PRIx16", nsid=3D0x%"PRIx32"" pci_nvme_enqueue_event(uint8_t typ, uint8_t info, uint8_t log_page) "type = 0x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8"" diff --git a/include/block/nvme.h b/include/block/nvme.h index 9d2e121f1a..0fe7fe9bb1 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -1191,6 +1191,7 @@ enum NvmeIdCtrlCmic { =20 enum NvmeNsManagementOperation { NVME_NS_MANAGEMENT_CREATE =3D 0x0, + NVME_NS_MANAGEMENT_DELETE =3D 0x1, }; =20 enum NvmeNsAttachmentOperation { --=20 2.37.3