From nobody Sun May 19 11:06:53 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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=samsung.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1628860505525467.63365061836055; Fri, 13 Aug 2021 06:15:05 -0700 (PDT) Received: from localhost ([::1]:51418 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mEX1c-0002uQ-32 for importer@patchew.org; Fri, 13 Aug 2021 09:15:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50746) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mEV9D-0000OP-6E for qemu-devel@nongnu.org; Fri, 13 Aug 2021 07:14:47 -0400 Received: from mailout3.samsung.com ([203.254.224.33]:29240) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mEV98-0004aB-02 for qemu-devel@nongnu.org; Fri, 13 Aug 2021 07:14:47 -0400 Received: from epcas5p1.samsung.com (unknown [182.195.41.39]) by mailout3.samsung.com (KnoxPortal) with ESMTP id 20210813111432epoutp0354863bf182e71de75c86b369a9616057~a2WvT-r213215232152epoutp03W for ; Fri, 13 Aug 2021 11:14:32 +0000 (GMT) Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas5p1.samsung.com (KnoxPortal) with ESMTP id 20210813111431epcas5p179819f40d10542f8eeca8626d490e6c8~a2WuHusTY2952529525epcas5p1o; Fri, 13 Aug 2021 11:14:31 +0000 (GMT) Received: from epsmges5p2new.samsung.com (unknown [182.195.38.174]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4GmLYB4DV7z4x9Pv; Fri, 13 Aug 2021 11:14:22 +0000 (GMT) Received: from epcas5p2.samsung.com ( [182.195.41.40]) by epsmges5p2new.samsung.com (Symantec Messaging Gateway) with SMTP id 3E.C5.09595.E0456116; Fri, 13 Aug 2021 20:14:22 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas5p1.samsung.com (KnoxPortal) with ESMTPA id 20210813101459epcas5p19cf9edbb414726886b9d3a5a140fc706~a1iv85FCh1559815598epcas5p14; Fri, 13 Aug 2021 10:14:59 +0000 (GMT) Received: from epsmgms1p1new.samsung.com (unknown [182.195.42.41]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20210813101459epsmtrp13867b51586e3e40f9563c52621175783~a1iv74HBh0616806168epsmtrp1d; Fri, 13 Aug 2021 10:14:59 +0000 (GMT) Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p1new.samsung.com (Symantec Messaging Gateway) with SMTP id 28.28.08394.32646116; Fri, 13 Aug 2021 19:14:59 +0900 (KST) Received: from test.sa.corp.samsungelectronics.net (unknown [107.108.56.58]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20210813101456epsmtip1efb374a8e9a6c7c9a42f3fe1133daa44~a1itaaONI0696606966epsmtip1W; Fri, 13 Aug 2021 10:14:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout3.samsung.com 20210813111432epoutp0354863bf182e71de75c86b369a9616057~a2WvT-r213215232152epoutp03W DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1628853272; bh=5TvCTJkq+K+NvMZ1O+L8URFjZ65DiKdCe/NNBPOfrkk=; h=From:To:Cc:Subject:Date:References:From; b=hZziypMDgFRMUo2/XB+V+fdt3wi466sVtR+UplhXBncvp0ANoFiAVpwId+Dh/2QpF Za099DYU74VuosJ4pbjeLN/AofQ1PVgwNxeT2d2wFSnjlRM8Om5SF1I+ydx2xgwTnA rPT8Wo31LqJ4y6LmdMaYMe5JoFvHnq2MJnNGuYzw= X-AuditID: b6c32a4a-ed5ff7000000257b-bc-6116540eedc6 From: Naveen To: qemu-devel@nongnu.org Subject: [RFC PATCH v1] Adding Support for namespace management Date: Fri, 13 Aug 2021 15:02:22 +0530 Message-Id: <1628847142-24943-1-git-send-email-naveen.n1@samsung.com> X-Mailer: git-send-email 1.8.3.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAJsWRmVeSWpSXmKPExsWy7bCmhi5fiFiiQfssGYvXO48zW3z8e5bR 4u3XB2wWV/afZ7TYf/Abq8XS+foWJxv3sFpMOnSN0WLJxVSL+cueslvMu6Vs0fhkN7vF9Z+P 2C2uTFnEbDHrXTubxfHeHSwWe75sZLV4Pek/q4OQx49z7Wwe53acZ/fYtKqTzWPzknqPJ9c2 M3m833eVzaNvyyrGAPaobJuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxU WyUXnwBdt8wcoCeUFMoSc0qBQgGJxcVK+nY2RfmlJakKGfnFJbZKqQUpOQUmBXrFibnFpXnp enmpJVaGBgZGpkCFCdkZczofshd8r6s4emYqWwPj7pguRk4OCQETiemHr7F0MXJxCAnsZpSY 1fWVHcL5xCjx/toqVgjnG6PExV+zmWFaFtzYwwiR2MsocXX6W6j+RiaJ9rctbCBVbAIqEtP3 ngCzRQQkJX53nWYGKWIWmMws8Xf6AaAODg5hAXuJy22SICaLgKpE/x+wcl4BV4kHWx4xQixT kJjy8D1Yq4RAJ4dE9+rX7BAJF4kFm5ewQNjCEq+Ob4GKS0m87G+DsoslLvT2s0A0NzBKPPq2 AarBXuLinr9MIIuZBTQl1u/ShwjLSkw9tY4JxGYW4JPo/f2ECSLOK7Fj3hOwcgkBZYnzq7kh TEmJc9OTISo8JGav/A12spBArMSdW8tZJzDKzkKYv4CRcRWjZGpBcW56arFpgVFeajk8npLz czcxgpOmltcOxocPPugdYmTiYDzEKMHBrCTCWywslijEm5JYWZValB9fVJqTWnyI0RQYYhOZ pUST84FpO68k3tDE0sDEzMzMxNLYzFBJnJc9/muCkEB6YklqdmpqQWoRTB8TB6dUA1PXpjRr PzW/5/tsYrPc50fYb/Jse8j0tO48w3Wm6An2z54e54+eduzXaieF0t/N8WVHnnYK/VN+4qCn oMmg6HO1oXG59I6llzb/LjOb8ddrr59V4tc4L2fZJeUb9Ke1+nxMS37mc9LWPa5VbM6MH3LB cXHT3z37vk/r2o79T8/0fteuFfuzc1/nTA5/uc2PpS7YiXotSjuWta9n7Wvv/Xq7NT+wLoq8 rqXK/nYnd4SAtWFP6fH2GuaMpwYr9l40b9zY1HOxenXwvXtpd5Yem6uW3KlUkrhdu9SwdVfz SjmjC7Fyb8+8U7R5ceaOjvXmw7+vvSgJrnml9YjT7tPc0rIPZ64e9E6r+7mxIto6eKISS3FG oqEWc1FxIgBwDyTzIwQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrDLMWRmVeSWpSXmKPExsWy7bCSnK6ym1iiweZfMhavdx5ntvj49yyj xduvD9gsruw/z2ix/+A3Voul8/UtTjbuYbWYdOgao8WSi6kW85c9ZbeYd0vZovHJbnaL6z8f sVtcmbKI2WLWu3Y2i+O9O1gs9nzZyGrxetJ/Vgchjx/n2tk8zu04z+6xaVUnm8fmJfUeT65t ZvJ4v+8qm0ffllWMAexRXDYpqTmZZalF+nYJXBlzOh+yF3yvqzh6ZipbA+PumC5GTg4JAROJ BTf2MHYxcnEICexmlFj8qZkNIiEpseHvViYIW1hi5b/n7BBF/xklJn4AcTg52ARUJKbvPQHW IALU8LvrNDNIEbPASmaJtte9QGM5OIQF7CUut0mCmCwCqhL9f8DKeQVcJR5secQIMV9BYsrD 98wTGHkWMDKsYpRMLSjOTc8tNiwwzEst1ytOzC0uzUvXS87P3cQIDmAtzR2M21d90DvEyMTB eIhRgoNZSYS3WFgsUYg3JbGyKrUoP76oNCe1+BCjNAeLkjjvha6T8UIC6YklqdmpqQWpRTBZ Jg5OqQamau2ZqaJvl4n97dgrL9Kb8XLDQ8kJG4yzRI/kf33ewmDr8bvk4l2r1oslPzI9qsrW OqeHdKc9XObj88VMsV9X029BnbsD992L4uKespLX85QzfDXOH7mwRzP2XXWZJbNEd8n2W7dT E1UEnzjFL1Nv6nyb29l5xOPi2xUFl5pvX14v2TDjpONLNb+Pi9Pvygb9MrjGYGsnyH/kv87U PQoKpy06u6IfHe88dCC6a/nGG6/SGw5dtb51e/dBuYI5c6zW2csdLV605B57hctX9Udd/1fs Nmt9spC117nglnztW9cVei3q0tyXOdP4Q7ft4VrDdLht76KjSwyfTvdh4O5xCXyWk35PcFHH +xkVU/4psRRnJBpqMRcVJwIAm6ytL88CAAA= X-CMS-MailID: 20210813101459epcas5p19cf9edbb414726886b9d3a5a140fc706 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-Sendblock-Type: REQ_APPROVE CMS-TYPE: 105P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20210813101459epcas5p19cf9edbb414726886b9d3a5a140fc706 References: 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: pass client-ip=203.254.224.33; envelope-from=naveen.n1@samsung.com; helo=mailout3.samsung.com X-Spam_score_int: -77 X-Spam_score: -7.8 X-Spam_bar: ------- X-Spam_report: (-7.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.701, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 13 Aug 2021 09:13:30 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fam@euphon.net, kwolf@redhat.com, anuj.singh@samsung.com, Naveen , jg123.choi@samsung.com, qemu-block@nongnu.org, k.jensen@samsung.com, anaidu.gollu@samsung.com, d.palani@samsung.com, linux-nvme@lists.infradead.org, mreitz@redhat.com, its@irrelevant.dk, stefanha@redhat.com, p.kalghatgi@samsung.com, kbusch@kernel.org, prakash.v@samsung.com, raphel.david@samsung.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1628860508034100001 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 This patch supports namespace management : create and delete operations. This patch has been tested with the following command and size of image file for unallocated namespaces is taken as 0GB. ns_create will look into the list of unallocated namespaces and it will initialize the same and=20 return the nsid of the same. A new mandatory field has been added called tnvmcap and we have ensured that the total capacity of namespace created does not exceed tnvmcap -device nvme-subsys,id=3Dsubsys0,tnvmcap=3D8 -device nvme,serial=3Dfoo,id=3Dnvme0,subsys=3Dsubsys0 -device nvme,serial=3Dbar,id=3Dnvme1,subsys=3Dsubsys0 -drive id=3Dns1,file=3Dns1.img,if=3Dnone -device nvme-ns,drive=3Dns1,bus=3Dnvme0,nsid=3D1,zoned=3Dfalse,shared=3Dtrue -drive id=3Dns2,file=3Dns2.img,if=3Dnone -device nvme-ns,drive=3Dns2,bus=3Dnvme0,nsid=3D2,zoned=3Dfalse,shared=3Dtrue -drive id=3Dns3,file=3Dns3.img,if=3Dnone -device nvme-ns,drive=3Dns3,bus=3Dnvme0,nsid=3D3,zoned=3Dfalse,shared=3Dtrue -drive id=3Dns4,file=3Dns4.img,if=3Dnone -device nvme-ns,drive=3Dns4,bus=3Dnvme0,nsid=3D4,zoned=3Dfalse,shared=3Dtrue Please review and suggest if any changes are required. Signed-off-by: Naveen Nagar Reviewed-by: Klaus Jensen Reviewed-by: Padmakar Kalghatgi Reviewed-by: Gollu Appalanaidu Reviewed-by: Jaegyu Choi --- hw/nvme/ctrl.c | 250 +++++++++++++++++++++++++++++++++++++++++-- hw/nvme/ns.c | 14 ++- hw/nvme/nvme.h | 6 +- hw/nvme/subsys.c | 3 + include/block/nvme.h | 18 +++- 5 files changed, 272 insertions(+), 19 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 6baf9e0420..4be23a3092 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -219,6 +219,7 @@ static const uint32_t nvme_cse_acs[256] =3D { [NVME_ADM_CMD_SET_FEATURES] =3D NVME_CMD_EFF_CSUPP, [NVME_ADM_CMD_GET_FEATURES] =3D NVME_CMD_EFF_CSUPP, [NVME_ADM_CMD_ASYNC_EV_REQ] =3D NVME_CMD_EFF_CSUPP, + [NVME_ADM_CMD_NS_MANAGEMENT] =3D NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_= NIC, [NVME_ADM_CMD_NS_ATTACHMENT] =3D NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_= NIC, [NVME_ADM_CMD_FORMAT_NVM] =3D NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_= LBCC, }; @@ -4445,6 +4446,30 @@ static uint16_t nvme_identify_ctrl_csi(NvmeCtrl *n, = NvmeRequest *req) return nvme_c2h(n, id, sizeof(id), req); } =20 +static uint16_t nvme_identify_ns_common(NvmeCtrl *n, NvmeRequest *req) +{ + NvmeIdNs id_ns =3D {}; + + id_ns.nsfeat |=3D (0x4 | 0x10); + id_ns.dpc =3D 0x1f; + + NvmeLBAF lbaf[16] =3D { + [0] =3D {.ds =3D 9}, + [1] =3D {.ds =3D 9, .ms =3D 8}, + [2] =3D {.ds =3D 9, .ms =3D 16}, + [3] =3D {.ds =3D 9, .ms =3D 64}, + [4] =3D {.ds =3D 12}, + [5] =3D {.ds =3D 12, .ms =3D 8}, + [6] =3D {.ds =3D 12, .ms =3D 16}, + [7] =3D {.ds =3D 12, .ms =3D 64}, + }; + + memcpy(&id_ns.lbaf, &lbaf, sizeof(lbaf)); + id_ns.nlbaf =3D 7; + + return nvme_c2h(n, (uint8_t *)&id_ns, sizeof(NvmeIdNs), req); +} + static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req, bool activ= e) { NvmeNamespace *ns; @@ -4453,8 +4478,10 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRe= quest *req, bool active) =20 trace_pci_nvme_identify_ns(nsid); =20 - if (!nvme_nsid_valid(n, nsid) || nsid =3D=3D NVME_NSID_BROADCAST) { + if (!nvme_nsid_valid(n, nsid)) { return NVME_INVALID_NSID | NVME_DNR; + } else if (nsid =3D=3D NVME_NSID_BROADCAST) { + return nvme_identify_ns_common(n, req); } =20 ns =3D nvme_ns(n, nsid); @@ -5184,6 +5211,195 @@ static void nvme_select_iocs_ns(NvmeCtrl *n, NvmeNa= mespace *ns) } } =20 +static int nvme_blk_truncate(BlockBackend *blk, size_t len, Error **errp) +{ + int ret; + uint64_t perm, shared_perm; + + blk_get_perm(blk, &perm, &shared_perm); + + ret =3D blk_set_perm(blk, perm | BLK_PERM_RESIZE, shared_perm, errp); + if (ret < 0) { + return ret; + } + + ret =3D blk_truncate(blk, len, false, PREALLOC_MODE_OFF, 0, errp); + if (ret < 0) { + return ret; + } + + ret =3D blk_set_perm(blk, perm, shared_perm, errp); + if (ret < 0) { + return ret; + } + + return 0; +} + +static uint32_t nvme_allocate_nsid(NvmeCtrl *n) +{ + uint32_t nsid =3D 0; + for (int i =3D 1; i <=3D NVME_MAX_NAMESPACES; i++) { + if (nvme_ns(n, i) || nvme_subsys_ns(n->subsys, i)) { + continue; + } + + nsid =3D i; + return nsid; + } + return nsid; +} + +static uint16_t nvme_namespace_create(NvmeCtrl *n, NvmeRequest *req) +{ + uint32_t ret; + NvmeIdNs id_ns_host; + NvmeSubsystem *subsys =3D n->subsys; + Error *err =3D NULL; + uint8_t flbas_host; + uint64_t ns_size; + int lba_index; + NvmeNamespace *ns; + NvmeCtrl *ctrl; + NvmeIdNs *id_ns; + + ret =3D nvme_h2c(n, (uint8_t *)&id_ns_host, sizeof(id_ns_host), req); + if (ret) { + return ret; + } + + if (id_ns_host.ncap < id_ns_host.nsze) { + return NVME_THIN_PROVISION_NO_SUPP | NVME_DNR; + } else if (id_ns_host.ncap > id_ns_host.nsze) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + if (!id_ns_host.nsze) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + if (QSLIST_EMPTY(&subsys->unallocated_namespaces)) { + return NVME_NS_ID_UNAVAILABLE; + } + + ns =3D QSLIST_FIRST(&subsys->unallocated_namespaces); + id_ns =3D &ns->id_ns; + flbas_host =3D (id_ns_host.flbas) & (0xF); + + if (flbas_host > id_ns->nlbaf) { + return NVME_INVALID_FORMAT | NVME_DNR; + } + + ret =3D nvme_ns_setup(ns, &err); + if (ret) { + return ret; + } + + id_ns->flbas =3D id_ns_host.flbas; + id_ns->dps =3D id_ns_host.dps; + id_ns->nmic =3D id_ns_host.nmic; + + lba_index =3D NVME_ID_NS_FLBAS_INDEX(id_ns->flbas); + ns_size =3D id_ns_host.nsze * ((1 << id_ns->lbaf[lba_index].ds) + + (id_ns->lbaf[lba_index].ms)); + id_ns->nvmcap =3D ns_size; + + if (ns_size > n->id_ctrl.unvmcap) { + return NVME_NS_INSUFF_CAP; + } + + ret =3D nvme_blk_truncate(ns->blkconf.blk, id_ns->nvmcap, &err); + if (ret) { + return ret; + } + + ns->size =3D blk_getlength(ns->blkconf.blk); + nvme_ns_init_format(ns); + + ns->params.nsid =3D nvme_allocate_nsid(n); + if (!ns->params.nsid) { + return NVME_NS_ID_UNAVAILABLE; + } + subsys->namespaces[ns->params.nsid] =3D ns; + + for (int cntlid =3D 0; cntlid < ARRAY_SIZE(n->subsys->ctrls); cntlid++= ) { + ctrl =3D nvme_subsys_ctrl(n->subsys, cntlid); + if (ctrl) { + ctrl->id_ctrl.unvmcap -=3D le64_to_cpu(ns->size); + } + } + + stl_le_p(&req->cqe.result, ns->params.nsid); + QSLIST_REMOVE_HEAD(&subsys->unallocated_namespaces, entry); + return NVME_SUCCESS; +} + +static void nvme_namespace_delete(NvmeCtrl *n, NvmeNamespace *ns, uint32_t= nsid) +{ + NvmeCtrl *ctrl; + NvmeSubsystem *subsys =3D n->subsys; + + subsys->namespaces[nsid] =3D NULL; + QSLIST_INSERT_HEAD(&subsys->unallocated_namespaces, ns, entry); + + for (int cntlid =3D 0; cntlid < ARRAY_SIZE(n->subsys->ctrls); cntlid++= ) { + ctrl =3D nvme_subsys_ctrl(n->subsys, cntlid); + if (ctrl) { + ctrl->id_ctrl.unvmcap +=3D le64_to_cpu(ns->size); + if (nvme_ns(ctrl, nsid)) { + nvme_detach_ns(ctrl, ns, nsid); + } + nvme_ns_attr_changed_aer(ctrl, nsid); + } + } +} + +static uint16_t nvme_ns_management(NvmeCtrl *n, NvmeRequest *req) +{ + uint32_t dw10 =3D le32_to_cpu(req->cmd.cdw10); + uint8_t sel =3D dw10 & 0x7; + uint32_t nsid =3D le32_to_cpu(req->cmd.nsid); + NvmeNamespace *ns; + + if (!n->subsys) { + return NVME_INVALID_FIELD | NVME_DNR; + } + + switch (sel) { + case NVME_NS_MANAGEMENT_CREATE: + if (nsid) { + return NVME_INVALID_FIELD | NVME_DNR; + } + return nvme_namespace_create(n, req); + case NVME_NS_MANAGEMENT_DELETE: + if (nsid !=3D NVME_NSID_BROADCAST && !nvme_nsid_valid(n, nsid)) { + return NVME_INVALID_NSID | NVME_DNR; + } + if (nsid =3D=3D NVME_NSID_BROADCAST) { + uint32_t i; + + for (i =3D 1; i <=3D NVME_MAX_NAMESPACES; i++) { + ns =3D nvme_subsys_ns(n->subsys, i); + if (!ns) { + continue; + } + nvme_namespace_delete(n, ns, i); + } + return NVME_SUCCESS; + } else { + ns =3D nvme_subsys_ns(n->subsys, nsid); + if (!ns) { + return NVME_INVALID_FIELD | NVME_DNR; + } + nvme_namespace_delete(n, ns, nsid); + return NVME_SUCCESS; + } + + default: + return NVME_INVALID_FIELD | NVME_DNR; + } +} + static uint16_t nvme_ns_attachment(NvmeCtrl *n, NvmeRequest *req) { NvmeNamespace *ns; @@ -5239,22 +5455,14 @@ static uint16_t nvme_ns_attachment(NvmeCtrl *n, Nvm= eRequest *req) if (!nvme_ns(ctrl, nsid)) { return NVME_NS_NOT_ATTACHED | NVME_DNR; } - - ctrl->namespaces[nsid] =3D NULL; - ns->attached--; - - nvme_update_dmrsl(ctrl); + nvme_detach_ns(ctrl, ns, nsid); } =20 /* * Add namespace id to the changed namespace id list for event cle= aring * via Get Log Page command. */ - if (!test_and_set_bit(nsid, ctrl->changed_nsids)) { - nvme_enqueue_event(ctrl, NVME_AER_TYPE_NOTICE, - NVME_AER_INFO_NOTICE_NS_ATTR_CHANGED, - NVME_LOG_CHANGED_NSLIST); - } + nvme_ns_attr_changed_aer(ctrl, nsid); } =20 return NVME_SUCCESS; @@ -5487,6 +5695,8 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeReque= st *req) return nvme_get_feature(n, req); case NVME_ADM_CMD_ASYNC_EV_REQ: return nvme_aer(n, req); + case NVME_ADM_CMD_NS_MANAGEMENT: + return nvme_ns_management(n, req); case NVME_ADM_CMD_NS_ATTACHMENT: return nvme_ns_attachment(n, req); case NVME_ADM_CMD_FORMAT_NVM: @@ -6471,6 +6681,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pc= i_dev) =20 if (n->subsys) { id->cmic |=3D NVME_CMIC_MULTI_CTRL; + id->tnvmcap =3D n->subsys->params.tnvmcap * GiB; + id->unvmcap =3D n->subsys->params.tnvmcap * GiB; } =20 NVME_CAP_SET_MQES(cap, 0x7ff); @@ -6518,6 +6730,22 @@ void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns) BDRV_REQUEST_MAX_BYTES / nvme_l2b(ns, 1)); } =20 +void nvme_detach_ns(NvmeCtrl *n, NvmeNamespace *ns, uint32_t nsid) +{ + n->namespaces[nsid] =3D NULL; + ns->attached--; + nvme_update_dmrsl(n); +} + +void nvme_ns_attr_changed_aer(NvmeCtrl *n, uint32_t nsid) +{ + if (!test_and_set_bit(nsid, n->changed_nsids)) { + nvme_enqueue_event(n, NVME_AER_TYPE_NOTICE, + NVME_AER_INFO_NOTICE_NS_ATTR_CHANGED, + NVME_LOG_CHANGED_NSLIST); + } +} + static void nvme_realize(PCIDevice *pci_dev, Error **errp) { NvmeCtrl *n =3D NVME(pci_dev); diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index b7cf1494e7..c2b8c82024 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -402,10 +402,6 @@ int nvme_ns_setup(NvmeNamespace *ns, Error **errp) return -1; } =20 - if (nvme_ns_init_blk(ns, errp)) { - return -1; - } - if (nvme_ns_init(ns, errp)) { return -1; } @@ -481,6 +477,15 @@ static void nvme_ns_realize(DeviceState *dev, Error **= errp) } } =20 + if (nvme_ns_init_blk(ns, errp)) { + return; + } + + if (!ns->size) { + QSLIST_INSERT_HEAD(&subsys->unallocated_namespaces, ns, entry); + return; + } + if (nvme_ns_setup(ns, errp)) { return; } @@ -519,6 +524,7 @@ static void nvme_ns_realize(DeviceState *dev, Error **e= rrp) =20 if (ctrl) { nvme_attach_ns(ctrl, ns); + ctrl->id_ctrl.unvmcap -=3D le64_to_cpu(ns->size); } } =20 diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 83ffabade4..e1e4ab8a01 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -51,9 +51,11 @@ typedef struct NvmeSubsystem { =20 NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS]; NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; + QSLIST_HEAD(, NvmeNamespace) unallocated_namespaces; =20 struct { char *nqn; + uint64_t tnvmcap; } params; } NvmeSubsystem; =20 @@ -130,7 +132,7 @@ typedef struct NvmeNamespace { uint16_t status; int attached; =20 - QTAILQ_ENTRY(NvmeNamespace) entry; + QSLIST_ENTRY(NvmeNamespace) entry; =20 NvmeIdNsZoned *id_ns_zoned; NvmeZone *zone_array; @@ -495,6 +497,8 @@ static inline uint16_t nvme_cid(NvmeRequest *req) } =20 void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns); +void nvme_detach_ns(NvmeCtrl *n, NvmeNamespace *ns, uint32_t nsid); +void nvme_ns_attr_changed_aer(NvmeCtrl *n, uint32_t nsid); uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len, NvmeTxDirection dir, NvmeRequest *req); uint16_t nvme_bounce_mdata(NvmeCtrl *n, uint8_t *ptr, uint32_t len, diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 93c35950d6..e30bfbca81 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -53,11 +53,14 @@ static void nvme_subsys_realize(DeviceState *dev, Error= **errp) qbus_create_inplace(&subsys->bus, sizeof(NvmeBus), TYPE_NVME_BUS, dev, dev->id); =20 + QSLIST_INIT(&subsys->unallocated_namespaces); + nvme_subsys_setup(subsys); } =20 static Property nvme_subsystem_props[] =3D { DEFINE_PROP_STRING("nqn", NvmeSubsystem, params.nqn), + DEFINE_PROP_SIZE("tnvmcap", NvmeSubsystem, params.tnvmcap, 0), DEFINE_PROP_END_OF_LIST(), }; =20 diff --git a/include/block/nvme.h b/include/block/nvme.h index 77aae01174..8a8ca6753b 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -592,6 +592,7 @@ enum NvmeAdminCommands { NVME_ADM_CMD_SET_FEATURES =3D 0x09, NVME_ADM_CMD_GET_FEATURES =3D 0x0a, NVME_ADM_CMD_ASYNC_EV_REQ =3D 0x0c, + NVME_ADM_CMD_NS_MANAGEMENT =3D 0x0d, NVME_ADM_CMD_ACTIVATE_FW =3D 0x10, NVME_ADM_CMD_DOWNLOAD_FW =3D 0x11, NVME_ADM_CMD_NS_ATTACHMENT =3D 0x15, @@ -882,6 +883,9 @@ enum NvmeStatusCodes { NVME_FEAT_NOT_CHANGEABLE =3D 0x010e, NVME_FEAT_NOT_NS_SPEC =3D 0x010f, NVME_FW_REQ_SUSYSTEM_RESET =3D 0x0110, + NVME_NS_INSUFF_CAP =3D 0x0115, + NVME_THIN_PROVISION_NO_SUPP =3D 0x011b, + NVME_NS_ID_UNAVAILABLE =3D 0x0116, NVME_NS_ALREADY_ATTACHED =3D 0x0118, NVME_NS_PRIVATE =3D 0x0119, NVME_NS_NOT_ATTACHED =3D 0x011a, @@ -1056,8 +1060,10 @@ typedef struct QEMU_PACKED NvmeIdCtrl { uint16_t mtfa; uint32_t hmpre; uint32_t hmmin; - uint8_t tnvmcap[16]; - uint8_t unvmcap[16]; + uint64_t tnvmcap; + uint64_t tnvmcap_u; + uint64_t unvmcap; + uint64_t unvmcap_u; uint32_t rpmbs; uint16_t edstt; uint8_t dsto; @@ -1154,6 +1160,11 @@ enum NvmeIdCtrlCmic { NVME_CMIC_MULTI_CTRL =3D 1 << 1, }; =20 +enum NvmeNsManagementOperation { + NVME_NS_MANAGEMENT_CREATE =3D 0x0, + NVME_NS_MANAGEMENT_DELETE =3D 0x1, +}; + #define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf) #define NVME_CTRL_SQES_MAX(sqes) (((sqes) >> 4) & 0xf) #define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf) @@ -1285,7 +1296,8 @@ typedef struct QEMU_PACKED NvmeIdNs { uint16_t nabo; uint16_t nabspf; uint16_t noiob; - uint8_t nvmcap[16]; + uint64_t nvmcap; + uint64_t nvmcap_u; uint16_t npwg; uint16_t npwa; uint16_t npdg; --=20 2.17.1