From nobody Tue May 21 04:59:00 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 162938207387649.32369171726839; Thu, 19 Aug 2021 07:07:53 -0700 (PDT) Received: from localhost ([::1]:32852 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mGii0-0007Cl-E7 for importer@patchew.org; Thu, 19 Aug 2021 10:07:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50758) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mGigl-000537-24 for qemu-devel@nongnu.org; Thu, 19 Aug 2021 10:06:35 -0400 Received: from mailout2.samsung.com ([203.254.224.25]:58444) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mGigh-0001xh-So for qemu-devel@nongnu.org; Thu, 19 Aug 2021 10:06:34 -0400 Received: from epcas5p3.samsung.com (unknown [182.195.41.41]) by mailout2.samsung.com (KnoxPortal) with ESMTP id 20210819140620epoutp023f64cf18b776de9e0a57285ef1259278~cukdAG0FJ1504315043epoutp025 for ; Thu, 19 Aug 2021 14:06:20 +0000 (GMT) Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas5p1.samsung.com (KnoxPortal) with ESMTP id 20210819140619epcas5p11f33ea190bfda197598f477ca6917c20~cukbwIHX81389313893epcas5p1E; Thu, 19 Aug 2021 14:06:19 +0000 (GMT) Received: from epsmges5p2new.samsung.com (unknown [182.195.38.178]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4Gr64g1Fx3z4x9Pv; Thu, 19 Aug 2021 14:06:11 +0000 (GMT) Received: from epcas5p4.samsung.com ( [182.195.41.42]) by epsmges5p2new.samsung.com (Symantec Messaging Gateway) with SMTP id 1D.87.09595.3556E116; Thu, 19 Aug 2021 23:06:11 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas5p1.samsung.com (KnoxPortal) with ESMTPA id 20210819135248epcas5p1fcc9f399f16a5336e6af004170a0eea4~cuYpOY8tG2371923719epcas5p1E; Thu, 19 Aug 2021 13:52:48 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20210819135248epsmtrp197b3ace4dadfd6b09aa9353e9d7856c6~cuYpMoSyl1382913829epsmtrp1T; Thu, 19 Aug 2021 13:52:48 +0000 (GMT) Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id B7.41.32548.0326E116; Thu, 19 Aug 2021 22:52:48 +0900 (KST) Received: from test.sa.corp.samsungelectronics.net (unknown [107.108.56.58]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20210819135245epsmtip1375a3dc8c7ef9a2f6126769f1d0a1999~cuYmJAw7o0955609556epsmtip1f; Thu, 19 Aug 2021 13:52:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.samsung.com 20210819140620epoutp023f64cf18b776de9e0a57285ef1259278~cukdAG0FJ1504315043epoutp025 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1629381980; bh=w/Yl9BE+N06IquYHF1Bsc0L35HQsV0eIUuRcSc0QbVk=; h=From:To:Cc:Subject:Date:References:From; b=B+LPc+uniT1RsHYWRE7/PICPjtYO8sILFk33oLcUoUqJpwpkGueqUiAGEW9aQeNvz YSpNoAdV70KVCznwLbHGKFCTxDHPoH0hnHz7NTfrsryK0f8woDRPKGj3jlVHxbZ5IK hH1Chc0NopsQzqyqNvvOMaP9+5wg8yp0M5/SYzrc= X-AuditID: b6c32a4a-eebff7000000257b-8a-611e65535404 From: Naveen Nagar To: qemu-devel@nongnu.org Subject: [RFC PATCH v2] hw/nvme:Adding Support for namespace management Date: Thu, 19 Aug 2021 18:39:57 +0530 Message-Id: <1629378597-30480-1-git-send-email-naveen.n1@samsung.com> X-Mailer: git-send-email 1.8.3.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprEJsWRmVeSWpSXmKPExsWy7bCmlm5wqlyiwcofLBavdx5ntvj49yyj xduvD9gsruw/z2ix/+A3Voul8/UtTjbuYbWYdOgao8WSi6kW85c9ZbeYd0vZovHJbnaL6z8f sVtcmbKI2WLWu3Y2i+O9O1gs9nzZyGrxetJ/Vgchjx/n2tk8zu04z+6xaVUnm8fmJfUeT65t ZvJ4v+8qm0ffllWMAexR2TYZqYkpqUUKqXnJ+SmZeem2St7B8c7xpmYGhrqGlhbmSgp5ibmp tkouPgG6bpk5QE8oKZQl5pQChQISi4uV9O1sivJLS1IVMvKLS2yVUgtScgpMCvSKE3OLS/PS 9fJSS6wMDQyMTIEKE7Iznm3axVawYSJjxbO3v5gbGD9mdDFyckgImEgcfXKJuYuRi0NIYDej xNzdZ9ggnE+MEvOe/4fKfGaU+Pl6IxNMy46VMFW7GCUmvL7PCOE0Mkns6XnPAlLFJqAl8f3q NGYQW0RAUuJ312mwUcwCk5klpv3cBJYQFnCXmPT1IjuIzSKgKvHszVOgsRwcvAKuEn8n5EBs U5CY8vA9WK+EQC+HRMf3iYwQCReJjnezmSFsYYlXx7ewQ9hSEi/726DsYokLvf0sEM0NjBKP vm1ggUjYS1zc85cJZBmzgKbE+l36EGFZiamn1oG9ySzAJ9H7+wnUy7wSO+Y9ASuXEFCWOL+a G8KUlDg3PRmiwkPi8rn9rCC2kECsxPYN0xknMMrOQpi/gJFxFaNkakFxbnpqsWmBUV5qOTym kvNzNzGCE6eW1w7Ghw8+6B1iZOJgPMQowcGsJMJ77I9sohBvSmJlVWpRfnxRaU5q8SFGU2CI TWSWEk3OB6buvJJ4QxNLAxMzMzMTS2MzQyVxXt1XMolCAumJJanZqakFqUUwfUwcnFINTK7v X5xgNWH7us2yYvp1t5cnvecmJy/TPjnFd3tY0ePXM4uPtPWtSUrdH5krWfPyJtePqTY+zuIn J7X8VQuNcFum1RRtEqJjrXbjkdUrz2ux0r0V8ztPzHz3QEjoT8L63X8vCCmWPklRvF///F3E LoF5xc8PJcTuFlRZcUR+dif7syMb6pK6Zi4Q8Jyz5vO9F4cnWq6S1j0zd9rv5W+vNhQmKkvt fpPXtNnCZH7Wqi+7WoJKbFuuhd0xl5q+hitLq4Sj/LSjaPSL9PD5xrMm8p0ymfRalEF0X4VN 4h7LJ3Wrwi5GfZ/qLzrl/p5DuQJ+HWa+K49cKTtxsdql9INwR6jqulOewmz7PGVStkQEMyix FGckGmoxFxUnAgD1oUAlJQQAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrHLMWRmVeSWpSXmKPExsWy7bCSnK5BklyiweuVOhavdx5ntvj49yyj xduvD9gsruw/z2ix/+A3Voul8/UtTjbuYbWYdOgao8WSi6kW85c9ZbeYd0vZovHJbnaL6z8f sVtcmbKI2WLWu3Y2i+O9O1gs9nzZyGrxetJ/Vgchjx/n2tk8zu04z+6xaVUnm8fmJfUeT65t ZvJ4v+8qm0ffllWMAexRXDYpqTmZZalF+nYJXBnPNu1iK9gwkbHi2dtfzA2MHzO6GDk5JARM JHasPMPWxcjFISSwg1Hi6uzLzBAJSYkNf7cyQdjCEiv/PWeHKPrPKPGkYz8bSIJNQEvi+9Vp YA0iQA2/u04zgxQxC6xklpi95hBYkbCAu8SkrxfZQWwWAVWJZ2+eAsU5OHgFXCX+TsiBWKAg MeXhe+YJjDwLGBlWMUqmFhTnpucWGxYY5aWW6xUn5haX5qXrJefnbmIEB7GW1g7GPas+6B1i ZOJgPMQowcGsJMJ77I9sohBvSmJlVWpRfnxRaU5q8SFGaQ4WJXHeC10n44UE0hNLUrNTUwtS i2CyTBycUg1M/KlZr7oTDu75dF6//+f8hzynP+738bpZPNVweYNGW7lAUmG0yfnUbzO133cs NXgrd5ldw/rj7PC/HK+KFlZ8Wrag65b3hU+nckNO/S23W2Qcp7S7V5O3IsFg3rLfp6Unhd39 om69p57/3OHeHyGCM8y2uf3mZUw5MfuF3ZfYzJNTSpeeX1AasbpGTv2zfpbRca12wb7pfnHL vRzaZkRIm8+V/ia5f/qd1tUSLhf+xjUr3+5SKvVt7VZeKtRZVDhJ9f+hFWq50f+d7ffNCZZd 8sEm9Z796U7pufZHJBZ4+qp+jyjefnyrjtQrtXM3L0XaG2zTqll1eeaHL7bXdgt/EBAIiN18 LS2nJe3gvm3RSizFGYmGWsxFxYkAhCuJydECAAA= X-CMS-MailID: 20210819135248epcas5p1fcc9f399f16a5336e6af004170a0eea4 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: 20210819135248epcas5p1fcc9f399f16a5336e6af004170a0eea4 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.25; envelope-from=naveen.n1@samsung.com; helo=mailout2.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.7, 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_H2=-0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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 , p.kalghatgi@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, kbusch@kernel.org, prakash.v@samsung.com, raphel.david@samsung.com, jg123.choi@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: 1629382078225100001 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 From: Naveen This patch supports namespace management : create and delete operations. Since v1: - Modified and moved nvme_ns_identify_common in ns.c file=20 - Added check for CSI field in NS management - Indentation fix in namespace create 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 =20 --- hw/nvme/ctrl.c | 237 +++++++++++++++++++++++++++++++++++++++++-- hw/nvme/ns.c | 61 ++++++----- hw/nvme/nvme.h | 7 +- hw/nvme/subsys.c | 3 + include/block/nvme.h | 18 +++- 5 files changed, 285 insertions(+), 41 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 6baf9e0420..992aaa7d02 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, }; @@ -4450,11 +4451,19 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeR= equest *req, bool active) NvmeNamespace *ns; NvmeIdentify *c =3D (NvmeIdentify *)&req->cmd; uint32_t nsid =3D le32_to_cpu(c->nsid); + NvmeIdNs *id_ns =3D NULL; + uint16_t ret; =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) { + id_ns =3D g_new0(NvmeIdNs, 1); + nvme_ns_identify_common(id_ns); + ret =3D nvme_c2h(n, (uint8_t *)id_ns, sizeof(NvmeIdNs), req); + g_free(id_ns); + return ret; } =20 ns =3D nvme_ns(n, nsid); @@ -5184,6 +5193,200 @@ 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); + uint8_t csi =3D le32_to_cpu(req->cmd.cdw11) >> 24; + 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; + } + if (csi =3D=3D NVME_CSI_NVM) { + return nvme_namespace_create(n, req); + } + break; + 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; + } + return NVME_INVALID_FIELD | NVME_DNR; +} + static uint16_t nvme_ns_attachment(NvmeCtrl *n, NvmeRequest *req) { NvmeNamespace *ns; @@ -5239,22 +5442,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 +5682,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 +6668,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 +6717,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..f62a695132 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -54,6 +54,30 @@ void nvme_ns_init_format(NvmeNamespace *ns) id_ns->npda =3D id_ns->npdg =3D npdg - 1; } =20 +void nvme_ns_identify_common(NvmeIdNs *id_ns) +{ + id_ns->dlfeat =3D 0x1; + + /* support DULBE and I/O optimization fields */ + id_ns->nsfeat |=3D (0x4 | 0x10); + id_ns->mc =3D NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE; + id_ns->dpc =3D 0x1f; + + static const 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; +} + static int nvme_ns_init(NvmeNamespace *ns, Error **errp) { static uint64_t ns_count; @@ -65,11 +89,7 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) ns->csi =3D NVME_CSI_NVM; ns->status =3D 0x0; =20 - ns->id_ns.dlfeat =3D 0x1; - - /* support DULBE and I/O optimization fields */ - id_ns->nsfeat |=3D (0x4 | 0x10); - + nvme_ns_identify_common(id_ns); if (ns->params.shared) { id_ns->nmic |=3D NVME_NMIC_NS_SHARED; } @@ -89,32 +109,15 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **err= p) ds =3D 31 - clz32(ns->blkconf.logical_block_size); ms =3D ns->params.ms; =20 - id_ns->mc =3D NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE; - if (ms && ns->params.mset) { id_ns->flbas |=3D NVME_ID_NS_FLBAS_EXTENDED; } =20 - id_ns->dpc =3D 0x1f; id_ns->dps =3D ns->params.pi; if (ns->params.pi && ns->params.pil) { id_ns->dps |=3D NVME_ID_NS_DPS_FIRST_EIGHT; } =20 - static const 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; - for (i =3D 0; i <=3D id_ns->nlbaf; i++) { NvmeLBAF *lbaf =3D &id_ns->lbaf[i]; if (lbaf->ds =3D=3D ds) { @@ -402,10 +405,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 +480,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 +527,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..142268f4e0 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; @@ -259,6 +261,7 @@ int nvme_ns_setup(NvmeNamespace *ns, Error **errp); void nvme_ns_drain(NvmeNamespace *ns); void nvme_ns_shutdown(NvmeNamespace *ns); void nvme_ns_cleanup(NvmeNamespace *ns); +void nvme_ns_identify_common(NvmeIdNs *id_ns); =20 typedef struct NvmeAsyncEvent { QTAILQ_ENTRY(NvmeAsyncEvent) entry; @@ -495,6 +498,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