From patchwork Mon Sep 27 05:17:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533188 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=aj45o4ZR; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=D9QNLQIP; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrcz0gcKz9sVw for ; Mon, 27 Sep 2021 15:22:59 +1000 (AEST) Received: from localhost ([::1]:39972 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUj6O-0005gz-La for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:22:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34050) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj1p-0002Yl-3b; Mon, 27 Sep 2021 01:18:13 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:51561) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj1n-0008Iv-JP; Mon, 27 Sep 2021 01:18:12 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.west.internal (Postfix) with ESMTP id 2DDF32B011FE; Mon, 27 Sep 2021 01:18:09 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 27 Sep 2021 01:18:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=5yt5X09LNjNuE xr0Bi0xN0yrJWRZcc+WYIN5acFZcVY=; b=aj45o4ZR3yL0ROLWWhyeKV3DWQWyZ 2Mp1iKNQUuQUYrkY2IJP/NoqNDEt9nzGJVcvOCc2fooMuw7Y85dwSOkhnwp0/VDO X2n07WETGAIKS0cp4WLqdGRjSkZRePWGv7zt/DFrMsxkTrF/zvaXOBZuexGLMkye phSo1S0xzigCZ4o9dFJ2zVZNezgA4nljc8hU779eQkXmWxhq8mMzkDiam5eYWEvQ xDxLsbPXyfGcg2yWR4bTEcF31lvTRdCEcUGuXUDUA+p+B0jUo90CskFg2oDkjvp/ EYh/Y/e21vHZUCDue1jyHaprp+n6IUp80C4zqSH6zgJfuX2unoOgXIL3g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=5yt5X09LNjNuExr0Bi0xN0yrJWRZcc+WYIN5acFZcVY=; b=D9QNLQIP He2k3A2upN5XhiGdqui+1Hm4LyDLPWrBGNOi3ZIp4xYHi7/NTFEhs24xSQgf7U98 RvPCSHmoVIY/LvehBhG8WO7Y8G5GylJefnmP2TT0jcF/V2Pg4Wji+C7U5uDUU/Bf 6b3XKfSX8tOoDdqlhLP0JVphLP8ljDQYGHdkXZQ1Pfh8z910F07+4DXxWG6Q889N HovDJNhoeopxWuKPhctZqXvUx2L+aeVrc9eBzvOPoL6tLtD2rrUrh+ymLfzj3PdS s71cZiDRLYQNzYPtWO+x7iRWBepF5qg2lhSZWOSuZlCuOKIB4/ZOEXChjK7L6c2H 7ppR1U/i+OrBZw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:06 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 01/16] hw/nvme: reattach subsystem namespaces on hotplug Date: Mon, 27 Sep 2021 07:17:44 +0200 Message-Id: <20210927051759.447305-2-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Hannes Reinecke With commit 5ffbaeed16 ("hw/nvme: fix controller hot unplugging") namespaces get moved from the controller to the subsystem if one is specified. That keeps the namespaces alive after a controller hot-unplug, but after a controller hotplug we have to reconnect the namespaces from the subsystem to the controller. Fixes: 5ffbaeed16 ("hw/nvme: fix controller hot unplugging") Cc: Klaus Jensen Signed-off-by: Hannes Reinecke [k.jensen: only attach to shared and non-detached namespaces] Signed-off-by: Klaus Jensen --- hw/nvme/subsys.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 93c35950d69d..6b2e4c975f5b 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -14,7 +14,7 @@ int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp) { NvmeSubsystem *subsys = n->subsys; - int cntlid; + int cntlid, nsid; for (cntlid = 0; cntlid < ARRAY_SIZE(subsys->ctrls); cntlid++) { if (!subsys->ctrls[cntlid]) { @@ -29,12 +29,20 @@ int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp) subsys->ctrls[cntlid] = n; + for (nsid = 1; nsid < ARRAY_SIZE(subsys->namespaces); nsid++) { + NvmeNamespace *ns = subsys->namespaces[nsid]; + if (ns && ns->params.shared && !ns->params.detached) { + nvme_attach_ns(n, ns); + } + } + return cntlid; } void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n) { subsys->ctrls[n->cntlid] = NULL; + n->cntlid = -1; } static void nvme_subsys_setup(NvmeSubsystem *subsys) From patchwork Mon Sep 27 05:17:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533187 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=Ep92hDIh; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=k48YgY4/; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrc60vjWz9sVw for ; Mon, 27 Sep 2021 15:22:14 +1000 (AEST) Received: from localhost ([::1]:38194 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUj5f-0004Pz-Nv for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:22:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34066) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj1t-0002cD-AW; Mon, 27 Sep 2021 01:18:18 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:49201) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj1r-0008Mj-IJ; Mon, 27 Sep 2021 01:18:17 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailnew.west.internal (Postfix) with ESMTP id 1FA402B011FD; Mon, 27 Sep 2021 01:18:13 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Mon, 27 Sep 2021 01:18:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=Ae5wCA8dhSpHI VA3VC5vqxMvJy+pmCouZ+8WyrMRKyQ=; b=Ep92hDIhmIHqjZ5bOV+/s+WOcFGsJ re00TfxY1u+mjJ+EDJN3hwDwyykQnp0SvW/MVeNDivNHLTMIDOVxfZrHIDKdUWtU XelK6ww+Z4A1nLF7afrN8qiZbjYGIbDfzzZrud12GgDw1aHRsH+yaN7F1itXwibS ZXIFvat1Et/Ii/Gopo2HlaB4I9f9rXLq4WAuP+zADb0gjl+WZMIcTbus+JbyhOzQ FGxFG7BTQ99Wsu9WY5zQvhGoYGmbwf8b9GyQg3d1fPH5wcAxtby+OOl5E1yUEgd9 Nsf1QY/IYTbuB6usSUqxAsWEN4CoGtfTBpbVDalrkAkGQGABPiotg5fpg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=Ae5wCA8dhSpHIVA3VC5vqxMvJy+pmCouZ+8WyrMRKyQ=; b=k48YgY4/ aKu6ZmkTajucL+QHx4SHyZbfLpftjUqsscAHg2dzvbj7XPpP8JOqi7M5etA9vV5n yk0Xhg7Q/zrhTBvjereRyUsIdzGdZpH5OfH2nS4lc9tC3KmKbnCIQAHuZ+hj9BbR iq7eieRjCpCpmr4fQe9qOmp+gGARg/o21InLZ0LTo80wffVl8htjzUwFQATwqsvA qEhpz2PvAzPgwj98JDby1TfQZHPOQr+QRtk/9YNyQhmODZbNEFC/2sywC6Fa2D80 iw9XgzeeW0lVBXQ6vyM9j2ULxQbIO8kEIbBdcq+9Yj7Ib80tbj8sQiKnY9Tk65VG izj0lKzUDXLb7A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:10 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 02/16] hw/nvme: change nvme-ns 'shared' default Date: Mon, 27 Sep 2021 07:17:45 +0200 Message-Id: <20210927051759.447305-3-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Change namespaces to be shared namespaces by default (parameter shared=on). Keep shared=off for older machine types. Signed-off-by: Klaus Jensen --- docs/system/devices/nvme.rst | 24 ++++++++++++++---------- hw/core/machine.c | 4 +++- hw/nvme/ns.c | 8 +------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/system/devices/nvme.rst b/docs/system/devices/nvme.rst index bff72d1c24d0..a1c0db01f6d5 100644 --- a/docs/system/devices/nvme.rst +++ b/docs/system/devices/nvme.rst @@ -110,28 +110,32 @@ multipath I/O. This will create an NVM subsystem with two controllers. Having controllers linked to an ``nvme-subsys`` device allows additional ``nvme-ns`` parameters: -``shared`` (default: ``off``) +``shared`` (default: ``on`` since 6.2) Specifies that the namespace will be attached to all controllers in the - subsystem. If set to ``off`` (the default), the namespace will remain a - private namespace and may only be attached to a single controller at a time. + subsystem. If set to ``off``, the namespace will remain a private namespace + and may only be attached to a single controller at a time. Shared namespaces + are always automatically attached to all controllers (also when controllers + are hotplugged). ``detached`` (default: ``off``) If set to ``on``, the namespace will be be available in the subsystem, but - not attached to any controllers initially. + not attached to any controllers initially. A shared namespace with this set + to ``on`` will never be automatically attached to controllers. Thus, adding .. code-block:: console -drive file=nvm-1.img,if=none,id=nvm-1 - -device nvme-ns,drive=nvm-1,nsid=1,shared=on + -device nvme-ns,drive=nvm-1,nsid=1 -drive file=nvm-2.img,if=none,id=nvm-2 - -device nvme-ns,drive=nvm-2,nsid=3,detached=on + -device nvme-ns,drive=nvm-2,nsid=3,shared=off,detached=on -will cause NSID 1 will be a shared namespace (due to ``shared=on``) that is -initially attached to both controllers. NSID 3 will be a private namespace -(i.e. only attachable to a single controller at a time) and will not be -attached to any controller initially (due to ``detached=on``). +will cause NSID 1 will be a shared namespace that is initially attached to both +controllers. NSID 3 will be a private namespace due to ``shared=off`` and only +attachable to a single controller at a time. Additionally it will not be +attached to any controller initially (due to ``detached=on``) or to hotplugged +controllers. Optional Features ================= diff --git a/hw/core/machine.c b/hw/core/machine.c index 067f42b528fd..5e2fa3e392b9 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -37,7 +37,9 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" -GlobalProperty hw_compat_6_1[] = {}; +GlobalProperty hw_compat_6_1[] = { + { "nvme-ns", "shared", "off" }, +}; const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1); GlobalProperty hw_compat_6_0[] = { diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index b7cf1494e75b..8b5f98c76180 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -465,12 +465,6 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp) "linked to an nvme-subsys device"); return; } - - if (ns->params.shared) { - error_setg(errp, "shared requires that the nvme device is " - "linked to an nvme-subsys device"); - return; - } } else { /* * If this namespace belongs to a subsystem (through a link on the @@ -532,7 +526,7 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp) static Property nvme_ns_props[] = { DEFINE_BLOCK_PROPERTIES(NvmeNamespace, blkconf), DEFINE_PROP_BOOL("detached", NvmeNamespace, params.detached, false), - DEFINE_PROP_BOOL("shared", NvmeNamespace, params.shared, false), + DEFINE_PROP_BOOL("shared", NvmeNamespace, params.shared, true), DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0), DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid), DEFINE_PROP_UINT64("eui64", NvmeNamespace, params.eui64, 0), From patchwork Mon Sep 27 05:17:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533191 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=HLgmrO/N; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=CFReqVl0; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrmV5V1Wz9t5m for ; Mon, 27 Sep 2021 15:29:30 +1000 (AEST) Received: from localhost ([::1]:49234 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjCh-0003Xj-GI for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:29:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34084) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj1y-0002f6-6I; Mon, 27 Sep 2021 01:18:22 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:50049) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj1w-0008PF-3q; Mon, 27 Sep 2021 01:18:21 -0400 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailnew.west.internal (Postfix) with ESMTP id 12FB52B011FF; Mon, 27 Sep 2021 01:18:17 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 27 Sep 2021 01:18:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=OFPUwsR06zKzt OhTZ9TubnAicq1s3vhgXzfQw83jQi4=; b=HLgmrO/NFRgVU501ILMlBxMGtIutj 8urWCjDcoPI6OhaEEqqYbIHabimXO4uVtuA9AwvOoCjDj5jd7e3S3B2Vysc0IPBN 6KknQU52Wi/LQ0yOlwR9UMK1ap9JMN1tiYXUr5ieEt495GFBIWcTGSjY/M3cwQM5 h0TvV+PULBgHuO18jMs3qpF0S0hjpjRZWKBYbw/YA8al7up3K7IfwGkaHmKKUaQm usjPSN97yNnEIV3Kne6xYWYwupHgFGqH42pzzpWh+AMNHc5XLE9QPr/jM6I55WTe 4d44T/PQYG4S+cy/feQCsh4N1SoKdqqMJUB2xQU2+cl8itkTA2cKgCpxA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=OFPUwsR06zKztOhTZ9TubnAicq1s3vhgXzfQw83jQi4=; b=CFReqVl0 UtFgi9RuWyDpe3HVRjjGXiMNy75O7/2+uVMkzgIVWv4jsinK2/S6R8Vm1xItQe43 i/ZfCNAJ/sEEq/G1FX7sjxPlDyd7G3YiKZcArtpD+olUYvhaN6XeN9dRkcMz02F9 mdGEM0iz067KPvGhkF3d0QcW6JKaXgBsGR+uE/Vp4UFUj2E86OXj+0lLiuYmJn6u 8zq1LM0dsDIvvPrrdT2kX8f4xVW/BcHgSEfpp4bwB+8jO4dSBdDpF2NmafSFABbx cECMmsvj7XkcsfypEAraXrujRG3WiW3IR+KAnyeG+SUJyH/sOws/cnMVOONBVaN/ K/MJVjDIQ3DRxg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:14 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 03/16] hw/nvme: move dif/pi prototypes into dif.h Date: Mon, 27 Sep 2021 07:17:46 +0200 Message-Id: <20210927051759.447305-4-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 1 + hw/nvme/dif.c | 1 + hw/nvme/dif.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/nvme/nvme.h | 50 ----------------------------------------------- 4 files changed, 55 insertions(+), 50 deletions(-) create mode 100644 hw/nvme/dif.h diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 2f247a9275ca..b148e1dbb148 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -163,6 +163,7 @@ #include "migration/vmstate.h" #include "nvme.h" +#include "dif.h" #include "trace.h" #define NVME_MAX_IOQPAIRS 0xffff diff --git a/hw/nvme/dif.c b/hw/nvme/dif.c index 5dbd18b2a4a5..cd0cea2b5ebd 100644 --- a/hw/nvme/dif.c +++ b/hw/nvme/dif.c @@ -13,6 +13,7 @@ #include "sysemu/block-backend.h" #include "nvme.h" +#include "dif.h" #include "trace.h" uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint8_t prinfo, uint64_t slba, diff --git a/hw/nvme/dif.h b/hw/nvme/dif.h new file mode 100644 index 000000000000..e36fea30e71e --- /dev/null +++ b/hw/nvme/dif.h @@ -0,0 +1,53 @@ +#ifndef HW_NVME_DIF_H +#define HW_NVME_DIF_H + +/* from Linux kernel (crypto/crct10dif_common.c) */ +static const uint16_t t10_dif_crc_table[256] = { + 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, + 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6, + 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6, + 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B, + 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1, + 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C, + 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C, + 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781, + 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8, + 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255, + 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925, + 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698, + 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472, + 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF, + 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF, + 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02, + 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA, + 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067, + 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17, + 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA, + 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640, + 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD, + 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D, + 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30, + 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759, + 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4, + 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394, + 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29, + 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3, + 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E, + 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E, + 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 +}; + +uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint8_t prinfo, uint64_t slba, + uint32_t reftag); +uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, + uint64_t slba); +void nvme_dif_pract_generate_dif(NvmeNamespace *ns, uint8_t *buf, size_t len, + uint8_t *mbuf, size_t mlen, uint16_t apptag, + uint32_t *reftag); +uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, + uint8_t *mbuf, size_t mlen, uint8_t prinfo, + uint64_t slba, uint16_t apptag, + uint16_t appmask, uint32_t *reftag); +uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req); + +#endif /* HW_NVME_DIF_H */ diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 83ffabade4cf..45bf96d65321 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -503,54 +503,4 @@ void nvme_rw_complete_cb(void *opaque, int ret); uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, NvmeCmd *cmd); -/* from Linux kernel (crypto/crct10dif_common.c) */ -static const uint16_t t10_dif_crc_table[256] = { - 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, - 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6, - 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6, - 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B, - 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1, - 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C, - 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C, - 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781, - 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8, - 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255, - 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925, - 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698, - 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472, - 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF, - 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF, - 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02, - 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA, - 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067, - 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17, - 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA, - 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640, - 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD, - 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D, - 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30, - 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759, - 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4, - 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394, - 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29, - 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3, - 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E, - 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E, - 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 -}; - -uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint8_t prinfo, uint64_t slba, - uint32_t reftag); -uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, - uint64_t slba); -void nvme_dif_pract_generate_dif(NvmeNamespace *ns, uint8_t *buf, size_t len, - uint8_t *mbuf, size_t mlen, uint16_t apptag, - uint32_t *reftag); -uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, - uint8_t *mbuf, size_t mlen, uint8_t prinfo, - uint64_t slba, uint16_t apptag, - uint16_t appmask, uint32_t *reftag); -uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req); - - #endif /* HW_NVME_INTERNAL_H */ From patchwork Mon Sep 27 05:17:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533194 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=LfqRLEtD; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=qVs8XNQS; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrwZ5dl0z9t5m for ; Mon, 27 Sep 2021 15:36:29 +1000 (AEST) Received: from localhost ([::1]:57700 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjJR-0000sj-5Y for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:36:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34108) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj22-0002je-De; Mon, 27 Sep 2021 01:18:26 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:52777) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj1z-0008ST-Hw; Mon, 27 Sep 2021 01:18:26 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.west.internal (Postfix) with ESMTP id 1AA612B01203; Mon, 27 Sep 2021 01:18:21 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 27 Sep 2021 01:18:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=Qai8+SSyH8cWM h10ART1TPYw7ruocVQ07FXB1VwD+gI=; b=LfqRLEtDfnM2S0f8wrVwIDQ7VkghG PtjMHSn0AZHchdGDiQGgYvwzUArqG0IcHrXvVFvJrLOrW6JAWpL98qplcra2JYrY 0v1uTbMEWvSeehUEaxSCLpoEi67Gc59+CvCk2DsmbSBF/ZgK4T7DXA5TszBuUxhh 6cGxYDB0d2sbmaVM4UKHnMPkzBRKNaPW0irclGq7cDlY50YjxE0dNCSMtWzFDaxq gyroJGAPAY+5o+fp6Sw8IcDuL4fiMlnKkcZOuSCxN6szPcoPfpsPGM2NzZZjt8V/ RFB1PXal07udzALg6y5iXuVjjRqi20jEGBiDBtQflcd32T2RX06nTagYA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=Qai8+SSyH8cWMh10ART1TPYw7ruocVQ07FXB1VwD+gI=; b=qVs8XNQS lrGqKexbIZLxfpo1bt4V3Py81nKKzEMDjkgDPEMOVcV9W5bvqTdrhWq/ZyBZgSDy nU0HnnxF5XfXsTOkmsUI7ka/qalKOt7bbhjdhSjzPQ2+aTN6CgWg1Yvlttq6ojf0 cMh7NVpe5rziy0/uZOE6Pk+WJ+TecqRGAYStbMGo3IzF0n2Foe/aZ4W/4WqInIx6 TnysrE2ev20N2lo3Ll1Gl2hhex4cazdAeD1bmMUvt8rFHiUDFHB50kyJbOFtF1+4 OvMq7O4KqAYodeJHu5obHcp5601OnRopVuyhdNnG6y/X+X1//OI9C6I1pRYn+2et CS1OSZHaxNK1Og== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgleduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:18 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 04/16] hw/nvme: move zns helpers and types into zns.h Date: Mon, 27 Sep 2021 07:17:47 +0200 Message-Id: <20210927051759.447305-5-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Move ZNS related helpers and types into zns.h. Use a common prefix (nvme_zoned or nvme_ns_zoned) for zns related functions. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 110 +++++++++++++++++++++---------------------------- hw/nvme/ns.c | 47 ++++++++++----------- hw/nvme/nvme.h | 72 -------------------------------- hw/nvme/zns.h | 97 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 157 deletions(-) create mode 100644 hw/nvme/zns.h diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index b148e1dbb148..85937f57686c 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -164,6 +164,8 @@ #include "nvme.h" #include "dif.h" +#include "zns.h" + #include "trace.h" #define NVME_MAX_IOQPAIRS 0xffff @@ -258,11 +260,11 @@ static uint16_t nvme_sqid(NvmeRequest *req) return le16_to_cpu(req->sq->sqid); } -static void nvme_assign_zone_state(NvmeNamespace *ns, NvmeZone *zone, - NvmeZoneState state) +static void nvme_zns_assign_state(NvmeNamespace *ns, NvmeZone *zone, + NvmeZoneState state) { if (QTAILQ_IN_USE(zone, entry)) { - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: QTAILQ_REMOVE(&ns->exp_open_zones, zone, entry); break; @@ -279,7 +281,7 @@ static void nvme_assign_zone_state(NvmeNamespace *ns, NvmeZone *zone, } } - nvme_set_zone_state(zone, state); + nvme_zns_set_zs(zone, state); switch (state) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: @@ -304,7 +306,8 @@ static void nvme_assign_zone_state(NvmeNamespace *ns, NvmeZone *zone, * Check if we can open a zone without exceeding open/active limits. * AOR stands for "Active and Open Resources" (see TP 4053 section 2.5). */ -static int nvme_aor_check(NvmeNamespace *ns, uint32_t act, uint32_t opn) +static int nvme_zns_aor_check(NvmeNamespace *ns, uint32_t act, + uint32_t opn) { if (ns->params.max_active_zones != 0 && ns->nr_active_zones + act > ns->params.max_active_zones) { @@ -1552,28 +1555,11 @@ static void nvme_aio_err(NvmeRequest *req, int ret) req->status = status; } -static inline uint32_t nvme_zone_idx(NvmeNamespace *ns, uint64_t slba) -{ - return ns->zone_size_log2 > 0 ? slba >> ns->zone_size_log2 : - slba / ns->zone_size; -} - -static inline NvmeZone *nvme_get_zone_by_slba(NvmeNamespace *ns, uint64_t slba) -{ - uint32_t zone_idx = nvme_zone_idx(ns, slba); - - if (zone_idx >= ns->num_zones) { - return NULL; - } - - return &ns->zone_array[zone_idx]; -} - static uint16_t nvme_check_zone_state_for_write(NvmeZone *zone) { uint64_t zslba = zone->d.zslba; - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_EMPTY: case NVME_ZONE_STATE_IMPLICITLY_OPEN: case NVME_ZONE_STATE_EXPLICITLY_OPEN: @@ -1598,7 +1584,7 @@ static uint16_t nvme_check_zone_state_for_write(NvmeZone *zone) static uint16_t nvme_check_zone_write(NvmeNamespace *ns, NvmeZone *zone, uint64_t slba, uint32_t nlb) { - uint64_t zcap = nvme_zone_wr_boundary(zone); + uint64_t zcap = nvme_zns_write_boundary(zone); uint16_t status; status = nvme_check_zone_state_for_write(zone); @@ -1621,7 +1607,7 @@ static uint16_t nvme_check_zone_write(NvmeNamespace *ns, NvmeZone *zone, static uint16_t nvme_check_zone_state_for_read(NvmeZone *zone) { - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_EMPTY: case NVME_ZONE_STATE_IMPLICITLY_OPEN: case NVME_ZONE_STATE_EXPLICITLY_OPEN: @@ -1646,10 +1632,10 @@ static uint16_t nvme_check_zone_read(NvmeNamespace *ns, uint64_t slba, uint64_t bndry, end; uint16_t status; - zone = nvme_get_zone_by_slba(ns, slba); + zone = nvme_zns_get_by_slba(ns, slba); assert(zone); - bndry = nvme_zone_rd_boundary(ns, zone); + bndry = nvme_zns_read_boundary(ns, zone); end = slba + nlb; status = nvme_check_zone_state_for_read(zone); @@ -1669,7 +1655,7 @@ static uint16_t nvme_check_zone_read(NvmeNamespace *ns, uint64_t slba, if (status) { break; } - } while (end > nvme_zone_rd_boundary(ns, zone)); + } while (end > nvme_zns_read_boundary(ns, zone)); } } @@ -1678,19 +1664,19 @@ static uint16_t nvme_check_zone_read(NvmeNamespace *ns, uint64_t slba, static uint16_t nvme_zrm_finish(NvmeNamespace *ns, NvmeZone *zone) { - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_FULL: return NVME_SUCCESS; case NVME_ZONE_STATE_IMPLICITLY_OPEN: case NVME_ZONE_STATE_EXPLICITLY_OPEN: - nvme_aor_dec_open(ns); + nvme_zns_aor_dec_open(ns); /* fallthrough */ case NVME_ZONE_STATE_CLOSED: - nvme_aor_dec_active(ns); + nvme_zns_aor_dec_active(ns); /* fallthrough */ case NVME_ZONE_STATE_EMPTY: - nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_FULL); + nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_FULL); return NVME_SUCCESS; default: @@ -1700,11 +1686,11 @@ static uint16_t nvme_zrm_finish(NvmeNamespace *ns, NvmeZone *zone) static uint16_t nvme_zrm_close(NvmeNamespace *ns, NvmeZone *zone) { - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: case NVME_ZONE_STATE_IMPLICITLY_OPEN: - nvme_aor_dec_open(ns); - nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_CLOSED); + nvme_zns_aor_dec_open(ns); + nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_CLOSED); /* fall through */ case NVME_ZONE_STATE_CLOSED: return NVME_SUCCESS; @@ -1716,18 +1702,18 @@ static uint16_t nvme_zrm_close(NvmeNamespace *ns, NvmeZone *zone) static uint16_t nvme_zrm_reset(NvmeNamespace *ns, NvmeZone *zone) { - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: case NVME_ZONE_STATE_IMPLICITLY_OPEN: - nvme_aor_dec_open(ns); + nvme_zns_aor_dec_open(ns); /* fallthrough */ case NVME_ZONE_STATE_CLOSED: - nvme_aor_dec_active(ns); + nvme_zns_aor_dec_active(ns); /* fallthrough */ case NVME_ZONE_STATE_FULL: zone->w_ptr = zone->d.zslba; zone->d.wp = zone->w_ptr; - nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_EMPTY); + nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_EMPTY); /* fallthrough */ case NVME_ZONE_STATE_EMPTY: return NVME_SUCCESS; @@ -1764,7 +1750,7 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns, int act = 0; uint16_t status; - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_EMPTY: act = 1; @@ -1774,19 +1760,19 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns, if (n->params.auto_transition_zones) { nvme_zrm_auto_transition_zone(ns); } - status = nvme_aor_check(ns, act, 1); + status = nvme_zns_aor_check(ns, act, 1); if (status) { return status; } if (act) { - nvme_aor_inc_active(ns); + nvme_zns_aor_inc_active(ns); } - nvme_aor_inc_open(ns); + nvme_zns_aor_inc_open(ns); if (flags & NVME_ZRM_AUTO) { - nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_IMPLICITLY_OPEN); + nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_IMPLICITLY_OPEN); return NVME_SUCCESS; } @@ -1797,7 +1783,7 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns, return NVME_SUCCESS; } - nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_EXPLICITLY_OPEN); + nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_EXPLICITLY_OPEN); /* fallthrough */ @@ -1826,7 +1812,7 @@ static void nvme_advance_zone_wp(NvmeNamespace *ns, NvmeZone *zone, { zone->d.wp += nlb; - if (zone->d.wp == nvme_zone_wr_boundary(zone)) { + if (zone->d.wp == nvme_zns_write_boundary(zone)) { nvme_zrm_finish(ns, zone); } } @@ -1840,7 +1826,7 @@ static void nvme_finalize_zoned_write(NvmeNamespace *ns, NvmeRequest *req) slba = le64_to_cpu(rw->slba); nlb = le16_to_cpu(rw->nlb) + 1; - zone = nvme_get_zone_by_slba(ns, slba); + zone = nvme_zns_get_by_slba(ns, slba); assert(zone); nvme_advance_zone_wp(ns, zone, nlb); @@ -2821,7 +2807,7 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) iocb->slba = le64_to_cpu(copy->sdlba); if (ns->params.zoned) { - iocb->zone = nvme_get_zone_by_slba(ns, iocb->slba); + iocb->zone = nvme_zns_get_by_slba(ns, iocb->slba); if (!iocb->zone) { status = NVME_LBA_RANGE | NVME_DNR; goto invalid; @@ -3176,7 +3162,7 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, } if (ns->params.zoned) { - zone = nvme_get_zone_by_slba(ns, slba); + zone = nvme_zns_get_by_slba(ns, slba); assert(zone); if (append) { @@ -3297,7 +3283,7 @@ static uint16_t nvme_get_mgmt_zone_slba_idx(NvmeNamespace *ns, NvmeCmd *c, return NVME_LBA_RANGE | NVME_DNR; } - *zone_idx = nvme_zone_idx(ns, *slba); + *zone_idx = nvme_zns_zidx(ns, *slba); assert(*zone_idx < ns->num_zones); return NVME_SUCCESS; @@ -3337,7 +3323,7 @@ static uint16_t nvme_offline_zone(NvmeNamespace *ns, NvmeZone *zone, { switch (state) { case NVME_ZONE_STATE_READ_ONLY: - nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_OFFLINE); + nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_OFFLINE); /* fall through */ case NVME_ZONE_STATE_OFFLINE: return NVME_SUCCESS; @@ -3349,16 +3335,16 @@ static uint16_t nvme_offline_zone(NvmeNamespace *ns, NvmeZone *zone, static uint16_t nvme_set_zd_ext(NvmeNamespace *ns, NvmeZone *zone) { uint16_t status; - uint8_t state = nvme_get_zone_state(zone); + uint8_t state = nvme_zns_zs(zone); if (state == NVME_ZONE_STATE_EMPTY) { - status = nvme_aor_check(ns, 1, 0); + status = nvme_zns_aor_check(ns, 1, 0); if (status) { return status; } - nvme_aor_inc_active(ns); + nvme_zns_aor_inc_active(ns); zone->d.za |= NVME_ZA_ZD_EXT_VALID; - nvme_assign_zone_state(ns, zone, NVME_ZONE_STATE_CLOSED); + nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_CLOSED); return NVME_SUCCESS; } @@ -3370,7 +3356,7 @@ static uint16_t nvme_bulk_proc_zone(NvmeNamespace *ns, NvmeZone *zone, op_handler_t op_hndlr, NvmeRequest *req) { uint16_t status = NVME_SUCCESS; - NvmeZoneState zs = nvme_get_zone_state(zone); + NvmeZoneState zs = nvme_zns_zs(zone); bool proc_zone; switch (zs) { @@ -3407,7 +3393,7 @@ static uint16_t nvme_do_zone_op(NvmeNamespace *ns, NvmeZone *zone, int i; if (!proc_mask) { - status = op_hndlr(ns, zone, nvme_get_zone_state(zone), req); + status = op_hndlr(ns, zone, nvme_zns_zs(zone), req); } else { if (proc_mask & NVME_PROC_CLOSED_ZONES) { QTAILQ_FOREACH_SAFE(zone, &ns->closed_zones, entry, next) { @@ -3555,7 +3541,7 @@ static void nvme_zone_reset_cb(void *opaque, int ret) while (iocb->idx < ns->num_zones) { NvmeZone *zone = &ns->zone_array[iocb->idx++]; - switch (nvme_get_zone_state(zone)) { + switch (nvme_zns_zs(zone)) { case NVME_ZONE_STATE_EMPTY: if (!iocb->all) { goto done; @@ -3682,7 +3668,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) if (all || !ns->params.zd_extension_size) { return NVME_INVALID_FIELD | NVME_DNR; } - zd_ext = nvme_get_zd_extension(ns, zone_idx); + zd_ext = nvme_zns_zde(ns, zone_idx); status = nvme_h2c(n, zd_ext, ns->params.zd_extension_size, req); if (status) { trace_pci_nvme_err_zd_extension_map_error(zone_idx); @@ -3714,7 +3700,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) static bool nvme_zone_matches_filter(uint32_t zafs, NvmeZone *zl) { - NvmeZoneState zs = nvme_get_zone_state(zl); + NvmeZoneState zs = nvme_zns_zs(zl); switch (zafs) { case NVME_ZONE_REPORT_ALL: @@ -3820,7 +3806,7 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) z->zslba = cpu_to_le64(zone->d.zslba); z->za = zone->d.za; - if (nvme_wp_is_valid(zone)) { + if (nvme_zns_wp_valid(zone)) { z->wp = cpu_to_le64(zone->d.wp); } else { z->wp = cpu_to_le64(~0ULL); @@ -3828,7 +3814,7 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) if (zra == NVME_ZONE_REPORT_EXTENDED) { if (zone->d.za & NVME_ZA_ZD_EXT_VALID) { - memcpy(buf_p, nvme_get_zd_extension(ns, zone_idx), + memcpy(buf_p, nvme_zns_zde(ns, zone_idx), ns->params.zd_extension_size); } buf_p += ns->params.zd_extension_size; diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 8b5f98c76180..471d1ddc016a 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -20,10 +20,11 @@ #include "sysemu/block-backend.h" #include "nvme.h" +#include "zns.h" + #include "trace.h" #define MIN_DISCARD_GRANULARITY (4 * KiB) -#define NVME_DEFAULT_ZONE_SIZE (128 * MiB) void nvme_ns_init_format(NvmeNamespace *ns) { @@ -164,7 +165,7 @@ static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp) return 0; } -static int nvme_ns_zoned_check_calc_geometry(NvmeNamespace *ns, Error **errp) +static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) { uint64_t zone_size, zone_cap; @@ -214,7 +215,7 @@ static int nvme_ns_zoned_check_calc_geometry(NvmeNamespace *ns, Error **errp) return 0; } -static void nvme_ns_zoned_init_state(NvmeNamespace *ns) +static void nvme_zns_init_state(NvmeNamespace *ns) { uint64_t start = 0, zone_size = ns->zone_size; uint64_t capacity = ns->num_zones * zone_size; @@ -238,7 +239,7 @@ static void nvme_ns_zoned_init_state(NvmeNamespace *ns) zone_size = capacity - start; } zone->d.zt = NVME_ZONE_TYPE_SEQ_WRITE; - nvme_set_zone_state(zone, NVME_ZONE_STATE_EMPTY); + nvme_zns_set_zs(zone, NVME_ZONE_STATE_EMPTY); zone->d.za = 0; zone->d.zcap = ns->zone_capacity; zone->d.zslba = start; @@ -253,12 +254,12 @@ static void nvme_ns_zoned_init_state(NvmeNamespace *ns) } } -static void nvme_ns_init_zoned(NvmeNamespace *ns) +static void nvme_zns_init(NvmeNamespace *ns) { NvmeIdNsZoned *id_ns_z; int i; - nvme_ns_zoned_init_state(ns); + nvme_zns_init_state(ns); id_ns_z = g_malloc0(sizeof(NvmeIdNsZoned)); @@ -298,49 +299,49 @@ static void nvme_ns_init_zoned(NvmeNamespace *ns) ns->id_ns_zoned = id_ns_z; } -static void nvme_clear_zone(NvmeNamespace *ns, NvmeZone *zone) +static void nvme_zns_clear_zone(NvmeNamespace *ns, NvmeZone *zone) { uint8_t state; zone->w_ptr = zone->d.wp; - state = nvme_get_zone_state(zone); + state = nvme_zns_zs(zone); if (zone->d.wp != zone->d.zslba || (zone->d.za & NVME_ZA_ZD_EXT_VALID)) { if (state != NVME_ZONE_STATE_CLOSED) { trace_pci_nvme_clear_ns_close(state, zone->d.zslba); - nvme_set_zone_state(zone, NVME_ZONE_STATE_CLOSED); + nvme_zns_set_zs(zone, NVME_ZONE_STATE_CLOSED); } - nvme_aor_inc_active(ns); + nvme_zns_aor_inc_active(ns); QTAILQ_INSERT_HEAD(&ns->closed_zones, zone, entry); } else { trace_pci_nvme_clear_ns_reset(state, zone->d.zslba); - nvme_set_zone_state(zone, NVME_ZONE_STATE_EMPTY); + nvme_zns_set_zs(zone, NVME_ZONE_STATE_EMPTY); } } /* * Close all the zones that are currently open. */ -static void nvme_zoned_ns_shutdown(NvmeNamespace *ns) +static void nvme_zns_shutdown(NvmeNamespace *ns) { NvmeZone *zone, *next; QTAILQ_FOREACH_SAFE(zone, &ns->closed_zones, entry, next) { QTAILQ_REMOVE(&ns->closed_zones, zone, entry); - nvme_aor_dec_active(ns); - nvme_clear_zone(ns, zone); + nvme_zns_aor_dec_active(ns); + nvme_zns_clear_zone(ns, zone); } QTAILQ_FOREACH_SAFE(zone, &ns->imp_open_zones, entry, next) { QTAILQ_REMOVE(&ns->imp_open_zones, zone, entry); - nvme_aor_dec_open(ns); - nvme_aor_dec_active(ns); - nvme_clear_zone(ns, zone); + nvme_zns_aor_dec_open(ns); + nvme_zns_aor_dec_active(ns); + nvme_zns_clear_zone(ns, zone); } QTAILQ_FOREACH_SAFE(zone, &ns->exp_open_zones, entry, next) { QTAILQ_REMOVE(&ns->exp_open_zones, zone, entry); - nvme_aor_dec_open(ns); - nvme_aor_dec_active(ns); - nvme_clear_zone(ns, zone); + nvme_zns_aor_dec_open(ns); + nvme_zns_aor_dec_active(ns); + nvme_zns_clear_zone(ns, zone); } assert(ns->nr_open_zones == 0); @@ -410,10 +411,10 @@ int nvme_ns_setup(NvmeNamespace *ns, Error **errp) return -1; } if (ns->params.zoned) { - if (nvme_ns_zoned_check_calc_geometry(ns, errp) != 0) { + if (nvme_zns_check_calc_geometry(ns, errp) != 0) { return -1; } - nvme_ns_init_zoned(ns); + nvme_zns_init(ns); } return 0; @@ -428,7 +429,7 @@ void nvme_ns_shutdown(NvmeNamespace *ns) { blk_flush(ns->blkconf.blk); if (ns->params.zoned) { - nvme_zoned_ns_shutdown(ns); + nvme_zns_shutdown(ns); } } diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 45bf96d65321..99d8b9066cc9 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -182,78 +182,6 @@ static inline bool nvme_ns_ext(NvmeNamespace *ns) return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas); } -static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone) -{ - return zone->d.zs >> 4; -} - -static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state) -{ - zone->d.zs = state << 4; -} - -static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone) -{ - return zone->d.zslba + ns->zone_size; -} - -static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone) -{ - return zone->d.zslba + zone->d.zcap; -} - -static inline bool nvme_wp_is_valid(NvmeZone *zone) -{ - uint8_t st = nvme_get_zone_state(zone); - - return st != NVME_ZONE_STATE_FULL && - st != NVME_ZONE_STATE_READ_ONLY && - st != NVME_ZONE_STATE_OFFLINE; -} - -static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns, - uint32_t zone_idx) -{ - return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size]; -} - -static inline void nvme_aor_inc_open(NvmeNamespace *ns) -{ - assert(ns->nr_open_zones >= 0); - if (ns->params.max_open_zones) { - ns->nr_open_zones++; - assert(ns->nr_open_zones <= ns->params.max_open_zones); - } -} - -static inline void nvme_aor_dec_open(NvmeNamespace *ns) -{ - if (ns->params.max_open_zones) { - assert(ns->nr_open_zones > 0); - ns->nr_open_zones--; - } - assert(ns->nr_open_zones >= 0); -} - -static inline void nvme_aor_inc_active(NvmeNamespace *ns) -{ - assert(ns->nr_active_zones >= 0); - if (ns->params.max_active_zones) { - ns->nr_active_zones++; - assert(ns->nr_active_zones <= ns->params.max_active_zones); - } -} - -static inline void nvme_aor_dec_active(NvmeNamespace *ns) -{ - if (ns->params.max_active_zones) { - assert(ns->nr_active_zones > 0); - ns->nr_active_zones--; - assert(ns->nr_active_zones >= ns->nr_open_zones); - } - assert(ns->nr_active_zones >= 0); -} - void nvme_ns_init_format(NvmeNamespace *ns); int nvme_ns_setup(NvmeNamespace *ns, Error **errp); void nvme_ns_drain(NvmeNamespace *ns); diff --git a/hw/nvme/zns.h b/hw/nvme/zns.h new file mode 100644 index 000000000000..609db6eda7e5 --- /dev/null +++ b/hw/nvme/zns.h @@ -0,0 +1,97 @@ +#ifndef HW_NVME_ZONED_H +#define HW_NVME_ZONED_H + +#include "qemu/units.h" + +#include "nvme.h" + +#define NVME_DEFAULT_ZONE_SIZE (128 * MiB) + +static inline NvmeZoneState nvme_zns_zs(NvmeZone *zone) +{ + return zone->d.zs >> 4; +} + +static inline void nvme_zns_set_zs(NvmeZone *zone, NvmeZoneState state) +{ + zone->d.zs = state << 4; +} + +static inline uint64_t nvme_zns_read_boundary(NvmeNamespace *ns, + NvmeZone *zone) +{ + return zone->d.zslba + ns->zone_size; +} + +static inline uint64_t nvme_zns_write_boundary(NvmeZone *zone) +{ + return zone->d.zslba + zone->d.zcap; +} + +static inline bool nvme_zns_wp_valid(NvmeZone *zone) +{ + uint8_t st = nvme_zns_zs(zone); + + return st != NVME_ZONE_STATE_FULL && + st != NVME_ZONE_STATE_READ_ONLY && + st != NVME_ZONE_STATE_OFFLINE; +} + +static inline uint32_t nvme_zns_zidx(NvmeNamespace *ns, uint64_t slba) +{ + return ns->zone_size_log2 > 0 ? slba >> ns->zone_size_log2 : + slba / ns->zone_size; +} + +static inline NvmeZone *nvme_zns_get_by_slba(NvmeNamespace *ns, uint64_t slba) +{ + uint32_t zone_idx = nvme_zns_zidx(ns, slba); + + assert(zone_idx < ns->num_zones); + return &ns->zone_array[zone_idx]; +} + +static inline uint8_t *nvme_zns_zde(NvmeNamespace *ns, uint32_t zone_idx) +{ + return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size]; +} + +static inline void nvme_zns_aor_inc_open(NvmeNamespace *ns) +{ + assert(ns->nr_open_zones >= 0); + if (ns->params.max_open_zones) { + ns->nr_open_zones++; + assert(ns->nr_open_zones <= ns->params.max_open_zones); + } +} + +static inline void nvme_zns_aor_dec_open(NvmeNamespace *ns) +{ + if (ns->params.max_open_zones) { + assert(ns->nr_open_zones > 0); + ns->nr_open_zones--; + } + assert(ns->nr_open_zones >= 0); +} + +static inline void nvme_zns_aor_inc_active(NvmeNamespace *ns) +{ + assert(ns->nr_active_zones >= 0); + if (ns->params.max_active_zones) { + ns->nr_active_zones++; + assert(ns->nr_active_zones <= ns->params.max_active_zones); + } +} + +static inline void nvme_zns_aor_dec_active(NvmeNamespace *ns) +{ + if (ns->params.max_active_zones) { + assert(ns->nr_active_zones > 0); + ns->nr_active_zones--; + assert(ns->nr_active_zones >= ns->nr_open_zones); + } + assert(ns->nr_active_zones >= 0); +} + + +#endif /* HW_NVME_ZONED_H */ From patchwork Mon Sep 27 05:17:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533192 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=Zh0kGWUe; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=PE5sFfHH; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrmt1CrWz9t5m for ; Mon, 27 Sep 2021 15:29:50 +1000 (AEST) Received: from localhost ([::1]:49700 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjD1-0003qW-Pa for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:29:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34132) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj29-0002vw-1U; Mon, 27 Sep 2021 01:18:33 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:34887) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj23-00004z-O6; Mon, 27 Sep 2021 01:18:32 -0400 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailnew.west.internal (Postfix) with ESMTP id 359772B01207; Mon, 27 Sep 2021 01:18:25 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 27 Sep 2021 01:18:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=DVvaYhVsSbe4k 8Zcan9LVRTQFx15+pgHlHdW3lV5HBc=; b=Zh0kGWUeFyxrvg7XO0/AmFIDDss68 lSzdN7OlCYht97Hv1MHU1RelLE3hN/gbS5aka8c+fDm0PgMpyCKEqgpagWJWwr6c PEEqfhFjeiKmzMg/2sghxRsYp7hGfDXWqzWiAkN9dxzpyYjggOEx0pR/uSBZhTy9 Xg1Fg96fYgpf+PtR1enEK98hB4DyxVENeI8KLmsj6jvsLRXUhTx3TpgqHsyFUoGn HO9cZ5rYCbu4QwAq7gVqM6K43fNmNZlER5QR9822JhomMoyCV4nuysQIxkCvn4oQ z9Tvlqo5wkibxmheAu84pXejyi87mifMTfs57yP4zhnQW7My69pD4GaBQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=DVvaYhVsSbe4k8Zcan9LVRTQFx15+pgHlHdW3lV5HBc=; b=PE5sFfHH yQnIbCYk1uYpgB2KdowwPthwaxbR4uHk3SwpLjfQoCNVJnydWVXpeIwiVb5FgTZ5 KWiKIUGqqy/kGQYaYJnB1j1+72wXRsazRiV8S3hG8jGduQuCyGZXJL0pNB1tu5vd 6xDGqeT6aTR7p3gE7sEv2bG6+L/HLUoiCe/tkv23mvO+fGQ+3FTW/QT/VL3p+quL WTUltdMH6xcrXsueNQxHXRmjDHQrBjrfF1gZ2qfZpdfJuiUnC1UeSuUNMYyT0TAK 1SqAR+0MRvtZv5lH3hqd25Lg1MYlS6GL836XaK9GF5YuZuuYrCNKqtSBalQbmj85 iP97Urw0hQaikA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:22 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 05/16] hw/nvme: move zoned namespace members to separate struct Date: Mon, 27 Sep 2021 07:17:48 +0200 Message-Id: <20210927051759.447305-6-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen In preparation for nvm and zoned namespace separation, move zoned related members from NvmeNamespace into NvmeNamespaceZoned. There are no functional changes here, basically just a s/NvmeNamespace/NvmeNamespaceZoned and s/ns/zoned where applicable. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 302 ++++++++++++++++++++++--------------------- hw/nvme/ns.c | 142 +++++++++++--------- hw/nvme/nvme.h | 66 +++++++--- hw/nvme/zns.h | 80 ++++++------ include/block/nvme.h | 4 + 5 files changed, 327 insertions(+), 267 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 85937f57686c..e357329d85b8 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -260,41 +260,41 @@ static uint16_t nvme_sqid(NvmeRequest *req) return le16_to_cpu(req->sq->sqid); } -static void nvme_zns_assign_state(NvmeNamespace *ns, NvmeZone *zone, +static void nvme_zns_assign_state(NvmeNamespaceZoned *zoned, NvmeZone *zone, NvmeZoneState state) { if (QTAILQ_IN_USE(zone, entry)) { - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: - QTAILQ_REMOVE(&ns->exp_open_zones, zone, entry); + QTAILQ_REMOVE(&zoned->exp_open_zones, zone, entry); break; case NVME_ZONE_STATE_IMPLICITLY_OPEN: - QTAILQ_REMOVE(&ns->imp_open_zones, zone, entry); + QTAILQ_REMOVE(&zoned->imp_open_zones, zone, entry); break; case NVME_ZONE_STATE_CLOSED: - QTAILQ_REMOVE(&ns->closed_zones, zone, entry); + QTAILQ_REMOVE(&zoned->closed_zones, zone, entry); break; case NVME_ZONE_STATE_FULL: - QTAILQ_REMOVE(&ns->full_zones, zone, entry); + QTAILQ_REMOVE(&zoned->full_zones, zone, entry); default: ; } } - nvme_zns_set_zs(zone, state); + nvme_zns_set_state(zone, state); switch (state) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: - QTAILQ_INSERT_TAIL(&ns->exp_open_zones, zone, entry); + QTAILQ_INSERT_TAIL(&zoned->exp_open_zones, zone, entry); break; case NVME_ZONE_STATE_IMPLICITLY_OPEN: - QTAILQ_INSERT_TAIL(&ns->imp_open_zones, zone, entry); + QTAILQ_INSERT_TAIL(&zoned->imp_open_zones, zone, entry); break; case NVME_ZONE_STATE_CLOSED: - QTAILQ_INSERT_TAIL(&ns->closed_zones, zone, entry); + QTAILQ_INSERT_TAIL(&zoned->closed_zones, zone, entry); break; case NVME_ZONE_STATE_FULL: - QTAILQ_INSERT_TAIL(&ns->full_zones, zone, entry); + QTAILQ_INSERT_TAIL(&zoned->full_zones, zone, entry); case NVME_ZONE_STATE_READ_ONLY: break; default: @@ -306,17 +306,17 @@ static void nvme_zns_assign_state(NvmeNamespace *ns, NvmeZone *zone, * Check if we can open a zone without exceeding open/active limits. * AOR stands for "Active and Open Resources" (see TP 4053 section 2.5). */ -static int nvme_zns_aor_check(NvmeNamespace *ns, uint32_t act, - uint32_t opn) +static int nvme_zns_aor_check(NvmeNamespaceZoned *zoned, uint32_t act, + uint32_t opn) { - if (ns->params.max_active_zones != 0 && - ns->nr_active_zones + act > ns->params.max_active_zones) { - trace_pci_nvme_err_insuff_active_res(ns->params.max_active_zones); + if (zoned->max_active_zones != 0 && + zoned->nr_active_zones + act > zoned->max_active_zones) { + trace_pci_nvme_err_insuff_active_res(zoned->max_active_zones); return NVME_ZONE_TOO_MANY_ACTIVE | NVME_DNR; } - if (ns->params.max_open_zones != 0 && - ns->nr_open_zones + opn > ns->params.max_open_zones) { - trace_pci_nvme_err_insuff_open_res(ns->params.max_open_zones); + if (zoned->max_open_zones != 0 && + zoned->nr_open_zones + opn > zoned->max_open_zones) { + trace_pci_nvme_err_insuff_open_res(zoned->max_open_zones); return NVME_ZONE_TOO_MANY_OPEN | NVME_DNR; } @@ -1559,7 +1559,7 @@ static uint16_t nvme_check_zone_state_for_write(NvmeZone *zone) { uint64_t zslba = zone->d.zslba; - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_EMPTY: case NVME_ZONE_STATE_IMPLICITLY_OPEN: case NVME_ZONE_STATE_EXPLICITLY_OPEN: @@ -1581,8 +1581,8 @@ static uint16_t nvme_check_zone_state_for_write(NvmeZone *zone) return NVME_INTERNAL_DEV_ERROR; } -static uint16_t nvme_check_zone_write(NvmeNamespace *ns, NvmeZone *zone, - uint64_t slba, uint32_t nlb) +static uint16_t nvme_check_zone_write(NvmeZone *zone, uint64_t slba, + uint32_t nlb) { uint64_t zcap = nvme_zns_write_boundary(zone); uint16_t status; @@ -1607,7 +1607,7 @@ static uint16_t nvme_check_zone_write(NvmeNamespace *ns, NvmeZone *zone, static uint16_t nvme_check_zone_state_for_read(NvmeZone *zone) { - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_EMPTY: case NVME_ZONE_STATE_IMPLICITLY_OPEN: case NVME_ZONE_STATE_EXPLICITLY_OPEN: @@ -1625,24 +1625,24 @@ static uint16_t nvme_check_zone_state_for_read(NvmeZone *zone) return NVME_INTERNAL_DEV_ERROR; } -static uint16_t nvme_check_zone_read(NvmeNamespace *ns, uint64_t slba, +static uint16_t nvme_check_zone_read(NvmeNamespaceZoned *zoned, uint64_t slba, uint32_t nlb) { NvmeZone *zone; uint64_t bndry, end; uint16_t status; - zone = nvme_zns_get_by_slba(ns, slba); + zone = nvme_zns_get_by_slba(zoned, slba); assert(zone); - bndry = nvme_zns_read_boundary(ns, zone); + bndry = nvme_zns_read_boundary(zoned, zone); end = slba + nlb; status = nvme_check_zone_state_for_read(zone); if (status) { ; } else if (unlikely(end > bndry)) { - if (!ns->params.cross_zone_read) { + if (!(zoned->flags & NVME_NS_ZONED_CROSS_READ)) { status = NVME_ZONE_BOUNDARY_ERROR; } else { /* @@ -1655,28 +1655,28 @@ static uint16_t nvme_check_zone_read(NvmeNamespace *ns, uint64_t slba, if (status) { break; } - } while (end > nvme_zns_read_boundary(ns, zone)); + } while (end > nvme_zns_read_boundary(zoned, zone)); } } return status; } -static uint16_t nvme_zrm_finish(NvmeNamespace *ns, NvmeZone *zone) +static uint16_t nvme_zrm_finish(NvmeNamespaceZoned *zoned, NvmeZone *zone) { - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_FULL: return NVME_SUCCESS; case NVME_ZONE_STATE_IMPLICITLY_OPEN: case NVME_ZONE_STATE_EXPLICITLY_OPEN: - nvme_zns_aor_dec_open(ns); + nvme_zns_aor_dec_open(zoned); /* fallthrough */ case NVME_ZONE_STATE_CLOSED: - nvme_zns_aor_dec_active(ns); + nvme_zns_aor_dec_active(zoned); /* fallthrough */ case NVME_ZONE_STATE_EMPTY: - nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_FULL); + nvme_zns_assign_state(zoned, zone, NVME_ZONE_STATE_FULL); return NVME_SUCCESS; default: @@ -1684,13 +1684,13 @@ static uint16_t nvme_zrm_finish(NvmeNamespace *ns, NvmeZone *zone) } } -static uint16_t nvme_zrm_close(NvmeNamespace *ns, NvmeZone *zone) +static uint16_t nvme_zrm_close(NvmeNamespaceZoned *zoned, NvmeZone *zone) { - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: case NVME_ZONE_STATE_IMPLICITLY_OPEN: - nvme_zns_aor_dec_open(ns); - nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_CLOSED); + nvme_zns_aor_dec_open(zoned); + nvme_zns_assign_state(zoned, zone, NVME_ZONE_STATE_CLOSED); /* fall through */ case NVME_ZONE_STATE_CLOSED: return NVME_SUCCESS; @@ -1700,20 +1700,20 @@ static uint16_t nvme_zrm_close(NvmeNamespace *ns, NvmeZone *zone) } } -static uint16_t nvme_zrm_reset(NvmeNamespace *ns, NvmeZone *zone) +static uint16_t nvme_zrm_reset(NvmeNamespaceZoned *zoned, NvmeZone *zone) { - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_EXPLICITLY_OPEN: case NVME_ZONE_STATE_IMPLICITLY_OPEN: - nvme_zns_aor_dec_open(ns); + nvme_zns_aor_dec_open(zoned); /* fallthrough */ case NVME_ZONE_STATE_CLOSED: - nvme_zns_aor_dec_active(ns); + nvme_zns_aor_dec_active(zoned); /* fallthrough */ case NVME_ZONE_STATE_FULL: zone->w_ptr = zone->d.zslba; zone->d.wp = zone->w_ptr; - nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_EMPTY); + nvme_zns_assign_state(zoned, zone, NVME_ZONE_STATE_EMPTY); /* fallthrough */ case NVME_ZONE_STATE_EMPTY: return NVME_SUCCESS; @@ -1723,19 +1723,19 @@ static uint16_t nvme_zrm_reset(NvmeNamespace *ns, NvmeZone *zone) } } -static void nvme_zrm_auto_transition_zone(NvmeNamespace *ns) +static void nvme_zrm_auto_transition_zone(NvmeNamespaceZoned *zoned) { NvmeZone *zone; - if (ns->params.max_open_zones && - ns->nr_open_zones == ns->params.max_open_zones) { - zone = QTAILQ_FIRST(&ns->imp_open_zones); + if (zoned->max_open_zones && + zoned->nr_open_zones == zoned->max_open_zones) { + zone = QTAILQ_FIRST(&zoned->imp_open_zones); if (zone) { /* * Automatically close this implicitly open zone. */ - QTAILQ_REMOVE(&ns->imp_open_zones, zone, entry); - nvme_zrm_close(ns, zone); + QTAILQ_REMOVE(&zoned->imp_open_zones, zone, entry); + nvme_zrm_close(zoned, zone); } } } @@ -1744,13 +1744,13 @@ enum { NVME_ZRM_AUTO = 1 << 0, }; -static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns, +static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespaceZoned *zoned, NvmeZone *zone, int flags) { int act = 0; uint16_t status; - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_EMPTY: act = 1; @@ -1758,21 +1758,21 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns, case NVME_ZONE_STATE_CLOSED: if (n->params.auto_transition_zones) { - nvme_zrm_auto_transition_zone(ns); + nvme_zrm_auto_transition_zone(zoned); } - status = nvme_zns_aor_check(ns, act, 1); + status = nvme_zns_aor_check(zoned, act, 1); if (status) { return status; } if (act) { - nvme_zns_aor_inc_active(ns); + nvme_zns_aor_inc_active(zoned); } - nvme_zns_aor_inc_open(ns); + nvme_zns_aor_inc_open(zoned); if (flags & NVME_ZRM_AUTO) { - nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_IMPLICITLY_OPEN); + nvme_zns_assign_state(zoned, zone, NVME_ZONE_STATE_IMPLICITLY_OPEN); return NVME_SUCCESS; } @@ -1783,7 +1783,7 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns, return NVME_SUCCESS; } - nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_EXPLICITLY_OPEN); + nvme_zns_assign_state(zoned, zone, NVME_ZONE_STATE_EXPLICITLY_OPEN); /* fallthrough */ @@ -1795,29 +1795,30 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespace *ns, } } -static inline uint16_t nvme_zrm_auto(NvmeCtrl *n, NvmeNamespace *ns, +static inline uint16_t nvme_zrm_auto(NvmeCtrl *n, NvmeNamespaceZoned *zoned, NvmeZone *zone) { - return nvme_zrm_open_flags(n, ns, zone, NVME_ZRM_AUTO); + return nvme_zrm_open_flags(n, zoned, zone, NVME_ZRM_AUTO); } -static inline uint16_t nvme_zrm_open(NvmeCtrl *n, NvmeNamespace *ns, +static inline uint16_t nvme_zrm_open(NvmeCtrl *n, NvmeNamespaceZoned *zoned, NvmeZone *zone) { - return nvme_zrm_open_flags(n, ns, zone, 0); + return nvme_zrm_open_flags(n, zoned, zone, 0); } -static void nvme_advance_zone_wp(NvmeNamespace *ns, NvmeZone *zone, +static void nvme_advance_zone_wp(NvmeNamespaceZoned *zoned, NvmeZone *zone, uint32_t nlb) { zone->d.wp += nlb; if (zone->d.wp == nvme_zns_write_boundary(zone)) { - nvme_zrm_finish(ns, zone); + nvme_zrm_finish(zoned, zone); } } -static void nvme_finalize_zoned_write(NvmeNamespace *ns, NvmeRequest *req) +static void nvme_finalize_zoned_write(NvmeNamespaceZoned *zoned, + NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeZone *zone; @@ -1826,10 +1827,10 @@ static void nvme_finalize_zoned_write(NvmeNamespace *ns, NvmeRequest *req) slba = le64_to_cpu(rw->slba); nlb = le16_to_cpu(rw->nlb) + 1; - zone = nvme_zns_get_by_slba(ns, slba); + zone = nvme_zns_get_by_slba(zoned, slba); assert(zone); - nvme_advance_zone_wp(ns, zone, nlb); + nvme_advance_zone_wp(zoned, zone, nlb); } static inline bool nvme_is_write(NvmeRequest *req) @@ -1876,8 +1877,8 @@ void nvme_rw_complete_cb(void *opaque, int ret) block_acct_done(stats, acct); } - if (ns->params.zoned && nvme_is_write(req)) { - nvme_finalize_zoned_write(ns, req); + if (nvme_ns_zoned(ns) && nvme_is_write(req)) { + nvme_finalize_zoned_write(NVME_NAMESPACE_ZONED(ns), req); } nvme_enqueue_req_completion(nvme_cq(req), req); @@ -2503,8 +2504,8 @@ static void nvme_copy_out_completed_cb(void *opaque, int ret) goto out; } - if (ns->params.zoned) { - nvme_advance_zone_wp(ns, iocb->zone, nlb); + if (nvme_ns_zoned(ns)) { + nvme_advance_zone_wp(NVME_NAMESPACE_ZONED(ns), iocb->zone, nlb); } iocb->idx++; @@ -2623,8 +2624,8 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) goto invalid; } - if (ns->params.zoned) { - status = nvme_check_zone_write(ns, iocb->zone, iocb->slba, nlb); + if (nvme_ns_zoned(ns)) { + status = nvme_check_zone_write(iocb->zone, iocb->slba, nlb); if (status) { goto invalid; } @@ -2737,8 +2738,8 @@ static void nvme_copy_cb(void *opaque, int ret) } } - if (ns->params.zoned) { - status = nvme_check_zone_read(ns, slba, nlb); + if (nvme_ns_zoned(ns)) { + status = nvme_check_zone_read(NVME_NAMESPACE_ZONED(ns), slba, nlb); if (status) { goto invalid; } @@ -2806,14 +2807,16 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) iocb->slba = le64_to_cpu(copy->sdlba); - if (ns->params.zoned) { - iocb->zone = nvme_zns_get_by_slba(ns, iocb->slba); + if (nvme_ns_zoned(ns)) { + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + + iocb->zone = nvme_zns_get_by_slba(zoned, iocb->slba); if (!iocb->zone) { status = NVME_LBA_RANGE | NVME_DNR; goto invalid; } - status = nvme_zrm_auto(n, ns, iocb->zone); + status = nvme_zrm_auto(n, zoned, iocb->zone); if (status) { goto invalid; } @@ -3081,8 +3084,8 @@ static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req) goto invalid; } - if (ns->params.zoned) { - status = nvme_check_zone_read(ns, slba, nlb); + if (nvme_ns_zoned(ns)) { + status = nvme_check_zone_read(NVME_NAMESPACE_ZONED(ns), slba, nlb); if (status) { trace_pci_nvme_err_zone_read_not_ok(slba, nlb, status); goto invalid; @@ -3161,8 +3164,10 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, goto invalid; } - if (ns->params.zoned) { - zone = nvme_zns_get_by_slba(ns, slba); + if (nvme_ns_zoned(ns)) { + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + + zone = nvme_zns_get_by_slba(zoned, slba); assert(zone); if (append) { @@ -3209,12 +3214,12 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, } } - status = nvme_check_zone_write(ns, zone, slba, nlb); + status = nvme_check_zone_write(zone, slba, nlb); if (status) { goto invalid; } - status = nvme_zrm_auto(n, ns, zone); + status = nvme_zrm_auto(n, zoned, zone); if (status) { goto invalid; } @@ -3268,14 +3273,18 @@ static inline uint16_t nvme_zone_append(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_get_mgmt_zone_slba_idx(NvmeNamespace *ns, NvmeCmd *c, uint64_t *slba, uint32_t *zone_idx) { + NvmeNamespaceZoned *zoned; + uint32_t dw10 = le32_to_cpu(c->cdw10); uint32_t dw11 = le32_to_cpu(c->cdw11); - if (!ns->params.zoned) { + if (!nvme_ns_zoned(ns)) { trace_pci_nvme_err_invalid_opc(c->opcode); return NVME_INVALID_OPCODE | NVME_DNR; } + zoned = NVME_NAMESPACE_ZONED(ns); + *slba = ((uint64_t)dw11) << 32 | dw10; if (unlikely(*slba >= ns->id_ns.nsze)) { trace_pci_nvme_err_invalid_lba_range(*slba, 0, ns->id_ns.nsze); @@ -3283,14 +3292,14 @@ static uint16_t nvme_get_mgmt_zone_slba_idx(NvmeNamespace *ns, NvmeCmd *c, return NVME_LBA_RANGE | NVME_DNR; } - *zone_idx = nvme_zns_zidx(ns, *slba); - assert(*zone_idx < ns->num_zones); + *zone_idx = nvme_zns_zidx(zoned, *slba); + assert(*zone_idx < zoned->num_zones); return NVME_SUCCESS; } -typedef uint16_t (*op_handler_t)(NvmeNamespace *, NvmeZone *, NvmeZoneState, - NvmeRequest *); +typedef uint16_t (*op_handler_t)(NvmeNamespaceZoned *, NvmeZone *, + NvmeZoneState, NvmeRequest *); enum NvmeZoneProcessingMask { NVME_PROC_CURRENT_ZONE = 0, @@ -3300,30 +3309,30 @@ enum NvmeZoneProcessingMask { NVME_PROC_FULL_ZONES = 1 << 3, }; -static uint16_t nvme_open_zone(NvmeNamespace *ns, NvmeZone *zone, +static uint16_t nvme_open_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone, NvmeZoneState state, NvmeRequest *req) { - return nvme_zrm_open(nvme_ctrl(req), ns, zone); + return nvme_zrm_open(nvme_ctrl(req), zoned, zone); } -static uint16_t nvme_close_zone(NvmeNamespace *ns, NvmeZone *zone, +static uint16_t nvme_close_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone, NvmeZoneState state, NvmeRequest *req) { - return nvme_zrm_close(ns, zone); + return nvme_zrm_close(zoned, zone); } -static uint16_t nvme_finish_zone(NvmeNamespace *ns, NvmeZone *zone, +static uint16_t nvme_finish_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone, NvmeZoneState state, NvmeRequest *req) { - return nvme_zrm_finish(ns, zone); + return nvme_zrm_finish(zoned, zone); } -static uint16_t nvme_offline_zone(NvmeNamespace *ns, NvmeZone *zone, +static uint16_t nvme_offline_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone, NvmeZoneState state, NvmeRequest *req) { switch (state) { case NVME_ZONE_STATE_READ_ONLY: - nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_OFFLINE); + nvme_zns_assign_state(zoned, zone, NVME_ZONE_STATE_OFFLINE); /* fall through */ case NVME_ZONE_STATE_OFFLINE: return NVME_SUCCESS; @@ -3332,31 +3341,31 @@ static uint16_t nvme_offline_zone(NvmeNamespace *ns, NvmeZone *zone, } } -static uint16_t nvme_set_zd_ext(NvmeNamespace *ns, NvmeZone *zone) +static uint16_t nvme_set_zd_ext(NvmeNamespaceZoned *zoned, NvmeZone *zone) { uint16_t status; - uint8_t state = nvme_zns_zs(zone); + uint8_t state = nvme_zns_state(zone); if (state == NVME_ZONE_STATE_EMPTY) { - status = nvme_zns_aor_check(ns, 1, 0); + status = nvme_zns_aor_check(zoned, 1, 0); if (status) { return status; } - nvme_zns_aor_inc_active(ns); + nvme_zns_aor_inc_active(zoned); zone->d.za |= NVME_ZA_ZD_EXT_VALID; - nvme_zns_assign_state(ns, zone, NVME_ZONE_STATE_CLOSED); + nvme_zns_assign_state(zoned, zone, NVME_ZONE_STATE_CLOSED); return NVME_SUCCESS; } return NVME_ZONE_INVAL_TRANSITION; } -static uint16_t nvme_bulk_proc_zone(NvmeNamespace *ns, NvmeZone *zone, +static uint16_t nvme_bulk_proc_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone, enum NvmeZoneProcessingMask proc_mask, op_handler_t op_hndlr, NvmeRequest *req) { uint16_t status = NVME_SUCCESS; - NvmeZoneState zs = nvme_zns_zs(zone); + NvmeZoneState zs = nvme_zns_state(zone); bool proc_zone; switch (zs) { @@ -3378,13 +3387,13 @@ static uint16_t nvme_bulk_proc_zone(NvmeNamespace *ns, NvmeZone *zone, } if (proc_zone) { - status = op_hndlr(ns, zone, zs, req); + status = op_hndlr(zoned, zone, zs, req); } return status; } -static uint16_t nvme_do_zone_op(NvmeNamespace *ns, NvmeZone *zone, +static uint16_t nvme_do_zone_op(NvmeNamespaceZoned *zoned, NvmeZone *zone, enum NvmeZoneProcessingMask proc_mask, op_handler_t op_hndlr, NvmeRequest *req) { @@ -3393,11 +3402,11 @@ static uint16_t nvme_do_zone_op(NvmeNamespace *ns, NvmeZone *zone, int i; if (!proc_mask) { - status = op_hndlr(ns, zone, nvme_zns_zs(zone), req); + status = op_hndlr(zoned, zone, nvme_zns_state(zone), req); } else { if (proc_mask & NVME_PROC_CLOSED_ZONES) { - QTAILQ_FOREACH_SAFE(zone, &ns->closed_zones, entry, next) { - status = nvme_bulk_proc_zone(ns, zone, proc_mask, op_hndlr, + QTAILQ_FOREACH_SAFE(zone, &zoned->closed_zones, entry, next) { + status = nvme_bulk_proc_zone(zoned, zone, proc_mask, op_hndlr, req); if (status && status != NVME_NO_COMPLETE) { goto out; @@ -3405,16 +3414,16 @@ static uint16_t nvme_do_zone_op(NvmeNamespace *ns, NvmeZone *zone, } } if (proc_mask & NVME_PROC_OPENED_ZONES) { - QTAILQ_FOREACH_SAFE(zone, &ns->imp_open_zones, entry, next) { - status = nvme_bulk_proc_zone(ns, zone, proc_mask, op_hndlr, + QTAILQ_FOREACH_SAFE(zone, &zoned->imp_open_zones, entry, next) { + status = nvme_bulk_proc_zone(zoned, zone, proc_mask, op_hndlr, req); if (status && status != NVME_NO_COMPLETE) { goto out; } } - QTAILQ_FOREACH_SAFE(zone, &ns->exp_open_zones, entry, next) { - status = nvme_bulk_proc_zone(ns, zone, proc_mask, op_hndlr, + QTAILQ_FOREACH_SAFE(zone, &zoned->exp_open_zones, entry, next) { + status = nvme_bulk_proc_zone(zoned, zone, proc_mask, op_hndlr, req); if (status && status != NVME_NO_COMPLETE) { goto out; @@ -3422,8 +3431,8 @@ static uint16_t nvme_do_zone_op(NvmeNamespace *ns, NvmeZone *zone, } } if (proc_mask & NVME_PROC_FULL_ZONES) { - QTAILQ_FOREACH_SAFE(zone, &ns->full_zones, entry, next) { - status = nvme_bulk_proc_zone(ns, zone, proc_mask, op_hndlr, + QTAILQ_FOREACH_SAFE(zone, &zoned->full_zones, entry, next) { + status = nvme_bulk_proc_zone(zoned, zone, proc_mask, op_hndlr, req); if (status && status != NVME_NO_COMPLETE) { goto out; @@ -3432,8 +3441,8 @@ static uint16_t nvme_do_zone_op(NvmeNamespace *ns, NvmeZone *zone, } if (proc_mask & NVME_PROC_READ_ONLY_ZONES) { - for (i = 0; i < ns->num_zones; i++, zone++) { - status = nvme_bulk_proc_zone(ns, zone, proc_mask, op_hndlr, + for (i = 0; i < zoned->num_zones; i++, zone++) { + status = nvme_bulk_proc_zone(zoned, zone, proc_mask, op_hndlr, req); if (status && status != NVME_NO_COMPLETE) { goto out; @@ -3464,7 +3473,7 @@ static void nvme_zone_reset_cancel(BlockAIOCB *aiocb) NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; - iocb->idx = ns->num_zones; + iocb->idx = NVME_NAMESPACE_ZONED(ns)->num_zones; iocb->ret = -ECANCELED; @@ -3511,7 +3520,7 @@ static void nvme_zone_reset_epilogue_cb(void *opaque, int ret) } moff = nvme_moff(ns, iocb->zone->d.zslba); - count = nvme_m2b(ns, ns->zone_size); + count = nvme_m2b(ns, NVME_NAMESPACE_ZONED(ns)->zone_size); iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, moff, count, BDRV_REQ_MAY_UNMAP, @@ -3524,6 +3533,7 @@ static void nvme_zone_reset_cb(void *opaque, int ret) NvmeZoneResetAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); if (ret < 0) { iocb->ret = ret; @@ -3531,17 +3541,17 @@ static void nvme_zone_reset_cb(void *opaque, int ret) } if (iocb->zone) { - nvme_zrm_reset(ns, iocb->zone); + nvme_zrm_reset(zoned, iocb->zone); if (!iocb->all) { goto done; } } - while (iocb->idx < ns->num_zones) { - NvmeZone *zone = &ns->zone_array[iocb->idx++]; + while (iocb->idx < zoned->num_zones) { + NvmeZone *zone = &zoned->zone_array[iocb->idx++]; - switch (nvme_zns_zs(zone)) { + switch (nvme_zns_state(zone)) { case NVME_ZONE_STATE_EMPTY: if (!iocb->all) { goto done; @@ -3564,7 +3574,7 @@ static void nvme_zone_reset_cb(void *opaque, int ret) iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, nvme_l2b(ns, zone->d.zslba), - nvme_l2b(ns, ns->zone_size), + nvme_l2b(ns, zoned->zone_size), BDRV_REQ_MAY_UNMAP, nvme_zone_reset_epilogue_cb, iocb); @@ -3582,6 +3592,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) { NvmeCmd *cmd = (NvmeCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); NvmeZone *zone; NvmeZoneResetAIOCB *iocb; uint8_t *zd_ext; @@ -3605,7 +3616,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) } } - zone = &ns->zone_array[zone_idx]; + zone = &zoned->zone_array[zone_idx]; if (slba != zone->d.zslba) { trace_pci_nvme_err_unaligned_zone_cmd(action, slba, zone->d.zslba); return NVME_INVALID_FIELD | NVME_DNR; @@ -3618,7 +3629,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) proc_mask = NVME_PROC_CLOSED_ZONES; } trace_pci_nvme_open_zone(slba, zone_idx, all); - status = nvme_do_zone_op(ns, zone, proc_mask, nvme_open_zone, req); + status = nvme_do_zone_op(zoned, zone, proc_mask, nvme_open_zone, req); break; case NVME_ZONE_ACTION_CLOSE: @@ -3626,7 +3637,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) proc_mask = NVME_PROC_OPENED_ZONES; } trace_pci_nvme_close_zone(slba, zone_idx, all); - status = nvme_do_zone_op(ns, zone, proc_mask, nvme_close_zone, req); + status = nvme_do_zone_op(zoned, zone, proc_mask, nvme_close_zone, req); break; case NVME_ZONE_ACTION_FINISH: @@ -3634,7 +3645,8 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) proc_mask = NVME_PROC_OPENED_ZONES | NVME_PROC_CLOSED_ZONES; } trace_pci_nvme_finish_zone(slba, zone_idx, all); - status = nvme_do_zone_op(ns, zone, proc_mask, nvme_finish_zone, req); + status = nvme_do_zone_op(zoned, zone, proc_mask, nvme_finish_zone, + req); break; case NVME_ZONE_ACTION_RESET: @@ -3660,22 +3672,23 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) proc_mask = NVME_PROC_READ_ONLY_ZONES; } trace_pci_nvme_offline_zone(slba, zone_idx, all); - status = nvme_do_zone_op(ns, zone, proc_mask, nvme_offline_zone, req); + status = nvme_do_zone_op(zoned, zone, proc_mask, nvme_offline_zone, + req); break; case NVME_ZONE_ACTION_SET_ZD_EXT: trace_pci_nvme_set_descriptor_extension(slba, zone_idx); - if (all || !ns->params.zd_extension_size) { + if (all || !zoned->zd_extension_size) { return NVME_INVALID_FIELD | NVME_DNR; } - zd_ext = nvme_zns_zde(ns, zone_idx); - status = nvme_h2c(n, zd_ext, ns->params.zd_extension_size, req); + zd_ext = nvme_zns_zde(zoned, zone_idx); + status = nvme_h2c(n, zd_ext, zoned->zd_extension_size, req); if (status) { trace_pci_nvme_err_zd_extension_map_error(zone_idx); return status; } - status = nvme_set_zd_ext(ns, zone); + status = nvme_set_zd_ext(zoned, zone); if (status == NVME_SUCCESS) { trace_pci_nvme_zd_extension_set(zone_idx); return status; @@ -3700,7 +3713,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) static bool nvme_zone_matches_filter(uint32_t zafs, NvmeZone *zl) { - NvmeZoneState zs = nvme_zns_zs(zl); + NvmeZoneState zs = nvme_zns_state(zl); switch (zafs) { case NVME_ZONE_REPORT_ALL: @@ -3728,6 +3741,7 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) { NvmeCmd *cmd = (NvmeCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); /* cdw12 is zero-based number of dwords to return. Convert to bytes */ uint32_t data_size = (le32_to_cpu(cmd->cdw12) + 1) << 2; uint32_t dw13 = le32_to_cpu(cmd->cdw13); @@ -3753,7 +3767,7 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) if (zra != NVME_ZONE_REPORT && zra != NVME_ZONE_REPORT_EXTENDED) { return NVME_INVALID_FIELD | NVME_DNR; } - if (zra == NVME_ZONE_REPORT_EXTENDED && !ns->params.zd_extension_size) { + if (zra == NVME_ZONE_REPORT_EXTENDED && !zoned->zd_extension_size) { return NVME_INVALID_FIELD | NVME_DNR; } @@ -3775,14 +3789,14 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) zone_entry_sz = sizeof(NvmeZoneDescr); if (zra == NVME_ZONE_REPORT_EXTENDED) { - zone_entry_sz += ns->params.zd_extension_size; + zone_entry_sz += zoned->zd_extension_size; } max_zones = (data_size - sizeof(NvmeZoneReportHeader)) / zone_entry_sz; buf = g_malloc0(data_size); - zone = &ns->zone_array[zone_idx]; - for (i = zone_idx; i < ns->num_zones; i++) { + zone = &zoned->zone_array[zone_idx]; + for (i = zone_idx; i < zoned->num_zones; i++) { if (partial && nr_zones >= max_zones) { break; } @@ -3794,8 +3808,8 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) header->nr_zones = cpu_to_le64(nr_zones); buf_p = buf + sizeof(NvmeZoneReportHeader); - for (; zone_idx < ns->num_zones && max_zones > 0; zone_idx++) { - zone = &ns->zone_array[zone_idx]; + for (; zone_idx < zoned->num_zones && max_zones > 0; zone_idx++) { + zone = &zoned->zone_array[zone_idx]; if (nvme_zone_matches_filter(zrasf, zone)) { z = (NvmeZoneDescr *)buf_p; buf_p += sizeof(NvmeZoneDescr); @@ -3814,10 +3828,10 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) if (zra == NVME_ZONE_REPORT_EXTENDED) { if (zone->d.za & NVME_ZA_ZD_EXT_VALID) { - memcpy(buf_p, nvme_zns_zde(ns, zone_idx), - ns->params.zd_extension_size); + memcpy(buf_p, nvme_zns_zde(zoned, zone_idx), + zoned->zd_extension_size); } - buf_p += ns->params.zd_extension_size; + buf_p += zoned->zd_extension_size; } max_zones--; @@ -4542,8 +4556,8 @@ static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req, if (c->csi == NVME_CSI_NVM) { return nvme_rpt_empty_id_struct(n, req); } else if (c->csi == NVME_CSI_ZONED && ns->csi == NVME_CSI_ZONED) { - return nvme_c2h(n, (uint8_t *)ns->id_ns_zoned, sizeof(NvmeIdNsZoned), - req); + return nvme_c2h(n, (uint8_t *)&NVME_NAMESPACE_ZONED(ns)->id_ns, + sizeof(NvmeIdNsZoned), req); } return NVME_INVALID_FIELD | NVME_DNR; @@ -5343,7 +5357,7 @@ done: static uint16_t nvme_format_check(NvmeNamespace *ns, uint8_t lbaf, uint8_t pi) { - if (ns->params.zoned) { + if (nvme_ns_zoned(ns)) { return NVME_INVALID_FORMAT | NVME_DNR; } diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 471d1ddc016a..183483969088 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -167,6 +167,8 @@ static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp) static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) { + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + uint64_t zone_size, zone_cap; /* Make sure that the values of ZNS properties are sane */ @@ -200,12 +202,12 @@ static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) * Save the main zone geometry values to avoid * calculating them later again. */ - ns->zone_size = zone_size / ns->lbasz; - ns->zone_capacity = zone_cap / ns->lbasz; - ns->num_zones = le64_to_cpu(ns->id_ns.nsze) / ns->zone_size; + zoned->zone_size = zone_size / ns->lbasz; + zoned->zone_capacity = zone_cap / ns->lbasz; + zoned->num_zones = le64_to_cpu(ns->id_ns.nsze) / zoned->zone_size; /* Do a few more sanity checks of ZNS properties */ - if (!ns->num_zones) { + if (!zoned->num_zones) { error_setg(errp, "insufficient drive capacity, must be at least the size " "of one zone (%"PRIu64"B)", zone_size); @@ -215,68 +217,70 @@ static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) return 0; } -static void nvme_zns_init_state(NvmeNamespace *ns) +static void nvme_zns_init_state(NvmeNamespaceZoned *zoned) { - uint64_t start = 0, zone_size = ns->zone_size; - uint64_t capacity = ns->num_zones * zone_size; + uint64_t start = 0, zone_size = zoned->zone_size; + uint64_t capacity = zoned->num_zones * zone_size; NvmeZone *zone; int i; - ns->zone_array = g_new0(NvmeZone, ns->num_zones); - if (ns->params.zd_extension_size) { - ns->zd_extensions = g_malloc0(ns->params.zd_extension_size * - ns->num_zones); + zoned->zone_array = g_new0(NvmeZone, zoned->num_zones); + if (zoned->zd_extension_size) { + zoned->zd_extensions = g_malloc0(zoned->zd_extension_size * + zoned->num_zones); } - QTAILQ_INIT(&ns->exp_open_zones); - QTAILQ_INIT(&ns->imp_open_zones); - QTAILQ_INIT(&ns->closed_zones); - QTAILQ_INIT(&ns->full_zones); + QTAILQ_INIT(&zoned->exp_open_zones); + QTAILQ_INIT(&zoned->imp_open_zones); + QTAILQ_INIT(&zoned->closed_zones); + QTAILQ_INIT(&zoned->full_zones); - zone = ns->zone_array; - for (i = 0; i < ns->num_zones; i++, zone++) { + zone = zoned->zone_array; + for (i = 0; i < zoned->num_zones; i++, zone++) { if (start + zone_size > capacity) { zone_size = capacity - start; } zone->d.zt = NVME_ZONE_TYPE_SEQ_WRITE; - nvme_zns_set_zs(zone, NVME_ZONE_STATE_EMPTY); + nvme_zns_set_state(zone, NVME_ZONE_STATE_EMPTY); zone->d.za = 0; - zone->d.zcap = ns->zone_capacity; + zone->d.zcap = zoned->zone_capacity; zone->d.zslba = start; zone->d.wp = start; zone->w_ptr = start; start += zone_size; } - ns->zone_size_log2 = 0; - if (is_power_of_2(ns->zone_size)) { - ns->zone_size_log2 = 63 - clz64(ns->zone_size); + zoned->zone_size_log2 = 0; + if (is_power_of_2(zoned->zone_size)) { + zoned->zone_size_log2 = 63 - clz64(zoned->zone_size); } } static void nvme_zns_init(NvmeNamespace *ns) { - NvmeIdNsZoned *id_ns_z; + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + NvmeIdNsZoned *id_ns_z = &zoned->id_ns; int i; - nvme_zns_init_state(ns); - - id_ns_z = g_malloc0(sizeof(NvmeIdNsZoned)); + nvme_zns_init_state(zoned); /* MAR/MOR are zeroes-based, FFFFFFFFFh means no limit */ - id_ns_z->mar = cpu_to_le32(ns->params.max_active_zones - 1); - id_ns_z->mor = cpu_to_le32(ns->params.max_open_zones - 1); + id_ns_z->mar = cpu_to_le32(zoned->max_active_zones - 1); + id_ns_z->mor = cpu_to_le32(zoned->max_open_zones - 1); id_ns_z->zoc = 0; - id_ns_z->ozcs = ns->params.cross_zone_read ? 0x01 : 0x00; + + if (zoned->flags & NVME_NS_ZONED_CROSS_READ) { + id_ns_z->ozcs |= NVME_ID_NS_ZONED_OZCS_CROSS_READ; + } for (i = 0; i <= ns->id_ns.nlbaf; i++) { - id_ns_z->lbafe[i].zsze = cpu_to_le64(ns->zone_size); + id_ns_z->lbafe[i].zsze = cpu_to_le64(zoned->zone_size); id_ns_z->lbafe[i].zdes = - ns->params.zd_extension_size >> 6; /* Units of 64B */ + zoned->zd_extension_size >> 6; /* Units of 64B */ } ns->csi = NVME_CSI_ZONED; - ns->id_ns.nsze = cpu_to_le64(ns->num_zones * ns->zone_size); + ns->id_ns.nsze = cpu_to_le64(zoned->num_zones * zoned->zone_size); ns->id_ns.ncap = ns->id_ns.nsze; ns->id_ns.nuse = ns->id_ns.ncap; @@ -287,64 +291,62 @@ static void nvme_zns_init(NvmeNamespace *ns) * we can only support DULBE if the zone size is a multiple of the * calculated NPDG. */ - if (ns->zone_size % (ns->id_ns.npdg + 1)) { + if (zoned->zone_size % (ns->id_ns.npdg + 1)) { warn_report("the zone size (%"PRIu64" blocks) is not a multiple of " "the calculated deallocation granularity (%d blocks); " "DULBE support disabled", - ns->zone_size, ns->id_ns.npdg + 1); + zoned->zone_size, ns->id_ns.npdg + 1); ns->id_ns.nsfeat &= ~0x4; } - - ns->id_ns_zoned = id_ns_z; } -static void nvme_zns_clear_zone(NvmeNamespace *ns, NvmeZone *zone) +static void nvme_zns_clear_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone) { uint8_t state; zone->w_ptr = zone->d.wp; - state = nvme_zns_zs(zone); + state = nvme_zns_state(zone); if (zone->d.wp != zone->d.zslba || (zone->d.za & NVME_ZA_ZD_EXT_VALID)) { if (state != NVME_ZONE_STATE_CLOSED) { trace_pci_nvme_clear_ns_close(state, zone->d.zslba); - nvme_zns_set_zs(zone, NVME_ZONE_STATE_CLOSED); + nvme_zns_set_state(zone, NVME_ZONE_STATE_CLOSED); } - nvme_zns_aor_inc_active(ns); - QTAILQ_INSERT_HEAD(&ns->closed_zones, zone, entry); + nvme_zns_aor_inc_active(zoned); + QTAILQ_INSERT_HEAD(&zoned->closed_zones, zone, entry); } else { trace_pci_nvme_clear_ns_reset(state, zone->d.zslba); - nvme_zns_set_zs(zone, NVME_ZONE_STATE_EMPTY); + nvme_zns_set_state(zone, NVME_ZONE_STATE_EMPTY); } } /* * Close all the zones that are currently open. */ -static void nvme_zns_shutdown(NvmeNamespace *ns) +static void nvme_zns_shutdown(NvmeNamespaceZoned *zoned) { NvmeZone *zone, *next; - QTAILQ_FOREACH_SAFE(zone, &ns->closed_zones, entry, next) { - QTAILQ_REMOVE(&ns->closed_zones, zone, entry); - nvme_zns_aor_dec_active(ns); - nvme_zns_clear_zone(ns, zone); + QTAILQ_FOREACH_SAFE(zone, &zoned->closed_zones, entry, next) { + QTAILQ_REMOVE(&zoned->closed_zones, zone, entry); + nvme_zns_aor_dec_active(zoned); + nvme_zns_clear_zone(zoned, zone); } - QTAILQ_FOREACH_SAFE(zone, &ns->imp_open_zones, entry, next) { - QTAILQ_REMOVE(&ns->imp_open_zones, zone, entry); - nvme_zns_aor_dec_open(ns); - nvme_zns_aor_dec_active(ns); - nvme_zns_clear_zone(ns, zone); + QTAILQ_FOREACH_SAFE(zone, &zoned->imp_open_zones, entry, next) { + QTAILQ_REMOVE(&zoned->imp_open_zones, zone, entry); + nvme_zns_aor_dec_open(zoned); + nvme_zns_aor_dec_active(zoned); + nvme_zns_clear_zone(zoned, zone); } - QTAILQ_FOREACH_SAFE(zone, &ns->exp_open_zones, entry, next) { - QTAILQ_REMOVE(&ns->exp_open_zones, zone, entry); - nvme_zns_aor_dec_open(ns); - nvme_zns_aor_dec_active(ns); - nvme_zns_clear_zone(ns, zone); + QTAILQ_FOREACH_SAFE(zone, &zoned->exp_open_zones, entry, next) { + QTAILQ_REMOVE(&zoned->exp_open_zones, zone, entry); + nvme_zns_aor_dec_open(zoned); + nvme_zns_aor_dec_active(zoned); + nvme_zns_clear_zone(zoned, zone); } - assert(ns->nr_open_zones == 0); + assert(zoned->nr_open_zones == 0); } static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp) @@ -411,9 +413,20 @@ int nvme_ns_setup(NvmeNamespace *ns, Error **errp) return -1; } if (ns->params.zoned) { + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + if (nvme_zns_check_calc_geometry(ns, errp) != 0) { return -1; } + + /* copy device parameters */ + zoned->zd_extension_size = ns->params.zd_extension_size; + zoned->max_open_zones = ns->params.max_open_zones; + zoned->max_active_zones = ns->params.max_open_zones; + if (ns->params.cross_zone_read) { + zoned->flags |= NVME_NS_ZONED_CROSS_READ; + } + nvme_zns_init(ns); } @@ -428,17 +441,18 @@ void nvme_ns_drain(NvmeNamespace *ns) void nvme_ns_shutdown(NvmeNamespace *ns) { blk_flush(ns->blkconf.blk); - if (ns->params.zoned) { - nvme_zns_shutdown(ns); + if (nvme_ns_zoned(ns)) { + nvme_zns_shutdown(NVME_NAMESPACE_ZONED(ns)); } } void nvme_ns_cleanup(NvmeNamespace *ns) { - if (ns->params.zoned) { - g_free(ns->id_ns_zoned); - g_free(ns->zone_array); - g_free(ns->zd_extensions); + if (nvme_ns_zoned(ns)) { + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + + g_free(zoned->zone_array); + g_free(zoned->zd_extensions); } } diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 99d8b9066cc9..9cfb172101a9 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -84,12 +84,6 @@ static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys, #define NVME_NS(obj) \ OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) -typedef struct NvmeZone { - NvmeZoneDescr d; - uint64_t w_ptr; - QTAILQ_ENTRY(NvmeZone) entry; -} NvmeZone; - typedef struct NvmeNamespaceParams { bool detached; bool shared; @@ -116,6 +110,43 @@ typedef struct NvmeNamespaceParams { uint32_t zd_extension_size; } NvmeNamespaceParams; +typedef struct NvmeZone { + NvmeZoneDescr d; + uint64_t w_ptr; + QTAILQ_ENTRY(NvmeZone) entry; +} NvmeZone; + +enum { + NVME_NS_ZONED_CROSS_READ = 1 << 0, +}; + +typedef struct NvmeNamespaceZoned { + NvmeIdNsZoned id_ns; + + uint32_t num_zones; + NvmeZone *zone_array; + + uint64_t zone_size; + uint32_t zone_size_log2; + + uint64_t zone_capacity; + + uint32_t zd_extension_size; + uint8_t *zd_extensions; + + uint32_t max_open_zones; + int32_t nr_open_zones; + uint32_t max_active_zones; + int32_t nr_active_zones; + + unsigned long flags; + + QTAILQ_HEAD(, NvmeZone) exp_open_zones; + QTAILQ_HEAD(, NvmeZone) imp_open_zones; + QTAILQ_HEAD(, NvmeZone) closed_zones; + QTAILQ_HEAD(, NvmeZone) full_zones; +} NvmeNamespaceZoned; + typedef struct NvmeNamespace { DeviceState parent_obj; BlockConf blkconf; @@ -132,27 +163,17 @@ typedef struct NvmeNamespace { QTAILQ_ENTRY(NvmeNamespace) entry; - NvmeIdNsZoned *id_ns_zoned; - NvmeZone *zone_array; - QTAILQ_HEAD(, NvmeZone) exp_open_zones; - QTAILQ_HEAD(, NvmeZone) imp_open_zones; - QTAILQ_HEAD(, NvmeZone) closed_zones; - QTAILQ_HEAD(, NvmeZone) full_zones; - uint32_t num_zones; - uint64_t zone_size; - uint64_t zone_capacity; - uint32_t zone_size_log2; - uint8_t *zd_extensions; - int32_t nr_open_zones; - int32_t nr_active_zones; - NvmeNamespaceParams params; struct { uint32_t err_rec; } features; + + NvmeNamespaceZoned zoned; } NvmeNamespace; +#define NVME_NAMESPACE_ZONED(ns) (&(ns)->zoned) + static inline uint32_t nvme_nsid(NvmeNamespace *ns) { if (ns) { @@ -188,6 +209,11 @@ void nvme_ns_drain(NvmeNamespace *ns); void nvme_ns_shutdown(NvmeNamespace *ns); void nvme_ns_cleanup(NvmeNamespace *ns); +static inline bool nvme_ns_zoned(NvmeNamespace *ns) +{ + return ns->csi == NVME_CSI_ZONED; +} + typedef struct NvmeAsyncEvent { QTAILQ_ENTRY(NvmeAsyncEvent) entry; NvmeAerResult result; diff --git a/hw/nvme/zns.h b/hw/nvme/zns.h index 609db6eda7e5..967adc62d730 100644 --- a/hw/nvme/zns.h +++ b/hw/nvme/zns.h @@ -1,5 +1,5 @@ -#ifndef HW_NVME_ZONED_H -#define HW_NVME_ZONED_H +#ifndef HW_NVME_ZNS_H +#define HW_NVME_ZNS_H #include "qemu/units.h" @@ -7,20 +7,20 @@ #define NVME_DEFAULT_ZONE_SIZE (128 * MiB) -static inline NvmeZoneState nvme_zns_zs(NvmeZone *zone) +static inline NvmeZoneState nvme_zns_state(NvmeZone *zone) { return zone->d.zs >> 4; } -static inline void nvme_zns_set_zs(NvmeZone *zone, NvmeZoneState state) +static inline void nvme_zns_set_state(NvmeZone *zone, NvmeZoneState state) { zone->d.zs = state << 4; } -static inline uint64_t nvme_zns_read_boundary(NvmeNamespace *ns, +static inline uint64_t nvme_zns_read_boundary(NvmeNamespaceZoned *zoned, NvmeZone *zone) { - return zone->d.zslba + ns->zone_size; + return zone->d.zslba + zoned->zone_size; } static inline uint64_t nvme_zns_write_boundary(NvmeZone *zone) @@ -30,68 +30,70 @@ static inline uint64_t nvme_zns_write_boundary(NvmeZone *zone) static inline bool nvme_zns_wp_valid(NvmeZone *zone) { - uint8_t st = nvme_zns_zs(zone); + uint8_t st = nvme_zns_state(zone); return st != NVME_ZONE_STATE_FULL && st != NVME_ZONE_STATE_READ_ONLY && st != NVME_ZONE_STATE_OFFLINE; } -static inline uint32_t nvme_zns_zidx(NvmeNamespace *ns, uint64_t slba) +static inline uint32_t nvme_zns_zidx(NvmeNamespaceZoned *zoned, + uint64_t slba) { - return ns->zone_size_log2 > 0 ? slba >> ns->zone_size_log2 : - slba / ns->zone_size; + return zoned->zone_size_log2 > 0 ? + slba >> zoned->zone_size_log2 : slba / zoned->zone_size; } -static inline NvmeZone *nvme_zns_get_by_slba(NvmeNamespace *ns, uint64_t slba) +static inline NvmeZone *nvme_zns_get_by_slba(NvmeNamespaceZoned *zoned, + uint64_t slba) { - uint32_t zone_idx = nvme_zns_zidx(ns, slba); + uint32_t zone_idx = nvme_zns_zidx(zoned, slba); - assert(zone_idx < ns->num_zones); - return &ns->zone_array[zone_idx]; + assert(zone_idx < zoned->num_zones); + return &zoned->zone_array[zone_idx]; } -static inline uint8_t *nvme_zns_zde(NvmeNamespace *ns, uint32_t zone_idx) +static inline uint8_t *nvme_zns_zde(NvmeNamespaceZoned *zoned, + uint32_t zone_idx) { - return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size]; + return &zoned->zd_extensions[zone_idx * zoned->zd_extension_size]; } -static inline void nvme_zns_aor_inc_open(NvmeNamespace *ns) +static inline void nvme_zns_aor_inc_open(NvmeNamespaceZoned *zoned) { - assert(ns->nr_open_zones >= 0); - if (ns->params.max_open_zones) { - ns->nr_open_zones++; - assert(ns->nr_open_zones <= ns->params.max_open_zones); + assert(zoned->nr_open_zones >= 0); + if (zoned->max_open_zones) { + zoned->nr_open_zones++; + assert(zoned->nr_open_zones <= zoned->max_open_zones); } } -static inline void nvme_zns_aor_dec_open(NvmeNamespace *ns) +static inline void nvme_zns_aor_dec_open(NvmeNamespaceZoned *zoned) { - if (ns->params.max_open_zones) { - assert(ns->nr_open_zones > 0); - ns->nr_open_zones--; + if (zoned->max_open_zones) { + assert(zoned->nr_open_zones > 0); + zoned->nr_open_zones--; } - assert(ns->nr_open_zones >= 0); + assert(zoned->nr_open_zones >= 0); } -static inline void nvme_zns_aor_inc_active(NvmeNamespace *ns) +static inline void nvme_zns_aor_inc_active(NvmeNamespaceZoned *zoned) { - assert(ns->nr_active_zones >= 0); - if (ns->params.max_active_zones) { - ns->nr_active_zones++; - assert(ns->nr_active_zones <= ns->params.max_active_zones); + assert(zoned->nr_active_zones >= 0); + if (zoned->max_active_zones) { + zoned->nr_active_zones++; + assert(zoned->nr_active_zones <= zoned->max_active_zones); } } -static inline void nvme_zns_aor_dec_active(NvmeNamespace *ns) +static inline void nvme_zns_aor_dec_active(NvmeNamespaceZoned *zoned) { - if (ns->params.max_active_zones) { - assert(ns->nr_active_zones > 0); - ns->nr_active_zones--; - assert(ns->nr_active_zones >= ns->nr_open_zones); + if (zoned->max_active_zones) { + assert(zoned->nr_active_zones > 0); + zoned->nr_active_zones--; + assert(zoned->nr_active_zones >= zoned->nr_open_zones); } - assert(ns->nr_active_zones >= 0); + assert(zoned->nr_active_zones >= 0); } - -#endif /* HW_NVME_ZONED_H */ +#endif /* HW_NVME_ZNS_H */ diff --git a/include/block/nvme.h b/include/block/nvme.h index e3bd47bf76ab..2bcabe561589 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -1338,6 +1338,10 @@ enum NvmeCsi { #define NVME_SET_CSI(vec, csi) (vec |= (uint8_t)(1 << (csi))) +enum NvmeIdNsZonedOzcs { + NVME_ID_NS_ZONED_OZCS_CROSS_READ = 1 << 0, +}; + typedef struct QEMU_PACKED NvmeIdNsZoned { uint16_t zoc; uint16_t ozcs; From patchwork Mon Sep 27 05:17:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=lHyEiQQN; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=nffnDt/7; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHryK6PPQz9t5m for ; Mon, 27 Sep 2021 15:38:01 +1000 (AEST) Received: from localhost ([::1]:59162 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjKx-0001qj-Fi for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:37:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34148) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2C-00033K-BS; Mon, 27 Sep 2021 01:18:36 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:33343) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj27-00007v-US; Mon, 27 Sep 2021 01:18:36 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailnew.west.internal (Postfix) with ESMTP id 63E162B01209; Mon, 27 Sep 2021 01:18:29 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Mon, 27 Sep 2021 01:18:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=6Gp6JDGh1KEni +uJQ/Fm425+7Qfo780LTGzmEzft2AE=; b=lHyEiQQNXSAcL9MrVG5UHODOtSaSA cEY6ZrCrhUZL1TF8KRnTNPu3jkd2w9FvsGE0WfHAF1IaygqcEz4F2NbwvBHR3rl5 Q6PZ5AvPUjdF9fRuXDtODydKDnZcliADXupQCmEcTntSLE/yvi3Ub+2l67/Rfbf8 +uXifLUbmVfSszzgeie/05fF9/TLjSHhC83b5JeVOQ82yGbIxOiyZkyWq1DEr3tR GQL96FltYFo3Bw4d+Yd61rEFFd2Xbs8MsYRB9PwfEWYlR479puga25eS3ghg3oGR MQ0c7cxh/WY5KHFkk4vjgvLjBNE04y8v5LzOP89Q9dpE26jIxe/F8EQ+A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=6Gp6JDGh1KEni+uJQ/Fm425+7Qfo780LTGzmEzft2AE=; b=nffnDt/7 EefPCnbE5jfuj5EWJssY/M3Bzr2jn4+bkMtwE2xd7JzdztRqxPSuE8gnFCccAkxy nCSeX3WNfPDcCJzu8K5inNsD+iRfvDsu3k9VlPM+o2gw/mZK/+sI3uDKaVZBjtqM 8wt/Bd2iHthx8awPx/oXWj8Xd5ReibUcMhMEMMfe2kMDgMRS+zZoy8MEHOGfOugj idmaQ9l41WV7KTgqFyNL20eBFK4YoAnwCK65fND7SPu1rabqqbXIHIpG5BmN8SUK AEZu4LU4Nwcmd6+pl262o9aRTnSyauclKQFFUTK6F6nf6w+tqDmb7NJJN4cY2aNh J98QB4yFcHeSZw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:26 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 06/16] hw/nvme: move nvm namespace members to separate struct Date: Mon, 27 Sep 2021 07:17:49 +0200 Message-Id: <20210927051759.447305-7-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 282 +++++++++++++++++++++++++++---------------------- hw/nvme/dif.c | 101 +++++++++--------- hw/nvme/dif.h | 12 +-- hw/nvme/ns.c | 72 +++++++------ hw/nvme/nvme.h | 45 +++++--- 5 files changed, 290 insertions(+), 222 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index e357329d85b8..026dfaa71bda 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -528,11 +528,11 @@ static inline void nvme_sg_unmap(NvmeSg *sg) * holds both data and metadata. This function splits the data and metadata * into two separate QSG/IOVs. */ -static void nvme_sg_split(NvmeSg *sg, NvmeNamespace *ns, NvmeSg *data, +static void nvme_sg_split(NvmeSg *sg, NvmeNamespaceNvm *nvm, NvmeSg *data, NvmeSg *mdata) { NvmeSg *dst = data; - uint32_t trans_len, count = ns->lbasz; + uint32_t trans_len, count = nvm->lbasz; uint64_t offset = 0; bool dma = sg->flags & NVME_SG_DMA; size_t sge_len; @@ -564,7 +564,7 @@ static void nvme_sg_split(NvmeSg *sg, NvmeNamespace *ns, NvmeSg *data, if (count == 0) { dst = (dst == data) ? mdata : data; - count = (dst == data) ? ns->lbasz : ns->lbaf.ms; + count = (dst == data) ? nvm->lbasz : nvm->lbaf.ms; } if (sge_len == offset) { @@ -1029,17 +1029,17 @@ static uint16_t nvme_map_mptr(NvmeCtrl *n, NvmeSg *sg, size_t len, static uint16_t nvme_map_data(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) { - NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; - bool pi = !!NVME_ID_NS_DPS_TYPE(ns->id_ns.dps); + bool pi = !!NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps); bool pract = !!(le16_to_cpu(rw->control) & NVME_RW_PRINFO_PRACT); - size_t len = nvme_l2b(ns, nlb); + size_t len = nvme_l2b(nvm, nlb); uint16_t status; - if (nvme_ns_ext(ns) && !(pi && pract && ns->lbaf.ms == 8)) { + if (nvme_ns_ext(nvm) && !(pi && pract && nvm->lbaf.ms == 8)) { NvmeSg sg; - len += nvme_m2b(ns, nlb); + len += nvme_m2b(nvm, nlb); status = nvme_map_dptr(n, &sg, len, &req->cmd); if (status) { @@ -1047,7 +1047,7 @@ static uint16_t nvme_map_data(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) } nvme_sg_init(n, &req->sg, sg.flags & NVME_SG_DMA); - nvme_sg_split(&sg, ns, &req->sg, NULL); + nvme_sg_split(&sg, nvm, &req->sg, NULL); nvme_sg_unmap(&sg); return NVME_SUCCESS; @@ -1058,14 +1058,14 @@ static uint16_t nvme_map_data(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) static uint16_t nvme_map_mdata(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) { - NvmeNamespace *ns = req->ns; - size_t len = nvme_m2b(ns, nlb); + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); + size_t len = nvme_m2b(nvm, nlb); uint16_t status; - if (nvme_ns_ext(ns)) { + if (nvme_ns_ext(nvm)) { NvmeSg sg; - len += nvme_l2b(ns, nlb); + len += nvme_l2b(nvm, nlb); status = nvme_map_dptr(n, &sg, len, &req->cmd); if (status) { @@ -1073,7 +1073,7 @@ static uint16_t nvme_map_mdata(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) } nvme_sg_init(n, &req->sg, sg.flags & NVME_SG_DMA); - nvme_sg_split(&sg, ns, NULL, &req->sg); + nvme_sg_split(&sg, nvm, NULL, &req->sg); nvme_sg_unmap(&sg); return NVME_SUCCESS; @@ -1209,14 +1209,14 @@ static inline uint16_t nvme_h2c(NvmeCtrl *n, uint8_t *ptr, uint32_t len, uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len, NvmeTxDirection dir, NvmeRequest *req) { - NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; - bool pi = !!NVME_ID_NS_DPS_TYPE(ns->id_ns.dps); + bool pi = !!NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps); bool pract = !!(le16_to_cpu(rw->control) & NVME_RW_PRINFO_PRACT); - if (nvme_ns_ext(ns) && !(pi && pract && ns->lbaf.ms == 8)) { - return nvme_tx_interleaved(n, &req->sg, ptr, len, ns->lbasz, - ns->lbaf.ms, 0, dir); + if (nvme_ns_ext(nvm) && !(pi && pract && nvm->lbaf.ms == 8)) { + return nvme_tx_interleaved(n, &req->sg, ptr, len, nvm->lbasz, + nvm->lbaf.ms, 0, dir); } return nvme_tx(n, &req->sg, ptr, len, dir); @@ -1225,12 +1225,12 @@ uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len, uint16_t nvme_bounce_mdata(NvmeCtrl *n, uint8_t *ptr, uint32_t len, NvmeTxDirection dir, NvmeRequest *req) { - NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); uint16_t status; - if (nvme_ns_ext(ns)) { - return nvme_tx_interleaved(n, &req->sg, ptr, len, ns->lbaf.ms, - ns->lbasz, ns->lbasz, dir); + if (nvme_ns_ext(nvm)) { + return nvme_tx_interleaved(n, &req->sg, ptr, len, nvm->lbaf.ms, + nvm->lbasz, nvm->lbasz, dir); } nvme_sg_unmap(&req->sg); @@ -1448,10 +1448,10 @@ static inline uint16_t nvme_check_mdts(NvmeCtrl *n, size_t len) return NVME_SUCCESS; } -static inline uint16_t nvme_check_bounds(NvmeNamespace *ns, uint64_t slba, +static inline uint16_t nvme_check_bounds(NvmeNamespaceNvm *nvm, uint64_t slba, uint32_t nlb) { - uint64_t nsze = le64_to_cpu(ns->id_ns.nsze); + uint64_t nsze = le64_to_cpu(nvm->id_ns.nsze); if (unlikely(UINT64_MAX - slba < nlb || slba + nlb > nsze)) { trace_pci_nvme_err_invalid_lba_range(slba, nlb, nsze); @@ -1464,10 +1464,11 @@ static inline uint16_t nvme_check_bounds(NvmeNamespace *ns, uint64_t slba, static int nvme_block_status_all(NvmeNamespace *ns, uint64_t slba, uint32_t nlb, int flags) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockDriverState *bs = blk_bs(ns->blkconf.blk); - int64_t pnum = 0, bytes = nvme_l2b(ns, nlb); - int64_t offset = nvme_l2b(ns, slba); + int64_t pnum = 0, bytes = nvme_l2b(nvm, nlb); + int64_t offset = nvme_l2b(nvm, slba); int ret; /* @@ -1888,6 +1889,7 @@ static void nvme_rw_cb(void *opaque, int ret) { NvmeRequest *req = opaque; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = ns->blkconf.blk; @@ -1897,14 +1899,14 @@ static void nvme_rw_cb(void *opaque, int ret) goto out; } - if (ns->lbaf.ms) { + if (nvm->lbaf.ms) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; - uint64_t offset = nvme_moff(ns, slba); + uint64_t offset = nvme_moff(nvm, slba); if (req->cmd.opcode == NVME_CMD_WRITE_ZEROES) { - size_t mlen = nvme_m2b(ns, nlb); + size_t mlen = nvme_m2b(nvm, nlb); req->aiocb = blk_aio_pwrite_zeroes(blk, offset, mlen, BDRV_REQ_MAY_UNMAP, @@ -1912,7 +1914,7 @@ static void nvme_rw_cb(void *opaque, int ret) return; } - if (nvme_ns_ext(ns) || req->cmd.mptr) { + if (nvme_ns_ext(nvm) || req->cmd.mptr) { uint16_t status; nvme_sg_unmap(&req->sg); @@ -1939,6 +1941,7 @@ static void nvme_verify_cb(void *opaque, int ret) NvmeBounceContext *ctx = opaque; NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = ns->blkconf.blk; BlockAcctCookie *acct = &req->acct; BlockAcctStats *stats = blk_get_stats(blk); @@ -1960,7 +1963,7 @@ static void nvme_verify_cb(void *opaque, int ret) block_acct_done(stats, acct); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { status = nvme_dif_mangle_mdata(ns, ctx->mdata.bounce, ctx->mdata.iov.size, slba); if (status) { @@ -1968,7 +1971,7 @@ static void nvme_verify_cb(void *opaque, int ret) goto out; } - req->status = nvme_dif_check(ns, ctx->data.bounce, ctx->data.iov.size, + req->status = nvme_dif_check(nvm, ctx->data.bounce, ctx->data.iov.size, ctx->mdata.bounce, ctx->mdata.iov.size, prinfo, slba, apptag, appmask, &reftag); } @@ -1991,11 +1994,12 @@ static void nvme_verify_mdata_in_cb(void *opaque, int ret) NvmeBounceContext *ctx = opaque; NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; - size_t mlen = nvme_m2b(ns, nlb); - uint64_t offset = nvme_moff(ns, slba); + size_t mlen = nvme_m2b(nvm, nlb); + uint64_t offset = nvme_moff(nvm, slba); BlockBackend *blk = ns->blkconf.blk; trace_pci_nvme_verify_mdata_in_cb(nvme_cid(req), blk_name(blk)); @@ -2033,6 +2037,7 @@ static void nvme_compare_mdata_cb(void *opaque, int ret) { NvmeRequest *req = opaque; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCtrl *n = nvme_ctrl(req); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); @@ -2063,14 +2068,14 @@ static void nvme_compare_mdata_cb(void *opaque, int ret) goto out; } - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { uint64_t slba = le64_to_cpu(rw->slba); uint8_t *bufp; uint8_t *mbufp = ctx->mdata.bounce; uint8_t *end = mbufp + ctx->mdata.iov.size; int16_t pil = 0; - status = nvme_dif_check(ns, ctx->data.bounce, ctx->data.iov.size, + status = nvme_dif_check(nvm, ctx->data.bounce, ctx->data.iov.size, ctx->mdata.bounce, ctx->mdata.iov.size, prinfo, slba, apptag, appmask, &reftag); if (status) { @@ -2082,12 +2087,12 @@ static void nvme_compare_mdata_cb(void *opaque, int ret) * When formatted with protection information, do not compare the DIF * tuple. */ - if (!(ns->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { - pil = ns->lbaf.ms - sizeof(NvmeDifTuple); + if (!(nvm->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { + pil = nvm->lbaf.ms - sizeof(NvmeDifTuple); } - for (bufp = buf; mbufp < end; bufp += ns->lbaf.ms, mbufp += ns->lbaf.ms) { - if (memcmp(bufp + pil, mbufp + pil, ns->lbaf.ms - pil)) { + for (bufp = buf; mbufp < end; bufp += nvm->lbaf.ms, mbufp += nvm->lbaf.ms) { + if (memcmp(bufp + pil, mbufp + pil, nvm->lbaf.ms - pil)) { req->status = NVME_CMP_FAILURE; goto out; } @@ -2120,6 +2125,7 @@ static void nvme_compare_data_cb(void *opaque, int ret) NvmeRequest *req = opaque; NvmeCtrl *n = nvme_ctrl(req); NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = ns->blkconf.blk; BlockAcctCookie *acct = &req->acct; BlockAcctStats *stats = blk_get_stats(blk); @@ -2150,12 +2156,12 @@ static void nvme_compare_data_cb(void *opaque, int ret) goto out; } - if (ns->lbaf.ms) { + if (nvm->lbaf.ms) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; - size_t mlen = nvme_m2b(ns, nlb); - uint64_t offset = nvme_moff(ns, slba); + size_t mlen = nvme_m2b(nvm, nlb); + uint64_t offset = nvme_moff(nvm, slba); ctx->mdata.bounce = g_malloc(mlen); @@ -2232,6 +2238,7 @@ static void nvme_dsm_md_cb(void *opaque, int ret) NvmeDSMAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeDsmRange *range; uint64_t slba; uint32_t nlb; @@ -2241,7 +2248,7 @@ static void nvme_dsm_md_cb(void *opaque, int ret) goto done; } - if (!ns->lbaf.ms) { + if (!nvm->lbaf.ms) { nvme_dsm_cb(iocb, 0); return; } @@ -2265,8 +2272,8 @@ static void nvme_dsm_md_cb(void *opaque, int ret) nvme_dsm_cb(iocb, 0); } - iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, nvme_moff(ns, slba), - nvme_m2b(ns, nlb), BDRV_REQ_MAY_UNMAP, + iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, nvme_moff(nvm, slba), + nvme_m2b(nvm, nlb), BDRV_REQ_MAY_UNMAP, nvme_dsm_cb, iocb); return; @@ -2281,6 +2288,7 @@ static void nvme_dsm_cb(void *opaque, int ret) NvmeRequest *req = iocb->req; NvmeCtrl *n = nvme_ctrl(req); NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeDsmRange *range; uint64_t slba; uint32_t nlb; @@ -2306,14 +2314,14 @@ next: goto next; } - if (nvme_check_bounds(ns, slba, nlb)) { + if (nvme_check_bounds(nvm, slba, nlb)) { trace_pci_nvme_err_invalid_lba_range(slba, nlb, - ns->id_ns.nsze); + nvm->id_ns.nsze); goto next; } - iocb->aiocb = blk_aio_pdiscard(ns->blkconf.blk, nvme_l2b(ns, slba), - nvme_l2b(ns, nlb), + iocb->aiocb = blk_aio_pdiscard(ns->blkconf.blk, nvme_l2b(nvm, slba), + nvme_l2b(nvm, nlb), nvme_dsm_md_cb, iocb); return; @@ -2362,11 +2370,12 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = ns->blkconf.blk; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; - size_t len = nvme_l2b(ns, nlb); - int64_t offset = nvme_l2b(ns, slba); + size_t len = nvme_l2b(nvm, nlb); + int64_t offset = nvme_l2b(nvm, slba); uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); uint32_t reftag = le32_to_cpu(rw->reftag); NvmeBounceContext *ctx = NULL; @@ -2374,8 +2383,8 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest *req) trace_pci_nvme_verify(nvme_cid(req), nvme_nsid(ns), slba, nlb); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { - status = nvme_check_prinfo(ns, prinfo, slba, reftag); + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { + status = nvme_check_prinfo(nvm, prinfo, slba, reftag); if (status) { return status; } @@ -2389,7 +2398,7 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest *req) return NVME_INVALID_FIELD | NVME_DNR; } - status = nvme_check_bounds(ns, slba, nlb); + status = nvme_check_bounds(nvm, slba, nlb); if (status) { return status; } @@ -2519,6 +2528,7 @@ static void nvme_copy_out_cb(void *opaque, int ret) NvmeCopyAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCopySourceRange *range; uint32_t nlb; size_t mlen; @@ -2531,7 +2541,7 @@ static void nvme_copy_out_cb(void *opaque, int ret) goto out; } - if (!ns->lbaf.ms) { + if (!nvm->lbaf.ms) { nvme_copy_out_completed_cb(iocb, 0); return; } @@ -2539,13 +2549,13 @@ static void nvme_copy_out_cb(void *opaque, int ret) range = &iocb->ranges[iocb->idx]; nlb = le32_to_cpu(range->nlb) + 1; - mlen = nvme_m2b(ns, nlb); - mbounce = iocb->bounce + nvme_l2b(ns, nlb); + mlen = nvme_m2b(nvm, nlb); + mbounce = iocb->bounce + nvme_l2b(nvm, nlb); qemu_iovec_reset(&iocb->iov); qemu_iovec_add(&iocb->iov, mbounce, mlen); - iocb->aiocb = blk_aio_pwritev(ns->blkconf.blk, nvme_moff(ns, iocb->slba), + iocb->aiocb = blk_aio_pwritev(ns->blkconf.blk, nvme_moff(nvm, iocb->slba), &iocb->iov, 0, nvme_copy_out_completed_cb, iocb); @@ -2560,6 +2570,7 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) NvmeCopyAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCopySourceRange *range; uint32_t nlb; size_t len; @@ -2574,11 +2585,11 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) range = &iocb->ranges[iocb->idx]; nlb = le32_to_cpu(range->nlb) + 1; - len = nvme_l2b(ns, nlb); + len = nvme_l2b(nvm, nlb); trace_pci_nvme_copy_out(iocb->slba, nlb); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { NvmeCopyCmd *copy = (NvmeCopyCmd *)&req->cmd; uint16_t prinfor = ((copy->control[0] >> 4) & 0xf); @@ -2589,10 +2600,10 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) uint32_t reftag = le32_to_cpu(range->reftag); uint64_t slba = le64_to_cpu(range->slba); - size_t mlen = nvme_m2b(ns, nlb); - uint8_t *mbounce = iocb->bounce + nvme_l2b(ns, nlb); + size_t mlen = nvme_m2b(nvm, nlb); + uint8_t *mbounce = iocb->bounce + nvme_l2b(nvm, nlb); - status = nvme_dif_check(ns, iocb->bounce, len, mbounce, mlen, prinfor, + status = nvme_dif_check(nvm, iocb->bounce, len, mbounce, mlen, prinfor, slba, apptag, appmask, &reftag); if (status) { goto invalid; @@ -2602,15 +2613,15 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) appmask = le16_to_cpu(copy->appmask); if (prinfow & NVME_PRINFO_PRACT) { - status = nvme_check_prinfo(ns, prinfow, iocb->slba, iocb->reftag); + status = nvme_check_prinfo(nvm, prinfow, iocb->slba, iocb->reftag); if (status) { goto invalid; } - nvme_dif_pract_generate_dif(ns, iocb->bounce, len, mbounce, mlen, + nvme_dif_pract_generate_dif(nvm, iocb->bounce, len, mbounce, mlen, apptag, &iocb->reftag); } else { - status = nvme_dif_check(ns, iocb->bounce, len, mbounce, mlen, + status = nvme_dif_check(nvm, iocb->bounce, len, mbounce, mlen, prinfow, iocb->slba, apptag, appmask, &iocb->reftag); if (status) { @@ -2619,7 +2630,7 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) } } - status = nvme_check_bounds(ns, iocb->slba, nlb); + status = nvme_check_bounds(nvm, iocb->slba, nlb); if (status) { goto invalid; } @@ -2636,7 +2647,7 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) qemu_iovec_reset(&iocb->iov); qemu_iovec_add(&iocb->iov, iocb->bounce, len); - iocb->aiocb = blk_aio_pwritev(ns->blkconf.blk, nvme_l2b(ns, iocb->slba), + iocb->aiocb = blk_aio_pwritev(ns->blkconf.blk, nvme_l2b(nvm, iocb->slba), &iocb->iov, 0, nvme_copy_out_cb, iocb); return; @@ -2659,6 +2670,7 @@ static void nvme_copy_in_cb(void *opaque, int ret) NvmeCopyAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCopySourceRange *range; uint64_t slba; uint32_t nlb; @@ -2670,7 +2682,7 @@ static void nvme_copy_in_cb(void *opaque, int ret) goto out; } - if (!ns->lbaf.ms) { + if (!nvm->lbaf.ms) { nvme_copy_in_completed_cb(iocb, 0); return; } @@ -2680,10 +2692,10 @@ static void nvme_copy_in_cb(void *opaque, int ret) nlb = le32_to_cpu(range->nlb) + 1; qemu_iovec_reset(&iocb->iov); - qemu_iovec_add(&iocb->iov, iocb->bounce + nvme_l2b(ns, nlb), - nvme_m2b(ns, nlb)); + qemu_iovec_add(&iocb->iov, iocb->bounce + nvme_l2b(nvm, nlb), + nvme_m2b(nvm, nlb)); - iocb->aiocb = blk_aio_preadv(ns->blkconf.blk, nvme_moff(ns, slba), + iocb->aiocb = blk_aio_preadv(ns->blkconf.blk, nvme_moff(nvm, slba), &iocb->iov, 0, nvme_copy_in_completed_cb, iocb); return; @@ -2697,6 +2709,7 @@ static void nvme_copy_cb(void *opaque, int ret) NvmeCopyAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCopySourceRange *range; uint64_t slba; uint32_t nlb; @@ -2717,16 +2730,16 @@ static void nvme_copy_cb(void *opaque, int ret) range = &iocb->ranges[iocb->idx]; slba = le64_to_cpu(range->slba); nlb = le32_to_cpu(range->nlb) + 1; - len = nvme_l2b(ns, nlb); + len = nvme_l2b(nvm, nlb); trace_pci_nvme_copy_source_range(slba, nlb); - if (nlb > le16_to_cpu(ns->id_ns.mssrl)) { + if (nlb > le16_to_cpu(nvm->id_ns.mssrl)) { status = NVME_CMD_SIZE_LIMIT | NVME_DNR; goto invalid; } - status = nvme_check_bounds(ns, slba, nlb); + status = nvme_check_bounds(nvm, slba, nlb); if (status) { goto invalid; } @@ -2748,7 +2761,7 @@ static void nvme_copy_cb(void *opaque, int ret) qemu_iovec_reset(&iocb->iov); qemu_iovec_add(&iocb->iov, iocb->bounce, len); - iocb->aiocb = blk_aio_preadv(ns->blkconf.blk, nvme_l2b(ns, slba), + iocb->aiocb = blk_aio_preadv(ns->blkconf.blk, nvme_l2b(nvm, slba), &iocb->iov, 0, nvme_copy_in_cb, iocb); return; @@ -2765,6 +2778,7 @@ done: static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) { NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCopyCmd *copy = (NvmeCopyCmd *)&req->cmd; NvmeCopyAIOCB *iocb = blk_aio_get(&nvme_copy_aiocb_info, ns->blkconf.blk, nvme_misc_cb, req); @@ -2780,7 +2794,7 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) iocb->ranges = NULL; iocb->zone = NULL; - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps) && + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps) && ((prinfor & NVME_PRINFO_PRACT) != (prinfow & NVME_PRINFO_PRACT))) { status = NVME_INVALID_FIELD | NVME_DNR; goto invalid; @@ -2792,7 +2806,7 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) goto invalid; } - if (nr > ns->id_ns.msrc + 1) { + if (nr > nvm->id_ns.msrc + 1) { status = NVME_CMD_SIZE_LIMIT | NVME_DNR; goto invalid; } @@ -2828,8 +2842,8 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) iocb->nr = nr; iocb->idx = 0; iocb->reftag = le32_to_cpu(copy->reftag); - iocb->bounce = g_malloc_n(le16_to_cpu(ns->id_ns.mssrl), - ns->lbasz + ns->lbaf.ms); + iocb->bounce = g_malloc_n(le16_to_cpu(nvm->id_ns.mssrl), + nvm->lbasz + nvm->lbaf.ms); qemu_iovec_init(&iocb->iov, 1); @@ -2853,24 +2867,25 @@ static uint16_t nvme_compare(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = ns->blkconf.blk; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); - size_t data_len = nvme_l2b(ns, nlb); + size_t data_len = nvme_l2b(nvm, nlb); size_t len = data_len; - int64_t offset = nvme_l2b(ns, slba); + int64_t offset = nvme_l2b(nvm, slba); struct nvme_compare_ctx *ctx = NULL; uint16_t status; trace_pci_nvme_compare(nvme_cid(req), nvme_nsid(ns), slba, nlb); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps) && (prinfo & NVME_PRINFO_PRACT)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps) && (prinfo & NVME_PRINFO_PRACT)) { return NVME_INVALID_PROT_INFO | NVME_DNR; } - if (nvme_ns_ext(ns)) { - len += nvme_m2b(ns, nlb); + if (nvme_ns_ext(nvm)) { + len += nvme_m2b(nvm, nlb); } status = nvme_check_mdts(n, len); @@ -2878,7 +2893,7 @@ static uint16_t nvme_compare(NvmeCtrl *n, NvmeRequest *req) return status; } - status = nvme_check_bounds(ns, slba, nlb); + status = nvme_check_bounds(nvm, slba, nlb); if (status) { return status; } @@ -3051,22 +3066,23 @@ static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); - uint64_t data_size = nvme_l2b(ns, nlb); + uint64_t data_size = nvme_l2b(nvm, nlb); uint64_t mapped_size = data_size; uint64_t data_offset; BlockBackend *blk = ns->blkconf.blk; uint16_t status; - if (nvme_ns_ext(ns)) { - mapped_size += nvme_m2b(ns, nlb); + if (nvme_ns_ext(nvm)) { + mapped_size += nvme_m2b(nvm, nlb); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { bool pract = prinfo & NVME_PRINFO_PRACT; - if (pract && ns->lbaf.ms == 8) { + if (pract && nvm->lbaf.ms == 8) { mapped_size = data_size; } } @@ -3079,7 +3095,7 @@ static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req) goto invalid; } - status = nvme_check_bounds(ns, slba, nlb); + status = nvme_check_bounds(nvm, slba, nlb); if (status) { goto invalid; } @@ -3099,7 +3115,7 @@ static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req) } } - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { return nvme_dif_rw(n, req); } @@ -3108,7 +3124,7 @@ static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req) goto invalid; } - data_offset = nvme_l2b(ns, slba); + data_offset = nvme_l2b(nvm, slba); block_acct_start(blk_get_stats(blk), &req->acct, data_size, BLOCK_ACCT_READ); @@ -3125,11 +3141,12 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = (uint32_t)le16_to_cpu(rw->nlb) + 1; uint16_t ctrl = le16_to_cpu(rw->control); uint8_t prinfo = NVME_RW_PRINFO(ctrl); - uint64_t data_size = nvme_l2b(ns, nlb); + uint64_t data_size = nvme_l2b(nvm, nlb); uint64_t mapped_size = data_size; uint64_t data_offset; NvmeZone *zone; @@ -3137,14 +3154,14 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, BlockBackend *blk = ns->blkconf.blk; uint16_t status; - if (nvme_ns_ext(ns)) { - mapped_size += nvme_m2b(ns, nlb); + if (nvme_ns_ext(nvm)) { + mapped_size += nvme_m2b(nvm, nlb); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { bool pract = prinfo & NVME_PRINFO_PRACT; - if (pract && ns->lbaf.ms == 8) { - mapped_size -= nvme_m2b(ns, nlb); + if (pract && nvm->lbaf.ms == 8) { + mapped_size -= nvme_m2b(nvm, nlb); } } } @@ -3159,7 +3176,7 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, } } - status = nvme_check_bounds(ns, slba, nlb); + status = nvme_check_bounds(nvm, slba, nlb); if (status) { goto invalid; } @@ -3189,7 +3206,7 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, rw->slba = cpu_to_le64(slba); res->slba = cpu_to_le64(slba); - switch (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + switch (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { case NVME_ID_NS_DPS_TYPE_1: if (!piremap) { return NVME_INVALID_PROT_INFO | NVME_DNR; @@ -3227,9 +3244,9 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, zone->w_ptr += nlb; } - data_offset = nvme_l2b(ns, slba); + data_offset = nvme_l2b(nvm, slba); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { return nvme_dif_rw(n, req); } @@ -3273,6 +3290,7 @@ static inline uint16_t nvme_zone_append(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_get_mgmt_zone_slba_idx(NvmeNamespace *ns, NvmeCmd *c, uint64_t *slba, uint32_t *zone_idx) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeNamespaceZoned *zoned; uint32_t dw10 = le32_to_cpu(c->cdw10); @@ -3286,8 +3304,8 @@ static uint16_t nvme_get_mgmt_zone_slba_idx(NvmeNamespace *ns, NvmeCmd *c, zoned = NVME_NAMESPACE_ZONED(ns); *slba = ((uint64_t)dw11) << 32 | dw10; - if (unlikely(*slba >= ns->id_ns.nsze)) { - trace_pci_nvme_err_invalid_lba_range(*slba, 0, ns->id_ns.nsze); + if (unlikely(*slba >= nvm->id_ns.nsze)) { + trace_pci_nvme_err_invalid_lba_range(*slba, 0, nvm->id_ns.nsze); *slba = 0; return NVME_LBA_RANGE | NVME_DNR; } @@ -3506,6 +3524,8 @@ static void nvme_zone_reset_epilogue_cb(void *opaque, int ret) NvmeZoneResetAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); int64_t moff; int count; @@ -3514,13 +3534,13 @@ static void nvme_zone_reset_epilogue_cb(void *opaque, int ret) return; } - if (!ns->lbaf.ms) { + if (!nvm->lbaf.ms) { nvme_zone_reset_cb(iocb, 0); return; } - moff = nvme_moff(ns, iocb->zone->d.zslba); - count = nvme_m2b(ns, NVME_NAMESPACE_ZONED(ns)->zone_size); + moff = nvme_moff(nvm, iocb->zone->d.zslba); + count = nvme_m2b(nvm, zoned->zone_size); iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, moff, count, BDRV_REQ_MAY_UNMAP, @@ -3533,6 +3553,7 @@ static void nvme_zone_reset_cb(void *opaque, int ret) NvmeZoneResetAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); if (ret < 0) { @@ -3573,8 +3594,8 @@ static void nvme_zone_reset_cb(void *opaque, int ret) trace_pci_nvme_zns_zone_reset(zone->d.zslba); iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, - nvme_l2b(ns, zone->d.zslba), - nvme_l2b(ns, zoned->zone_size), + nvme_l2b(nvm, zone->d.zslba), + nvme_l2b(nvm, zoned->zone_size), BDRV_REQ_MAY_UNMAP, nvme_zone_reset_epilogue_cb, iocb); @@ -4475,7 +4496,8 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req, bool active) } if (active || ns->csi == NVME_CSI_NVM) { - return nvme_c2h(n, (uint8_t *)&ns->id_ns, sizeof(NvmeIdNs), req); + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + return nvme_c2h(n, (uint8_t *)&nvm->id_ns, sizeof(NvmeIdNs), req); } return NVME_INVALID_CMD_SET | NVME_DNR; @@ -4994,6 +5016,7 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) { NvmeNamespace *ns = NULL; + NvmeNamespaceNvm *nvm; NvmeCmd *cmd = &req->cmd; uint32_t dw10 = le32_to_cpu(cmd->cdw10); @@ -5068,7 +5091,9 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) continue; } - if (NVME_ID_NS_NSFEAT_DULBE(ns->id_ns.nsfeat)) { + nvm = NVME_NAMESPACE_NVM(ns); + + if (NVME_ID_NS_NSFEAT_DULBE(nvm->id_ns.nsfeat)) { ns->features.err_rec = dw11; } } @@ -5077,7 +5102,8 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) } assert(ns); - if (NVME_ID_NS_NSFEAT_DULBE(ns->id_ns.nsfeat)) { + nvm = NVME_NAMESPACE_NVM(ns); + if (NVME_ID_NS_NSFEAT_DULBE(nvm->id_ns.nsfeat)) { ns->features.err_rec = dw11; } break; @@ -5159,12 +5185,15 @@ static void nvme_update_dmrsl(NvmeCtrl *n) for (nsid = 1; nsid <= NVME_MAX_NAMESPACES; nsid++) { NvmeNamespace *ns = nvme_ns(n, nsid); + NvmeNamespaceNvm *nvm; if (!ns) { continue; } + nvm = NVME_NAMESPACE_NVM(ns); + n->dmrsl = MIN_NON_ZERO(n->dmrsl, - BDRV_REQUEST_MAX_BYTES / nvme_l2b(ns, 1)); + BDRV_REQUEST_MAX_BYTES / nvme_l2b(nvm, 1)); } } @@ -5306,6 +5335,7 @@ static const AIOCBInfo nvme_format_aiocb_info = { static void nvme_format_set(NvmeNamespace *ns, NvmeCmd *cmd) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); uint32_t dw10 = le32_to_cpu(cmd->cdw10); uint8_t lbaf = dw10 & 0xf; uint8_t pi = (dw10 >> 5) & 0x7; @@ -5314,8 +5344,8 @@ static void nvme_format_set(NvmeNamespace *ns, NvmeCmd *cmd) trace_pci_nvme_format_set(ns->params.nsid, lbaf, mset, pi, pil); - ns->id_ns.dps = (pil << 3) | pi; - ns->id_ns.flbas = lbaf | (mset << 4); + nvm->id_ns.dps = (pil << 3) | pi; + nvm->id_ns.flbas = lbaf | (mset << 4); nvme_ns_init_format(ns); } @@ -5325,6 +5355,7 @@ static void nvme_format_ns_cb(void *opaque, int ret) NvmeFormatAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = iocb->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); int bytes; if (ret < 0) { @@ -5334,8 +5365,8 @@ static void nvme_format_ns_cb(void *opaque, int ret) assert(ns); - if (iocb->offset < ns->size) { - bytes = MIN(BDRV_REQUEST_MAX_BYTES, ns->size - iocb->offset); + if (iocb->offset < nvm->size) { + bytes = MIN(BDRV_REQUEST_MAX_BYTES, nvm->size - iocb->offset); iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, iocb->offset, bytes, BDRV_REQ_MAY_UNMAP, @@ -5357,15 +5388,17 @@ done: static uint16_t nvme_format_check(NvmeNamespace *ns, uint8_t lbaf, uint8_t pi) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + if (nvme_ns_zoned(ns)) { return NVME_INVALID_FORMAT | NVME_DNR; } - if (lbaf > ns->id_ns.nlbaf) { + if (lbaf > nvm->id_ns.nlbaf) { return NVME_INVALID_FORMAT | NVME_DNR; } - if (pi && (ns->id_ns.lbaf[lbaf].ms < sizeof(NvmeDifTuple))) { + if (pi && (nvm->id_ns.lbaf[lbaf].ms < sizeof(NvmeDifTuple))) { return NVME_INVALID_FORMAT | NVME_DNR; } @@ -6518,6 +6551,7 @@ static int nvme_init_subsys(NvmeCtrl *n, Error **errp) void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); uint32_t nsid = ns->params.nsid; assert(nsid && nsid <= NVME_MAX_NAMESPACES); @@ -6525,7 +6559,7 @@ void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns) ns->attached++; n->dmrsl = MIN_NON_ZERO(n->dmrsl, - BDRV_REQUEST_MAX_BYTES / nvme_l2b(ns, 1)); + BDRV_REQUEST_MAX_BYTES / nvme_l2b(nvm, 1)); } static void nvme_realize(PCIDevice *pci_dev, Error **errp) diff --git a/hw/nvme/dif.c b/hw/nvme/dif.c index cd0cea2b5ebd..26c7412eb523 100644 --- a/hw/nvme/dif.c +++ b/hw/nvme/dif.c @@ -16,10 +16,10 @@ #include "dif.h" #include "trace.h" -uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint8_t prinfo, uint64_t slba, - uint32_t reftag) +uint16_t nvme_check_prinfo(NvmeNamespaceNvm *nvm, uint8_t prinfo, + uint64_t slba, uint32_t reftag) { - if ((NVME_ID_NS_DPS_TYPE(ns->id_ns.dps) == NVME_ID_NS_DPS_TYPE_1) && + if ((NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps) == NVME_ID_NS_DPS_TYPE_1) && (prinfo & NVME_PRINFO_PRCHK_REF) && (slba & 0xffffffff) != reftag) { return NVME_INVALID_PROT_INFO | NVME_DNR; } @@ -40,23 +40,23 @@ static uint16_t crc_t10dif(uint16_t crc, const unsigned char *buffer, return crc; } -void nvme_dif_pract_generate_dif(NvmeNamespace *ns, uint8_t *buf, size_t len, - uint8_t *mbuf, size_t mlen, uint16_t apptag, - uint32_t *reftag) +void nvme_dif_pract_generate_dif(NvmeNamespaceNvm *nvm, uint8_t *buf, + size_t len, uint8_t *mbuf, size_t mlen, + uint16_t apptag, uint32_t *reftag) { uint8_t *end = buf + len; int16_t pil = 0; - if (!(ns->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { - pil = ns->lbaf.ms - sizeof(NvmeDifTuple); + if (!(nvm->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { + pil = nvm->lbaf.ms - sizeof(NvmeDifTuple); } - trace_pci_nvme_dif_pract_generate_dif(len, ns->lbasz, ns->lbasz + pil, + trace_pci_nvme_dif_pract_generate_dif(len, nvm->lbasz, nvm->lbasz + pil, apptag, *reftag); - for (; buf < end; buf += ns->lbasz, mbuf += ns->lbaf.ms) { + for (; buf < end; buf += nvm->lbasz, mbuf += nvm->lbaf.ms) { NvmeDifTuple *dif = (NvmeDifTuple *)(mbuf + pil); - uint16_t crc = crc_t10dif(0x0, buf, ns->lbasz); + uint16_t crc = crc_t10dif(0x0, buf, nvm->lbasz); if (pil) { crc = crc_t10dif(crc, mbuf, pil); @@ -66,18 +66,18 @@ void nvme_dif_pract_generate_dif(NvmeNamespace *ns, uint8_t *buf, size_t len, dif->apptag = cpu_to_be16(apptag); dif->reftag = cpu_to_be32(*reftag); - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps) != NVME_ID_NS_DPS_TYPE_3) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps) != NVME_ID_NS_DPS_TYPE_3) { (*reftag)++; } } } -static uint16_t nvme_dif_prchk(NvmeNamespace *ns, NvmeDifTuple *dif, +static uint16_t nvme_dif_prchk(NvmeNamespaceNvm *nvm, NvmeDifTuple *dif, uint8_t *buf, uint8_t *mbuf, size_t pil, uint8_t prinfo, uint16_t apptag, uint16_t appmask, uint32_t reftag) { - switch (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + switch (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { case NVME_ID_NS_DPS_TYPE_3: if (be32_to_cpu(dif->reftag) != 0xffffffff) { break; @@ -97,7 +97,7 @@ static uint16_t nvme_dif_prchk(NvmeNamespace *ns, NvmeDifTuple *dif, } if (prinfo & NVME_PRINFO_PRCHK_GUARD) { - uint16_t crc = crc_t10dif(0x0, buf, ns->lbasz); + uint16_t crc = crc_t10dif(0x0, buf, nvm->lbasz); if (pil) { crc = crc_t10dif(crc, mbuf, pil); @@ -130,7 +130,7 @@ static uint16_t nvme_dif_prchk(NvmeNamespace *ns, NvmeDifTuple *dif, return NVME_SUCCESS; } -uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, +uint16_t nvme_dif_check(NvmeNamespaceNvm *nvm, uint8_t *buf, size_t len, uint8_t *mbuf, size_t mlen, uint8_t prinfo, uint64_t slba, uint16_t apptag, uint16_t appmask, uint32_t *reftag) @@ -139,27 +139,27 @@ uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, int16_t pil = 0; uint16_t status; - status = nvme_check_prinfo(ns, prinfo, slba, *reftag); + status = nvme_check_prinfo(nvm, prinfo, slba, *reftag); if (status) { return status; } - if (!(ns->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { - pil = ns->lbaf.ms - sizeof(NvmeDifTuple); + if (!(nvm->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { + pil = nvm->lbaf.ms - sizeof(NvmeDifTuple); } - trace_pci_nvme_dif_check(prinfo, ns->lbasz + pil); + trace_pci_nvme_dif_check(prinfo, nvm->lbasz + pil); - for (; buf < end; buf += ns->lbasz, mbuf += ns->lbaf.ms) { + for (; buf < end; buf += nvm->lbasz, mbuf += nvm->lbaf.ms) { NvmeDifTuple *dif = (NvmeDifTuple *)(mbuf + pil); - status = nvme_dif_prchk(ns, dif, buf, mbuf, pil, prinfo, apptag, + status = nvme_dif_prchk(nvm, dif, buf, mbuf, pil, prinfo, apptag, appmask, *reftag); if (status) { return status; } - if (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps) != NVME_ID_NS_DPS_TYPE_3) { + if (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps) != NVME_ID_NS_DPS_TYPE_3) { (*reftag)++; } } @@ -170,21 +170,22 @@ uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, uint64_t slba) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = ns->blkconf.blk; BlockDriverState *bs = blk_bs(blk); - int64_t moffset = 0, offset = nvme_l2b(ns, slba); + int64_t moffset = 0, offset = nvme_l2b(nvm, slba); uint8_t *mbufp, *end; bool zeroed; int16_t pil = 0; - int64_t bytes = (mlen / ns->lbaf.ms) << ns->lbaf.ds; + int64_t bytes = (mlen / nvm->lbaf.ms) << nvm->lbaf.ds; int64_t pnum = 0; Error *err = NULL; - if (!(ns->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { - pil = ns->lbaf.ms - sizeof(NvmeDifTuple); + if (!(nvm->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT)) { + pil = nvm->lbaf.ms - sizeof(NvmeDifTuple); } do { @@ -206,15 +207,15 @@ uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, if (zeroed) { mbufp = mbuf + moffset; - mlen = (pnum >> ns->lbaf.ds) * ns->lbaf.ms; + mlen = (pnum >> nvm->lbaf.ds) * nvm->lbaf.ms; end = mbufp + mlen; - for (; mbufp < end; mbufp += ns->lbaf.ms) { + for (; mbufp < end; mbufp += nvm->lbaf.ms) { memset(mbufp + pil, 0xff, sizeof(NvmeDifTuple)); } } - moffset += (pnum >> ns->lbaf.ds) * ns->lbaf.ms; + moffset += (pnum >> nvm->lbaf.ds) * nvm->lbaf.ms; offset += pnum; } while (pnum != bytes); @@ -246,6 +247,7 @@ static void nvme_dif_rw_check_cb(void *opaque, int ret) NvmeBounceContext *ctx = opaque; NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCtrl *n = nvme_ctrl(req); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); @@ -269,7 +271,7 @@ static void nvme_dif_rw_check_cb(void *opaque, int ret) goto out; } - status = nvme_dif_check(ns, ctx->data.bounce, ctx->data.iov.size, + status = nvme_dif_check(nvm, ctx->data.bounce, ctx->data.iov.size, ctx->mdata.bounce, ctx->mdata.iov.size, prinfo, slba, apptag, appmask, &reftag); if (status) { @@ -284,7 +286,7 @@ static void nvme_dif_rw_check_cb(void *opaque, int ret) goto out; } - if (prinfo & NVME_PRINFO_PRACT && ns->lbaf.ms == 8) { + if (prinfo & NVME_PRINFO_PRACT && nvm->lbaf.ms == 8) { goto out; } @@ -303,11 +305,12 @@ static void nvme_dif_rw_mdata_in_cb(void *opaque, int ret) NvmeBounceContext *ctx = opaque; NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; - size_t mlen = nvme_m2b(ns, nlb); - uint64_t offset = nvme_moff(ns, slba); + size_t mlen = nvme_m2b(nvm, nlb); + uint64_t offset = nvme_moff(nvm, slba); BlockBackend *blk = ns->blkconf.blk; trace_pci_nvme_dif_rw_mdata_in_cb(nvme_cid(req), blk_name(blk)); @@ -334,9 +337,10 @@ static void nvme_dif_rw_mdata_out_cb(void *opaque, int ret) NvmeBounceContext *ctx = opaque; NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); - uint64_t offset = nvme_moff(ns, slba); + uint64_t offset = nvme_moff(nvm, slba); BlockBackend *blk = ns->blkconf.blk; trace_pci_nvme_dif_rw_mdata_out_cb(nvme_cid(req), blk_name(blk)); @@ -357,14 +361,15 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = ns->blkconf.blk; bool wrz = rw->opcode == NVME_CMD_WRITE_ZEROES; uint32_t nlb = le16_to_cpu(rw->nlb) + 1; uint64_t slba = le64_to_cpu(rw->slba); - size_t len = nvme_l2b(ns, nlb); - size_t mlen = nvme_m2b(ns, nlb); + size_t len = nvme_l2b(nvm, nlb); + size_t mlen = nvme_m2b(nvm, nlb); size_t mapped_len = len; - int64_t offset = nvme_l2b(ns, slba); + int64_t offset = nvme_l2b(nvm, slba); uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); uint16_t apptag = le16_to_cpu(rw->apptag); uint16_t appmask = le16_to_cpu(rw->appmask); @@ -388,9 +393,9 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) if (pract) { uint8_t *mbuf, *end; - int16_t pil = ns->lbaf.ms - sizeof(NvmeDifTuple); + int16_t pil = nvm->lbaf.ms - sizeof(NvmeDifTuple); - status = nvme_check_prinfo(ns, prinfo, slba, reftag); + status = nvme_check_prinfo(nvm, prinfo, slba, reftag); if (status) { goto err; } @@ -405,17 +410,17 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) mbuf = ctx->mdata.bounce; end = mbuf + mlen; - if (ns->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT) { + if (nvm->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT) { pil = 0; } - for (; mbuf < end; mbuf += ns->lbaf.ms) { + for (; mbuf < end; mbuf += nvm->lbaf.ms) { NvmeDifTuple *dif = (NvmeDifTuple *)(mbuf + pil); dif->apptag = cpu_to_be16(apptag); dif->reftag = cpu_to_be32(reftag); - switch (NVME_ID_NS_DPS_TYPE(ns->id_ns.dps)) { + switch (NVME_ID_NS_DPS_TYPE(nvm->id_ns.dps)) { case NVME_ID_NS_DPS_TYPE_1: case NVME_ID_NS_DPS_TYPE_2: reftag++; @@ -428,7 +433,7 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) return NVME_NO_COMPLETE; } - if (nvme_ns_ext(ns) && !(pract && ns->lbaf.ms == 8)) { + if (nvme_ns_ext(nvm) && !(pract && nvm->lbaf.ms == 8)) { mapped_len += mlen; } @@ -462,7 +467,7 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) qemu_iovec_init(&ctx->mdata.iov, 1); qemu_iovec_add(&ctx->mdata.iov, ctx->mdata.bounce, mlen); - if (!(pract && ns->lbaf.ms == 8)) { + if (!(pract && nvm->lbaf.ms == 8)) { status = nvme_bounce_mdata(n, ctx->mdata.bounce, ctx->mdata.iov.size, NVME_TX_DIRECTION_TO_DEVICE, req); if (status) { @@ -470,18 +475,18 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) } } - status = nvme_check_prinfo(ns, prinfo, slba, reftag); + status = nvme_check_prinfo(nvm, prinfo, slba, reftag); if (status) { goto err; } if (pract) { /* splice generated protection information into the buffer */ - nvme_dif_pract_generate_dif(ns, ctx->data.bounce, ctx->data.iov.size, + nvme_dif_pract_generate_dif(nvm, ctx->data.bounce, ctx->data.iov.size, ctx->mdata.bounce, ctx->mdata.iov.size, apptag, &reftag); } else { - status = nvme_dif_check(ns, ctx->data.bounce, ctx->data.iov.size, + status = nvme_dif_check(nvm, ctx->data.bounce, ctx->data.iov.size, ctx->mdata.bounce, ctx->mdata.iov.size, prinfo, slba, apptag, appmask, &reftag); if (status) { diff --git a/hw/nvme/dif.h b/hw/nvme/dif.h index e36fea30e71e..7d47299252ae 100644 --- a/hw/nvme/dif.h +++ b/hw/nvme/dif.h @@ -37,14 +37,14 @@ static const uint16_t t10_dif_crc_table[256] = { 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3 }; -uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint8_t prinfo, uint64_t slba, - uint32_t reftag); +uint16_t nvme_check_prinfo(NvmeNamespaceNvm *nvm, uint8_t prinfo, + uint64_t slba, uint32_t reftag); uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, uint64_t slba); -void nvme_dif_pract_generate_dif(NvmeNamespace *ns, uint8_t *buf, size_t len, - uint8_t *mbuf, size_t mlen, uint16_t apptag, - uint32_t *reftag); -uint16_t nvme_dif_check(NvmeNamespace *ns, uint8_t *buf, size_t len, +void nvme_dif_pract_generate_dif(NvmeNamespaceNvm *nvm, uint8_t *buf, + size_t len, uint8_t *mbuf, size_t mlen, + uint16_t apptag, uint32_t *reftag); +uint16_t nvme_dif_check(NvmeNamespaceNvm *nvm, uint8_t *buf, size_t len, uint8_t *mbuf, size_t mlen, uint8_t prinfo, uint64_t slba, uint16_t apptag, uint16_t appmask, uint32_t *reftag); diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 183483969088..9b59beb0324d 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -28,14 +28,15 @@ void nvme_ns_init_format(NvmeNamespace *ns) { - NvmeIdNs *id_ns = &ns->id_ns; + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + NvmeIdNs *id_ns = &nvm->id_ns; BlockDriverInfo bdi; int npdg, nlbas, ret; - ns->lbaf = id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; - ns->lbasz = 1 << ns->lbaf.ds; + nvm->lbaf = id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; + nvm->lbasz = 1 << nvm->lbaf.ds; - nlbas = ns->size / (ns->lbasz + ns->lbaf.ms); + nlbas = nvm->size / (nvm->lbasz + nvm->lbaf.ms); id_ns->nsze = cpu_to_le64(nlbas); @@ -43,13 +44,13 @@ void nvme_ns_init_format(NvmeNamespace *ns) id_ns->ncap = id_ns->nsze; id_ns->nuse = id_ns->ncap; - ns->moff = (int64_t)nlbas << ns->lbaf.ds; + nvm->moff = (int64_t)nlbas << nvm->lbaf.ds; - npdg = ns->blkconf.discard_granularity / ns->lbasz; + npdg = nvm->discard_granularity / nvm->lbasz; ret = bdrv_get_info(blk_bs(ns->blkconf.blk), &bdi); - if (ret >= 0 && bdi.cluster_size > ns->blkconf.discard_granularity) { - npdg = bdi.cluster_size / ns->lbasz; + if (ret >= 0 && bdi.cluster_size > nvm->discard_granularity) { + npdg = bdi.cluster_size / nvm->lbasz; } id_ns->npda = id_ns->npdg = npdg - 1; @@ -57,8 +58,9 @@ void nvme_ns_init_format(NvmeNamespace *ns) static int nvme_ns_init(NvmeNamespace *ns, Error **errp) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); static uint64_t ns_count; - NvmeIdNs *id_ns = &ns->id_ns; + NvmeIdNs *id_ns = &nvm->id_ns; uint8_t ds; uint16_t ms; int i; @@ -66,7 +68,7 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) ns->csi = NVME_CSI_NVM; ns->status = 0x0; - ns->id_ns.dlfeat = 0x1; + nvm->id_ns.dlfeat = 0x1; /* support DULBE and I/O optimization fields */ id_ns->nsfeat |= (0x4 | 0x10); @@ -82,12 +84,12 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) } /* simple copy */ - id_ns->mssrl = cpu_to_le16(ns->params.mssrl); - id_ns->mcl = cpu_to_le32(ns->params.mcl); - id_ns->msrc = ns->params.msrc; + id_ns->mssrl = cpu_to_le16(nvm->mssrl); + id_ns->mcl = cpu_to_le32(nvm->mcl); + id_ns->msrc = nvm->msrc; id_ns->eui64 = cpu_to_be64(ns->params.eui64); - ds = 31 - clz32(ns->blkconf.logical_block_size); + ds = 31 - clz32(nvm->lbasz); ms = ns->params.ms; id_ns->mc = NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE; @@ -140,6 +142,7 @@ lbaf_found: static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); bool read_only; if (!blkconf_blocksizes(&ns->blkconf, errp)) { @@ -156,9 +159,14 @@ static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp) MAX(ns->blkconf.logical_block_size, MIN_DISCARD_GRANULARITY); } - ns->size = blk_getlength(ns->blkconf.blk); - if (ns->size < 0) { - error_setg_errno(errp, -ns->size, "could not get blockdev size"); + nvm->lbasz = ns->blkconf.logical_block_size; + nvm->discard_granularity = ns->blkconf.discard_granularity; + nvm->lbaf.ds = 31 - clz32(nvm->lbasz); + nvm->lbaf.ms = ns->params.ms; + + nvm->size = blk_getlength(ns->blkconf.blk); + if (nvm->size < 0) { + error_setg_errno(errp, -nvm->size, "could not get blockdev size"); return -1; } @@ -167,6 +175,7 @@ static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp) static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); uint64_t zone_size, zone_cap; @@ -187,14 +196,14 @@ static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) "zone size %"PRIu64"B", zone_cap, zone_size); return -1; } - if (zone_size < ns->lbasz) { + if (zone_size < nvm->lbasz) { error_setg(errp, "zone size %"PRIu64"B too small, " - "must be at least %zuB", zone_size, ns->lbasz); + "must be at least %zuB", zone_size, nvm->lbasz); return -1; } - if (zone_cap < ns->lbasz) { + if (zone_cap < nvm->lbasz) { error_setg(errp, "zone capacity %"PRIu64"B too small, " - "must be at least %zuB", zone_cap, ns->lbasz); + "must be at least %zuB", zone_cap, nvm->lbasz); return -1; } @@ -202,9 +211,9 @@ static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) * Save the main zone geometry values to avoid * calculating them later again. */ - zoned->zone_size = zone_size / ns->lbasz; - zoned->zone_capacity = zone_cap / ns->lbasz; - zoned->num_zones = le64_to_cpu(ns->id_ns.nsze) / zoned->zone_size; + zoned->zone_size = zone_size / nvm->lbasz; + zoned->zone_capacity = zone_cap / nvm->lbasz; + zoned->num_zones = le64_to_cpu(nvm->id_ns.nsze) / zoned->zone_size; /* Do a few more sanity checks of ZNS properties */ if (!zoned->num_zones) { @@ -258,6 +267,7 @@ static void nvme_zns_init_state(NvmeNamespaceZoned *zoned) static void nvme_zns_init(NvmeNamespace *ns) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); NvmeIdNsZoned *id_ns_z = &zoned->id_ns; int i; @@ -273,16 +283,16 @@ static void nvme_zns_init(NvmeNamespace *ns) id_ns_z->ozcs |= NVME_ID_NS_ZONED_OZCS_CROSS_READ; } - for (i = 0; i <= ns->id_ns.nlbaf; i++) { + for (i = 0; i <= nvm->id_ns.nlbaf; i++) { id_ns_z->lbafe[i].zsze = cpu_to_le64(zoned->zone_size); id_ns_z->lbafe[i].zdes = zoned->zd_extension_size >> 6; /* Units of 64B */ } ns->csi = NVME_CSI_ZONED; - ns->id_ns.nsze = cpu_to_le64(zoned->num_zones * zoned->zone_size); - ns->id_ns.ncap = ns->id_ns.nsze; - ns->id_ns.nuse = ns->id_ns.ncap; + nvm->id_ns.nsze = cpu_to_le64(zoned->num_zones * zoned->zone_size); + nvm->id_ns.ncap = nvm->id_ns.nsze; + nvm->id_ns.nuse = nvm->id_ns.ncap; /* * The device uses the BDRV_BLOCK_ZERO flag to determine the "deallocated" @@ -291,13 +301,13 @@ static void nvme_zns_init(NvmeNamespace *ns) * we can only support DULBE if the zone size is a multiple of the * calculated NPDG. */ - if (zoned->zone_size % (ns->id_ns.npdg + 1)) { + if (zoned->zone_size % (nvm->id_ns.npdg + 1)) { warn_report("the zone size (%"PRIu64" blocks) is not a multiple of " "the calculated deallocation granularity (%d blocks); " "DULBE support disabled", - zoned->zone_size, ns->id_ns.npdg + 1); + zoned->zone_size, nvm->id_ns.npdg + 1); - ns->id_ns.nsfeat &= ~0x4; + nvm->id_ns.nsfeat &= ~0x4; } } diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 9cfb172101a9..c5e08cf9e1c1 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -147,15 +147,32 @@ typedef struct NvmeNamespaceZoned { QTAILQ_HEAD(, NvmeZone) full_zones; } NvmeNamespaceZoned; +enum { + NVME_NS_NVM_EXTENDED_LBA = 1 << 0, + NVME_NS_NVM_PI_FIRST = 1 << 1, +}; + +typedef struct NvmeNamespaceNvm { + NvmeIdNs id_ns; + + int64_t size; + int64_t moff; + + NvmeLBAF lbaf; + size_t lbasz; + uint32_t discard_granularity; + + uint16_t mssrl; + uint32_t mcl; + uint8_t msrc; + + unsigned long flags; +} NvmeNamespaceNvm; + typedef struct NvmeNamespace { DeviceState parent_obj; BlockConf blkconf; int32_t bootindex; - int64_t size; - int64_t moff; - NvmeIdNs id_ns; - NvmeLBAF lbaf; - size_t lbasz; const uint32_t *iocs; uint8_t csi; uint16_t status; @@ -169,9 +186,11 @@ typedef struct NvmeNamespace { uint32_t err_rec; } features; + NvmeNamespaceNvm nvm; NvmeNamespaceZoned zoned; } NvmeNamespace; +#define NVME_NAMESPACE_NVM(ns) (&(ns)->nvm) #define NVME_NAMESPACE_ZONED(ns) (&(ns)->zoned) static inline uint32_t nvme_nsid(NvmeNamespace *ns) @@ -183,24 +202,24 @@ static inline uint32_t nvme_nsid(NvmeNamespace *ns) return 0; } -static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba) +static inline size_t nvme_l2b(NvmeNamespaceNvm *nvm, uint64_t lba) { - return lba << ns->lbaf.ds; + return lba << nvm->lbaf.ds; } -static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba) +static inline size_t nvme_m2b(NvmeNamespaceNvm *nvm, uint64_t lba) { - return ns->lbaf.ms * lba; + return nvm->lbaf.ms * lba; } -static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba) +static inline int64_t nvme_moff(NvmeNamespaceNvm *nvm, uint64_t lba) { - return ns->moff + nvme_m2b(ns, lba); + return nvm->moff + nvme_m2b(nvm, lba); } -static inline bool nvme_ns_ext(NvmeNamespace *ns) +static inline bool nvme_ns_ext(NvmeNamespaceNvm *nvm) { - return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas); + return !!NVME_ID_NS_FLBAS_EXTENDED(nvm->id_ns.flbas); } void nvme_ns_init_format(NvmeNamespace *ns); From patchwork Mon Sep 27 05:17:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533190 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=g2f0VmxS; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=Z+1/TF3k; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrmK6QGCz9t5m for ; Mon, 27 Sep 2021 15:29:20 +1000 (AEST) Received: from localhost ([::1]:49034 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjCW-0003Oi-Sd for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:29:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34158) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2F-00038r-FV; Mon, 27 Sep 2021 01:18:39 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:50781) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2B-0000Az-Ve; Mon, 27 Sep 2021 01:18:39 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailnew.west.internal (Postfix) with ESMTP id 714AC2B0120B; Mon, 27 Sep 2021 01:18:33 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Mon, 27 Sep 2021 01:18:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=TY2HX/At9ES/Y Rcp44HLh/CPfHci73ZM/lQlQhq7/Fo=; b=g2f0VmxSGhI9w5yofmtMelsZ4ctxz hP5qhTVbEVwFrC9m6DVmsETZOTTpwYP5ueQuYkYXn3dD5bKj8A5VgqJ+ZhvkNUFE Y9hcgzizAJnxNIfGqICpvHe9ymvA1wsV+nq8l6CxrVCV853VBbyxRPcx/wdbJ0hw sfHa6eazmxSad7TltrcwXvjZBhTDLyu7p3c/oAy3/kf7CqSCJuO1irKvnMr5KXHj 3EJEnEVQxTvyFzOjeZtTEqbk3A0ZNJuKExMHkKyEcwC1BPqXxaDeOEr0RakrRRZP hB0mVm7sWQBzQamriFyfGOvI6m13jPA4U4Lh0ZmAfHlW8Chp3R4UZYk1g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=TY2HX/At9ES/YRcp44HLh/CPfHci73ZM/lQlQhq7/Fo=; b=Z+1/TF3k N/A8B1w/DTsbPdzUWsPdpxhSrKj4ElYQ5/aYDUqiR1MWhAO2BqBlfRw5/G+m+M+k Ato6WROr3eG+/eDS1Aw1nqoLKrhDBmBty6teROqlD91WZuUIX8lRDLinlq8TUlrn /+HkF1O+fLZctSH+H8FSDN+43ooZZdobtkNKoogDL4CvmUyN2nmyfbASBASNXP9D OpZHNeSjPY5wXvO9o/uGqXxUD3FpPkvhCGZiqdDhyENJEEDTGxdlub/Rky/hq7u5 ITIbkdNP5ubyT9PEyMAVsCgnFvPK9hKPfc3kJLMb64d7k5RIco4QsPz/AvuZ8Y1C 88p+XUigDPQ3sQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:30 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 07/16] hw/nvme: move BlockBackend to NvmeNamespaceNvm Date: Mon, 27 Sep 2021 07:17:50 +0200 Message-Id: <20210927051759.447305-8-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 66 +++++++++++++++++++++++++------------------------- hw/nvme/dif.c | 14 +++++------ hw/nvme/nvme.h | 6 +++++ 3 files changed, 46 insertions(+), 40 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 026dfaa71bda..3e561a13f76f 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1465,7 +1465,7 @@ static int nvme_block_status_all(NvmeNamespace *ns, uint64_t slba, uint32_t nlb, int flags) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockDriverState *bs = blk_bs(ns->blkconf.blk); + BlockDriverState *bs = blk_bs(nvme_blk(ns)); int64_t pnum = 0, bytes = nvme_l2b(nvm, nlb); int64_t offset = nvme_l2b(nvm, slba); @@ -1865,7 +1865,7 @@ void nvme_rw_complete_cb(void *opaque, int ret) { NvmeRequest *req = opaque; NvmeNamespace *ns = req->ns; - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); BlockAcctCookie *acct = &req->acct; BlockAcctStats *stats = blk_get_stats(blk); @@ -1891,7 +1891,7 @@ static void nvme_rw_cb(void *opaque, int ret) NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); trace_pci_nvme_rw_cb(nvme_cid(req), blk_name(blk)); @@ -1942,7 +1942,7 @@ static void nvme_verify_cb(void *opaque, int ret) NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); BlockAcctCookie *acct = &req->acct; BlockAcctStats *stats = blk_get_stats(blk); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; @@ -2000,7 +2000,7 @@ static void nvme_verify_mdata_in_cb(void *opaque, int ret) uint32_t nlb = le16_to_cpu(rw->nlb) + 1; size_t mlen = nvme_m2b(nvm, nlb); uint64_t offset = nvme_moff(nvm, slba); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); trace_pci_nvme_verify_mdata_in_cb(nvme_cid(req), blk_name(blk)); @@ -2046,7 +2046,7 @@ static void nvme_compare_mdata_cb(void *opaque, int ret) uint32_t reftag = le32_to_cpu(rw->reftag); struct nvme_compare_ctx *ctx = req->opaque; g_autofree uint8_t *buf = NULL; - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); BlockAcctCookie *acct = &req->acct; BlockAcctStats *stats = blk_get_stats(blk); uint16_t status = NVME_SUCCESS; @@ -2126,7 +2126,7 @@ static void nvme_compare_data_cb(void *opaque, int ret) NvmeCtrl *n = nvme_ctrl(req); NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); BlockAcctCookie *acct = &req->acct; BlockAcctStats *stats = blk_get_stats(blk); @@ -2272,7 +2272,7 @@ static void nvme_dsm_md_cb(void *opaque, int ret) nvme_dsm_cb(iocb, 0); } - iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, nvme_moff(nvm, slba), + iocb->aiocb = blk_aio_pwrite_zeroes(nvme_blk(ns), nvme_moff(nvm, slba), nvme_m2b(nvm, nlb), BDRV_REQ_MAY_UNMAP, nvme_dsm_cb, iocb); return; @@ -2320,7 +2320,7 @@ next: goto next; } - iocb->aiocb = blk_aio_pdiscard(ns->blkconf.blk, nvme_l2b(nvm, slba), + iocb->aiocb = blk_aio_pdiscard(nvme_blk(ns), nvme_l2b(nvm, slba), nvme_l2b(nvm, nlb), nvme_dsm_md_cb, iocb); return; @@ -2341,7 +2341,7 @@ static uint16_t nvme_dsm(NvmeCtrl *n, NvmeRequest *req) trace_pci_nvme_dsm(nr, attr); if (attr & NVME_DSMGMT_AD) { - NvmeDSMAIOCB *iocb = blk_aio_get(&nvme_dsm_aiocb_info, ns->blkconf.blk, + NvmeDSMAIOCB *iocb = blk_aio_get(&nvme_dsm_aiocb_info, nvme_blk(ns), nvme_misc_cb, req); iocb->req = req; @@ -2371,7 +2371,7 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest *req) NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; size_t len = nvme_l2b(nvm, nlb); @@ -2421,7 +2421,7 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest *req) block_acct_start(blk_get_stats(blk), &req->acct, ctx->data.iov.size, BLOCK_ACCT_READ); - req->aiocb = blk_aio_preadv(ns->blkconf.blk, offset, &ctx->data.iov, 0, + req->aiocb = blk_aio_preadv(nvme_blk(ns), offset, &ctx->data.iov, 0, nvme_verify_mdata_in_cb, ctx); return NVME_NO_COMPLETE; } @@ -2472,7 +2472,7 @@ static void nvme_copy_bh(void *opaque) NvmeCopyAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; NvmeNamespace *ns = req->ns; - BlockAcctStats *stats = blk_get_stats(ns->blkconf.blk); + BlockAcctStats *stats = blk_get_stats(nvme_blk(ns)); if (iocb->idx != iocb->nr) { req->cqe.result = cpu_to_le32(iocb->idx); @@ -2555,7 +2555,7 @@ static void nvme_copy_out_cb(void *opaque, int ret) qemu_iovec_reset(&iocb->iov); qemu_iovec_add(&iocb->iov, mbounce, mlen); - iocb->aiocb = blk_aio_pwritev(ns->blkconf.blk, nvme_moff(nvm, iocb->slba), + iocb->aiocb = blk_aio_pwritev(nvme_blk(ns), nvme_moff(nvm, iocb->slba), &iocb->iov, 0, nvme_copy_out_completed_cb, iocb); @@ -2647,7 +2647,7 @@ static void nvme_copy_in_completed_cb(void *opaque, int ret) qemu_iovec_reset(&iocb->iov); qemu_iovec_add(&iocb->iov, iocb->bounce, len); - iocb->aiocb = blk_aio_pwritev(ns->blkconf.blk, nvme_l2b(nvm, iocb->slba), + iocb->aiocb = blk_aio_pwritev(nvme_blk(ns), nvme_l2b(nvm, iocb->slba), &iocb->iov, 0, nvme_copy_out_cb, iocb); return; @@ -2695,7 +2695,7 @@ static void nvme_copy_in_cb(void *opaque, int ret) qemu_iovec_add(&iocb->iov, iocb->bounce + nvme_l2b(nvm, nlb), nvme_m2b(nvm, nlb)); - iocb->aiocb = blk_aio_preadv(ns->blkconf.blk, nvme_moff(nvm, slba), + iocb->aiocb = blk_aio_preadv(nvme_blk(ns), nvme_moff(nvm, slba), &iocb->iov, 0, nvme_copy_in_completed_cb, iocb); return; @@ -2761,7 +2761,7 @@ static void nvme_copy_cb(void *opaque, int ret) qemu_iovec_reset(&iocb->iov); qemu_iovec_add(&iocb->iov, iocb->bounce, len); - iocb->aiocb = blk_aio_preadv(ns->blkconf.blk, nvme_l2b(nvm, slba), + iocb->aiocb = blk_aio_preadv(nvme_blk(ns), nvme_l2b(nvm, slba), &iocb->iov, 0, nvme_copy_in_cb, iocb); return; @@ -2780,7 +2780,7 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeCopyCmd *copy = (NvmeCopyCmd *)&req->cmd; - NvmeCopyAIOCB *iocb = blk_aio_get(&nvme_copy_aiocb_info, ns->blkconf.blk, + NvmeCopyAIOCB *iocb = blk_aio_get(&nvme_copy_aiocb_info, nvme_blk(ns), nvme_misc_cb, req); uint16_t nr = copy->nr + 1; uint8_t format = copy->control[0] & 0xf; @@ -2847,9 +2847,9 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) qemu_iovec_init(&iocb->iov, 1); - block_acct_start(blk_get_stats(ns->blkconf.blk), &iocb->acct.read, 0, + block_acct_start(blk_get_stats(nvme_blk(ns)), &iocb->acct.read, 0, BLOCK_ACCT_READ); - block_acct_start(blk_get_stats(ns->blkconf.blk), &iocb->acct.write, 0, + block_acct_start(blk_get_stats(nvme_blk(ns)), &iocb->acct.write, 0, BLOCK_ACCT_WRITE); req->aiocb = &iocb->common; @@ -2868,7 +2868,7 @@ static uint16_t nvme_compare(NvmeCtrl *n, NvmeRequest *req) NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); uint64_t slba = le64_to_cpu(rw->slba); uint32_t nlb = le16_to_cpu(rw->nlb) + 1; uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); @@ -2971,7 +2971,7 @@ static void nvme_flush_ns_cb(void *opaque, int ret) trace_pci_nvme_flush_ns(iocb->nsid); iocb->ns = NULL; - iocb->aiocb = blk_aio_flush(ns->blkconf.blk, nvme_flush_ns_cb, iocb); + iocb->aiocb = blk_aio_flush(nvme_blk(ns), nvme_flush_ns_cb, iocb); return; } @@ -3073,7 +3073,7 @@ static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req) uint64_t data_size = nvme_l2b(nvm, nlb); uint64_t mapped_size = data_size; uint64_t data_offset; - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); uint16_t status; if (nvme_ns_ext(nvm)) { @@ -3151,7 +3151,7 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, uint64_t data_offset; NvmeZone *zone; NvmeZonedResult *res = (NvmeZonedResult *)&req->cqe; - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); uint16_t status; if (nvme_ns_ext(nvm)) { @@ -3542,7 +3542,7 @@ static void nvme_zone_reset_epilogue_cb(void *opaque, int ret) moff = nvme_moff(nvm, iocb->zone->d.zslba); count = nvme_m2b(nvm, zoned->zone_size); - iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, moff, count, + iocb->aiocb = blk_aio_pwrite_zeroes(nvme_blk(ns), moff, count, BDRV_REQ_MAY_UNMAP, nvme_zone_reset_cb, iocb); return; @@ -3593,7 +3593,7 @@ static void nvme_zone_reset_cb(void *opaque, int ret) trace_pci_nvme_zns_zone_reset(zone->d.zslba); - iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, + iocb->aiocb = blk_aio_pwrite_zeroes(nvme_blk(ns), nvme_l2b(nvm, zone->d.zslba), nvme_l2b(nvm, zoned->zone_size), BDRV_REQ_MAY_UNMAP, @@ -3673,7 +3673,7 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) case NVME_ZONE_ACTION_RESET: trace_pci_nvme_reset_zone(slba, zone_idx, all); - iocb = blk_aio_get(&nvme_zone_reset_aiocb_info, ns->blkconf.blk, + iocb = blk_aio_get(&nvme_zone_reset_aiocb_info, nvme_blk(ns), nvme_misc_cb, req); iocb->req = req; @@ -4076,7 +4076,7 @@ struct nvme_stats { static void nvme_set_blk_stats(NvmeNamespace *ns, struct nvme_stats *stats) { - BlockAcctStats *s = blk_get_stats(ns->blkconf.blk); + BlockAcctStats *s = blk_get_stats(nvme_blk(ns)); stats->units_read += s->nr_bytes[BLOCK_ACCT_READ] >> BDRV_SECTOR_BITS; stats->units_written += s->nr_bytes[BLOCK_ACCT_WRITE] >> BDRV_SECTOR_BITS; @@ -4942,7 +4942,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req) continue; } - result = blk_enable_write_cache(ns->blkconf.blk); + result = blk_enable_write_cache(nvme_blk(ns)); if (result) { break; } @@ -5114,11 +5114,11 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) continue; } - if (!(dw11 & 0x1) && blk_enable_write_cache(ns->blkconf.blk)) { - blk_flush(ns->blkconf.blk); + if (!(dw11 & 0x1) && blk_enable_write_cache(nvme_blk(ns))) { + blk_flush(nvme_blk(ns)); } - blk_set_enable_write_cache(ns->blkconf.blk, dw11 & 1); + blk_set_enable_write_cache(nvme_blk(ns), dw11 & 1); } break; @@ -5368,7 +5368,7 @@ static void nvme_format_ns_cb(void *opaque, int ret) if (iocb->offset < nvm->size) { bytes = MIN(BDRV_REQUEST_MAX_BYTES, nvm->size - iocb->offset); - iocb->aiocb = blk_aio_pwrite_zeroes(ns->blkconf.blk, iocb->offset, + iocb->aiocb = blk_aio_pwrite_zeroes(nvme_blk(ns), iocb->offset, bytes, BDRV_REQ_MAY_UNMAP, nvme_format_ns_cb, iocb); diff --git a/hw/nvme/dif.c b/hw/nvme/dif.c index 26c7412eb523..1b8f9ba2fb44 100644 --- a/hw/nvme/dif.c +++ b/hw/nvme/dif.c @@ -171,7 +171,7 @@ uint16_t nvme_dif_mangle_mdata(NvmeNamespace *ns, uint8_t *mbuf, size_t mlen, uint64_t slba) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); BlockDriverState *bs = blk_bs(blk); int64_t moffset = 0, offset = nvme_l2b(nvm, slba); @@ -227,7 +227,7 @@ static void nvme_dif_rw_cb(void *opaque, int ret) NvmeBounceContext *ctx = opaque; NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); trace_pci_nvme_dif_rw_cb(nvme_cid(req), blk_name(blk)); @@ -311,7 +311,7 @@ static void nvme_dif_rw_mdata_in_cb(void *opaque, int ret) uint32_t nlb = le16_to_cpu(rw->nlb) + 1; size_t mlen = nvme_m2b(nvm, nlb); uint64_t offset = nvme_moff(nvm, slba); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); trace_pci_nvme_dif_rw_mdata_in_cb(nvme_cid(req), blk_name(blk)); @@ -341,7 +341,7 @@ static void nvme_dif_rw_mdata_out_cb(void *opaque, int ret) NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); uint64_t offset = nvme_moff(nvm, slba); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); trace_pci_nvme_dif_rw_mdata_out_cb(nvme_cid(req), blk_name(blk)); @@ -362,7 +362,7 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - BlockBackend *blk = ns->blkconf.blk; + BlockBackend *blk = nvme_blk(ns); bool wrz = rw->opcode == NVME_CMD_WRITE_ZEROES; uint32_t nlb = le16_to_cpu(rw->nlb) + 1; uint64_t slba = le64_to_cpu(rw->slba); @@ -451,7 +451,7 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) block_acct_start(blk_get_stats(blk), &req->acct, ctx->data.iov.size, BLOCK_ACCT_READ); - req->aiocb = blk_aio_preadv(ns->blkconf.blk, offset, &ctx->data.iov, 0, + req->aiocb = blk_aio_preadv(nvme_blk(ns), offset, &ctx->data.iov, 0, nvme_dif_rw_mdata_in_cb, ctx); return NVME_NO_COMPLETE; } @@ -497,7 +497,7 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) block_acct_start(blk_get_stats(blk), &req->acct, ctx->data.iov.size, BLOCK_ACCT_WRITE); - req->aiocb = blk_aio_pwritev(ns->blkconf.blk, offset, &ctx->data.iov, 0, + req->aiocb = blk_aio_pwritev(nvme_blk(ns), offset, &ctx->data.iov, 0, nvme_dif_rw_mdata_out_cb, ctx); return NVME_NO_COMPLETE; diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index c5e08cf9e1c1..525bfd0ca831 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -155,6 +155,7 @@ enum { typedef struct NvmeNamespaceNvm { NvmeIdNs id_ns; + BlockBackend *blk; int64_t size; int64_t moff; @@ -193,6 +194,11 @@ typedef struct NvmeNamespace { #define NVME_NAMESPACE_NVM(ns) (&(ns)->nvm) #define NVME_NAMESPACE_ZONED(ns) (&(ns)->zoned) +static inline BlockBackend *nvme_blk(NvmeNamespace *ns) +{ + return NVME_NAMESPACE_NVM(ns)->blk; +} + static inline uint32_t nvme_nsid(NvmeNamespace *ns) { if (ns) { From patchwork Mon Sep 27 05:17:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533206 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=lh94gXCF; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=A3HKfpES; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHsB31K2Cz9tD5 for ; Mon, 27 Sep 2021 15:48:09 +1000 (AEST) Received: from localhost ([::1]:39048 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjUj-0007gr-NN for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:48:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34184) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2K-0003Ik-7H; Mon, 27 Sep 2021 01:18:44 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:37617) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2F-0000F7-VW; Mon, 27 Sep 2021 01:18:43 -0400 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailnew.west.internal (Postfix) with ESMTP id 77A102B0120E; Mon, 27 Sep 2021 01:18:37 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 27 Sep 2021 01:18:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=S0eB+tPU702Wi bNvU9mwb0TP3Y70N5xeoeyuAJElhN0=; b=lh94gXCFzBW6gHNu5FWt4Is0yUg/F rw2btI+zncG0Zqt8fhH22T6mvcwHemmrB6jnmL9eXWTtziQXEI/dzTpIEHNvDn/u LCCBWz6GBjYAovGJkBzsB372WzLpkmOeuZ0eO65hPmoHVlgxZpSttx21rr2F/N/d WYPsLNCnsb9R0yJfHGEXgbaKFUn4A5NwbbWE7lPBqi7h8MgBR4e35MiqGlM1oz/J OkfeFHz1NwUmAr/Yj1PlZd21myvs8UHlxgkb19F2lzOv3vGLEiaNdaC+NBYNMxWx KxpXSTWqKFdDNK4u0+Bd47Gbxvbl2hDXw+3u/+GRloO83qAsaBsHlTxMQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=S0eB+tPU702WibNvU9mwb0TP3Y70N5xeoeyuAJElhN0=; b=A3HKfpES uIcmL2T4UKJYJXxk1mZrBbYKIK4UmjdIBhBTSiUWcHwGoxtTELCsOAwdLL+h6xr3 kbzGqnnsjkfPTSLlGN/sCkItM0uL1Fi3Vgps0tmT9tLxDcsAeLrO9wgCwy8Fsqzc 9Pxd43PQMjC9Q5aEdWJxSknCmUUAiiTitx9rIfc5SG+5RQFilpRqcvkK3CQU1kXY 3YwkvM6xhtKxrS26UX4zyHRNTzMtwiJ0s1vH0fq5bGvOvFlplsVmm7UG6RgrLcVl iyw8snkV8qUDd78p5YSG6osM9cmJwHJ8JWF5ITZApbfUw+SWIa6bhkF+MGVUmcFZ iELfVbWap0cqvA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeiudehfeejteegueeffeekhfelgfekheetfffgteejgeekuefgtddujeeuudeg ieenucffohhmrghinhepuhhuihgurdgurghtrgenucevlhhushhtvghrufhiiigvpedtne curfgrrhgrmhepmhgrihhlfhhrohhmpehithhssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:34 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 08/16] hw/nvme: hoist qdev state from namespace Date: Mon, 27 Sep 2021 07:17:51 +0200 Message-Id: <20210927051759.447305-9-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 32 +++--- hw/nvme/ns.c | 263 +++++++++++++++++++++++++---------------------- hw/nvme/nvme.h | 44 +++++--- hw/nvme/subsys.c | 2 +- 4 files changed, 186 insertions(+), 155 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 3e561a13f76f..67600d075d32 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -4620,10 +4620,10 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req, continue; } } - if (ns->params.nsid <= min_nsid) { + if (ns->nsid <= min_nsid) { continue; } - list_ptr[j++] = cpu_to_le32(ns->params.nsid); + list_ptr[j++] = cpu_to_le32(ns->nsid); if (j == data_len / sizeof(uint32_t)) { break; } @@ -4668,10 +4668,10 @@ static uint16_t nvme_identify_nslist_csi(NvmeCtrl *n, NvmeRequest *req, continue; } } - if (ns->params.nsid <= min_nsid || c->csi != ns->csi) { + if (ns->nsid <= min_nsid || c->csi != ns->csi) { continue; } - list_ptr[j++] = cpu_to_le32(ns->params.nsid); + list_ptr[j++] = cpu_to_le32(ns->nsid); if (j == data_len / sizeof(uint32_t)) { break; } @@ -4718,14 +4718,14 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) */ uuid.hdr.nidt = NVME_NIDT_UUID; uuid.hdr.nidl = NVME_NIDL_UUID; - memcpy(uuid.v, ns->params.uuid.data, NVME_NIDL_UUID); + memcpy(uuid.v, ns->uuid.data, NVME_NIDL_UUID); memcpy(pos, &uuid, sizeof(uuid)); pos += sizeof(uuid); - if (ns->params.eui64) { + if (ns->eui64.v) { eui64.hdr.nidt = NVME_NIDT_EUI64; eui64.hdr.nidl = NVME_NIDL_EUI64; - eui64.v = cpu_to_be64(ns->params.eui64); + eui64.v = cpu_to_be64(ns->eui64.v); memcpy(pos, &eui64, sizeof(eui64)); pos += sizeof(eui64); } @@ -5264,7 +5264,7 @@ static uint16_t nvme_ns_attachment(NvmeCtrl *n, NvmeRequest *req) return NVME_NS_ALREADY_ATTACHED | NVME_DNR; } - if (ns->attached && !ns->params.shared) { + if (ns->attached && !(ns->flags & NVME_NS_SHARED)) { return NVME_NS_PRIVATE | NVME_DNR; } @@ -5342,12 +5342,12 @@ static void nvme_format_set(NvmeNamespace *ns, NvmeCmd *cmd) uint8_t mset = (dw10 >> 4) & 0x1; uint8_t pil = (dw10 >> 8) & 0x1; - trace_pci_nvme_format_set(ns->params.nsid, lbaf, mset, pi, pil); + trace_pci_nvme_format_set(ns->nsid, lbaf, mset, pi, pil); nvm->id_ns.dps = (pil << 3) | pi; nvm->id_ns.flbas = lbaf | (mset << 4); - nvme_ns_init_format(ns); + nvme_ns_nvm_init_format(nvm); } static void nvme_format_ns_cb(void *opaque, int ret) @@ -6552,7 +6552,7 @@ static int nvme_init_subsys(NvmeCtrl *n, Error **errp) void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - uint32_t nsid = ns->params.nsid; + uint32_t nsid = ns->nsid; assert(nsid && nsid <= NVME_MAX_NAMESPACES); n->namespaces[nsid] = ns; @@ -6565,7 +6565,6 @@ void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns) static void nvme_realize(PCIDevice *pci_dev, Error **errp) { NvmeCtrl *n = NVME(pci_dev); - NvmeNamespace *ns; Error *local_err = NULL; nvme_check_constraints(n, &local_err); @@ -6590,12 +6589,11 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) /* setup a namespace if the controller drive property was given */ if (n->namespace.blkconf.blk) { - ns = &n->namespace; - ns->params.nsid = 1; + NvmeNamespaceDevice *nsdev = &n->namespace; + NvmeNamespace *ns = &nsdev->ns; + ns->nsid = 1; - if (nvme_ns_setup(ns, errp)) { - return; - } + nvme_ns_init(ns); nvme_attach_ns(n, ns); } diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 9b59beb0324d..582ff7d0236b 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -26,9 +26,8 @@ #define MIN_DISCARD_GRANULARITY (4 * KiB) -void nvme_ns_init_format(NvmeNamespace *ns) +void nvme_ns_nvm_init_format(NvmeNamespaceNvm *nvm) { - NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeIdNs *id_ns = &nvm->id_ns; BlockDriverInfo bdi; int npdg, nlbas, ret; @@ -48,7 +47,7 @@ void nvme_ns_init_format(NvmeNamespace *ns) npdg = nvm->discard_granularity / nvm->lbasz; - ret = bdrv_get_info(blk_bs(ns->blkconf.blk), &bdi); + ret = bdrv_get_info(blk_bs(nvm->blk), &bdi); if (ret >= 0 && bdi.cluster_size > nvm->discard_granularity) { npdg = bdi.cluster_size / nvm->lbasz; } @@ -56,53 +55,39 @@ void nvme_ns_init_format(NvmeNamespace *ns) id_ns->npda = id_ns->npdg = npdg - 1; } -static int nvme_ns_init(NvmeNamespace *ns, Error **errp) +void nvme_ns_init(NvmeNamespace *ns) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - static uint64_t ns_count; NvmeIdNs *id_ns = &nvm->id_ns; uint8_t ds; uint16_t ms; int i; - ns->csi = NVME_CSI_NVM; - ns->status = 0x0; - - nvm->id_ns.dlfeat = 0x1; + id_ns->dlfeat = 0x1; /* support DULBE and I/O optimization fields */ id_ns->nsfeat |= (0x4 | 0x10); - if (ns->params.shared) { + if (ns->flags & NVME_NS_SHARED) { id_ns->nmic |= NVME_NMIC_NS_SHARED; } - /* Substitute a missing EUI-64 by an autogenerated one */ - ++ns_count; - if (!ns->params.eui64 && ns->params.eui64_default) { - ns->params.eui64 = ns_count + NVME_EUI64_DEFAULT; - } - /* simple copy */ id_ns->mssrl = cpu_to_le16(nvm->mssrl); id_ns->mcl = cpu_to_le32(nvm->mcl); id_ns->msrc = nvm->msrc; - id_ns->eui64 = cpu_to_be64(ns->params.eui64); + id_ns->eui64 = cpu_to_be64(ns->eui64.v); ds = 31 - clz32(nvm->lbasz); - ms = ns->params.ms; + ms = nvm->lbaf.ms; id_ns->mc = NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE; - if (ms && ns->params.mset) { + if (ms && nvm->flags & NVME_NS_NVM_EXTENDED_LBA) { id_ns->flbas |= NVME_ID_NS_FLBAS_EXTENDED; } id_ns->dpc = 0x1f; - id_ns->dps = ns->params.pi; - if (ns->params.pi && ns->params.pil) { - id_ns->dps |= NVME_ID_NS_DPS_FIRST_EIGHT; - } static const NvmeLBAF lbaf[16] = { [0] = { .ds = 9 }, @@ -135,59 +120,63 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) id_ns->flbas |= id_ns->nlbaf; lbaf_found: - nvme_ns_init_format(ns); - - return 0; + nvme_ns_nvm_init_format(nvm); } -static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp) +static int nvme_nsdev_init_blk(NvmeNamespaceDevice *nsdev, + Error **errp) { + NvmeNamespace *ns = &nsdev->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + BlockConf *blkconf = &nsdev->blkconf; bool read_only; - if (!blkconf_blocksizes(&ns->blkconf, errp)) { + if (!blkconf_blocksizes(blkconf, errp)) { return -1; } - read_only = !blk_supports_write_perm(ns->blkconf.blk); - if (!blkconf_apply_backend_options(&ns->blkconf, read_only, false, errp)) { + read_only = !blk_supports_write_perm(blkconf->blk); + if (!blkconf_apply_backend_options(blkconf, read_only, false, errp)) { return -1; } - if (ns->blkconf.discard_granularity == -1) { - ns->blkconf.discard_granularity = - MAX(ns->blkconf.logical_block_size, MIN_DISCARD_GRANULARITY); + if (blkconf->discard_granularity == -1) { + blkconf->discard_granularity = + MAX(blkconf->logical_block_size, MIN_DISCARD_GRANULARITY); } - nvm->lbasz = ns->blkconf.logical_block_size; - nvm->discard_granularity = ns->blkconf.discard_granularity; + nvm->lbasz = blkconf->logical_block_size; + nvm->discard_granularity = blkconf->discard_granularity; nvm->lbaf.ds = 31 - clz32(nvm->lbasz); - nvm->lbaf.ms = ns->params.ms; + nvm->lbaf.ms = nsdev->params.ms; + nvm->blk = blkconf->blk; - nvm->size = blk_getlength(ns->blkconf.blk); + nvm->size = blk_getlength(nvm->blk); if (nvm->size < 0) { - error_setg_errno(errp, -nvm->size, "could not get blockdev size"); + error_setg_errno(errp, -(nvm->size), "could not get blockdev size"); return -1; } return 0; } -static int nvme_zns_check_calc_geometry(NvmeNamespace *ns, Error **errp) +static int nvme_nsdev_zns_check_calc_geometry(NvmeNamespaceDevice *nsdev, + Error **errp) { + NvmeNamespace *ns = &nsdev->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); uint64_t zone_size, zone_cap; /* Make sure that the values of ZNS properties are sane */ - if (ns->params.zone_size_bs) { - zone_size = ns->params.zone_size_bs; + if (nsdev->params.zone_size_bs) { + zone_size = nsdev->params.zone_size_bs; } else { zone_size = NVME_DEFAULT_ZONE_SIZE; } - if (ns->params.zone_cap_bs) { - zone_cap = ns->params.zone_cap_bs; + if (nsdev->params.zone_cap_bs) { + zone_cap = nsdev->params.zone_cap_bs; } else { zone_cap = zone_size; } @@ -359,46 +348,47 @@ static void nvme_zns_shutdown(NvmeNamespaceZoned *zoned) assert(zoned->nr_open_zones == 0); } -static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp) +static int nvme_nsdev_check_constraints(NvmeNamespaceDevice *nsdev, + Error **errp) { - if (!ns->blkconf.blk) { + if (!nsdev->blkconf.blk) { error_setg(errp, "block backend not configured"); return -1; } - if (ns->params.pi && ns->params.ms < 8) { + if (nsdev->params.pi && nsdev->params.ms < 8) { error_setg(errp, "at least 8 bytes of metadata required to enable " "protection information"); return -1; } - if (ns->params.nsid > NVME_MAX_NAMESPACES) { + if (nsdev->params.nsid > NVME_MAX_NAMESPACES) { error_setg(errp, "invalid namespace id (must be between 0 and %d)", NVME_MAX_NAMESPACES); return -1; } - if (ns->params.zoned) { - if (ns->params.max_active_zones) { - if (ns->params.max_open_zones > ns->params.max_active_zones) { + if (nsdev->params.zoned) { + if (nsdev->params.max_active_zones) { + if (nsdev->params.max_open_zones > nsdev->params.max_active_zones) { error_setg(errp, "max_open_zones (%u) exceeds " - "max_active_zones (%u)", ns->params.max_open_zones, - ns->params.max_active_zones); + "max_active_zones (%u)", nsdev->params.max_open_zones, + nsdev->params.max_active_zones); return -1; } - if (!ns->params.max_open_zones) { - ns->params.max_open_zones = ns->params.max_active_zones; + if (!nsdev->params.max_open_zones) { + nsdev->params.max_open_zones = nsdev->params.max_active_zones; } } - if (ns->params.zd_extension_size) { - if (ns->params.zd_extension_size & 0x3f) { + if (nsdev->params.zd_extension_size) { + if (nsdev->params.zd_extension_size & 0x3f) { error_setg(errp, "zone descriptor extension size must be a " "multiple of 64B"); return -1; } - if ((ns->params.zd_extension_size >> 6) > 0xff) { + if ((nsdev->params.zd_extension_size >> 6) > 0xff) { error_setg(errp, "zone descriptor extension size is too large"); return -1; @@ -409,35 +399,57 @@ static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp) return 0; } -int nvme_ns_setup(NvmeNamespace *ns, Error **errp) +static int nvme_nsdev_setup(NvmeNamespaceDevice *nsdev, Error **errp) { - if (nvme_ns_check_constraints(ns, errp)) { + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(&nsdev->ns); + static uint64_t ns_count; + + if (nvme_nsdev_check_constraints(nsdev, errp)) { return -1; } - if (nvme_ns_init_blk(ns, errp)) { - return -1; + if (nsdev->params.shared) { + nsdev->ns.flags |= NVME_NS_SHARED; } - if (nvme_ns_init(ns, errp)) { - return -1; - } - if (ns->params.zoned) { - NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + nsdev->ns.nsid = nsdev->params.nsid; + memcpy(&nsdev->ns.uuid, &nsdev->params.uuid, sizeof(nsdev->ns.uuid)); - if (nvme_zns_check_calc_geometry(ns, errp) != 0) { + if (nsdev->params.eui64) { + stq_be_p(&nsdev->ns.eui64.v, nsdev->params.eui64); + } + + /* Substitute a missing EUI-64 by an autogenerated one */ + ++ns_count; + if (!nsdev->ns.eui64.v && nsdev->params.eui64_default) { + nsdev->ns.eui64.v = ns_count + NVME_EUI64_DEFAULT; + } + + nvm->id_ns.dps = nsdev->params.pi; + if (nsdev->params.pi && nsdev->params.pil) { + nvm->id_ns.dps |= NVME_ID_NS_DPS_FIRST_EIGHT; + } + + nsdev->ns.csi = NVME_CSI_NVM; + + nvme_ns_init(&nsdev->ns); + + if (nsdev->params.zoned) { + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(&nsdev->ns); + + if (nvme_nsdev_zns_check_calc_geometry(nsdev, errp) != 0) { return -1; } /* copy device parameters */ - zoned->zd_extension_size = ns->params.zd_extension_size; - zoned->max_open_zones = ns->params.max_open_zones; - zoned->max_active_zones = ns->params.max_open_zones; - if (ns->params.cross_zone_read) { + zoned->zd_extension_size = nsdev->params.zd_extension_size; + zoned->max_open_zones = nsdev->params.max_open_zones; + zoned->max_active_zones = nsdev->params.max_open_zones; + if (nsdev->params.cross_zone_read) { zoned->flags |= NVME_NS_ZONED_CROSS_READ; } - nvme_zns_init(ns); + nvme_zns_init(&nsdev->ns); } return 0; @@ -445,12 +457,12 @@ int nvme_ns_setup(NvmeNamespace *ns, Error **errp) void nvme_ns_drain(NvmeNamespace *ns) { - blk_drain(ns->blkconf.blk); + blk_drain(nvme_blk(ns)); } void nvme_ns_shutdown(NvmeNamespace *ns) { - blk_flush(ns->blkconf.blk); + blk_flush(nvme_blk(ns)); if (nvme_ns_zoned(ns)) { nvme_zns_shutdown(NVME_NAMESPACE_ZONED(ns)); } @@ -466,26 +478,28 @@ void nvme_ns_cleanup(NvmeNamespace *ns) } } -static void nvme_ns_unrealize(DeviceState *dev) +static void nvme_nsdev_unrealize(DeviceState *dev) { - NvmeNamespace *ns = NVME_NS(dev); + NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev); + NvmeNamespace *ns = &nsdev->ns; nvme_ns_drain(ns); nvme_ns_shutdown(ns); nvme_ns_cleanup(ns); } -static void nvme_ns_realize(DeviceState *dev, Error **errp) +static void nvme_nsdev_realize(DeviceState *dev, Error **errp) { - NvmeNamespace *ns = NVME_NS(dev); + NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev); + NvmeNamespace *ns = &nsdev->ns; BusState *s = qdev_get_parent_bus(dev); NvmeCtrl *n = NVME(s->parent); NvmeSubsystem *subsys = n->subsys; - uint32_t nsid = ns->params.nsid; + uint32_t nsid = nsdev->params.nsid; int i; if (!n->subsys) { - if (ns->params.detached) { + if (nsdev->params.detached) { error_setg(errp, "detached requires that the nvme device is " "linked to an nvme-subsys device"); return; @@ -500,7 +514,11 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp) } } - if (nvme_ns_setup(ns, errp)) { + if (nvme_nsdev_init_blk(nsdev, errp)) { + return; + } + + if (nvme_nsdev_setup(nsdev, errp)) { return; } @@ -510,7 +528,7 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp) continue; } - nsid = ns->params.nsid = i; + nsid = ns->nsid = i; break; } @@ -528,11 +546,11 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp) if (subsys) { subsys->namespaces[nsid] = ns; - if (ns->params.detached) { + if (nsdev->params.detached) { return; } - if (ns->params.shared) { + if (nsdev->params.shared) { for (i = 0; i < ARRAY_SIZE(subsys->ctrls); i++) { NvmeCtrl *ctrl = subsys->ctrls[i]; @@ -548,73 +566,74 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp) nvme_attach_ns(n, ns); } -static Property nvme_ns_props[] = { - DEFINE_BLOCK_PROPERTIES(NvmeNamespace, blkconf), - DEFINE_PROP_BOOL("detached", NvmeNamespace, params.detached, false), - DEFINE_PROP_BOOL("shared", NvmeNamespace, params.shared, true), - DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0), - DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid), - DEFINE_PROP_UINT64("eui64", NvmeNamespace, params.eui64, 0), - DEFINE_PROP_UINT16("ms", NvmeNamespace, params.ms, 0), - DEFINE_PROP_UINT8("mset", NvmeNamespace, params.mset, 0), - DEFINE_PROP_UINT8("pi", NvmeNamespace, params.pi, 0), - DEFINE_PROP_UINT8("pil", NvmeNamespace, params.pil, 0), - DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128), - DEFINE_PROP_UINT32("mcl", NvmeNamespace, params.mcl, 128), - DEFINE_PROP_UINT8("msrc", NvmeNamespace, params.msrc, 127), - DEFINE_PROP_BOOL("zoned", NvmeNamespace, params.zoned, false), - DEFINE_PROP_SIZE("zoned.zone_size", NvmeNamespace, params.zone_size_bs, +static Property nvme_nsdev_props[] = { + DEFINE_BLOCK_PROPERTIES(NvmeNamespaceDevice, blkconf), + DEFINE_PROP_BOOL("detached", NvmeNamespaceDevice, params.detached, false), + DEFINE_PROP_BOOL("shared", NvmeNamespaceDevice, params.shared, true), + DEFINE_PROP_UINT32("nsid", NvmeNamespaceDevice, params.nsid, 0), + DEFINE_PROP_UUID("uuid", NvmeNamespaceDevice, params.uuid), + DEFINE_PROP_UINT64("eui64", NvmeNamespaceDevice, params.eui64, 0), + DEFINE_PROP_UINT16("ms", NvmeNamespaceDevice, params.ms, 0), + DEFINE_PROP_UINT8("mset", NvmeNamespaceDevice, params.mset, 0), + DEFINE_PROP_UINT8("pi", NvmeNamespaceDevice, params.pi, 0), + DEFINE_PROP_UINT8("pil", NvmeNamespaceDevice, params.pil, 0), + DEFINE_PROP_UINT16("mssrl", NvmeNamespaceDevice, params.mssrl, 128), + DEFINE_PROP_UINT32("mcl", NvmeNamespaceDevice, params.mcl, 128), + DEFINE_PROP_UINT8("msrc", NvmeNamespaceDevice, params.msrc, 127), + DEFINE_PROP_BOOL("zoned", NvmeNamespaceDevice, params.zoned, false), + DEFINE_PROP_SIZE("zoned.zone_size", NvmeNamespaceDevice, params.zone_size_bs, NVME_DEFAULT_ZONE_SIZE), - DEFINE_PROP_SIZE("zoned.zone_capacity", NvmeNamespace, params.zone_cap_bs, + DEFINE_PROP_SIZE("zoned.zone_capacity", NvmeNamespaceDevice, params.zone_cap_bs, 0), - DEFINE_PROP_BOOL("zoned.cross_read", NvmeNamespace, + DEFINE_PROP_BOOL("zoned.cross_read", NvmeNamespaceDevice, params.cross_zone_read, false), - DEFINE_PROP_UINT32("zoned.max_active", NvmeNamespace, + DEFINE_PROP_UINT32("zoned.max_active", NvmeNamespaceDevice, params.max_active_zones, 0), - DEFINE_PROP_UINT32("zoned.max_open", NvmeNamespace, + DEFINE_PROP_UINT32("zoned.max_open", NvmeNamespaceDevice, params.max_open_zones, 0), - DEFINE_PROP_UINT32("zoned.descr_ext_size", NvmeNamespace, + DEFINE_PROP_UINT32("zoned.descr_ext_size", NvmeNamespaceDevice, params.zd_extension_size, 0), - DEFINE_PROP_BOOL("eui64-default", NvmeNamespace, params.eui64_default, + DEFINE_PROP_BOOL("eui64-default", NvmeNamespaceDevice, params.eui64_default, true), DEFINE_PROP_END_OF_LIST(), }; -static void nvme_ns_class_init(ObjectClass *oc, void *data) +static void nvme_nsdev_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); dc->bus_type = TYPE_NVME_BUS; - dc->realize = nvme_ns_realize; - dc->unrealize = nvme_ns_unrealize; - device_class_set_props(dc, nvme_ns_props); + dc->realize = nvme_nsdev_realize; + dc->unrealize = nvme_nsdev_unrealize; + device_class_set_props(dc, nvme_nsdev_props); dc->desc = "Virtual NVMe namespace"; } -static void nvme_ns_instance_init(Object *obj) +static void nvme_nsdev_instance_init(Object *obj) { - NvmeNamespace *ns = NVME_NS(obj); - char *bootindex = g_strdup_printf("/namespace@%d,0", ns->params.nsid); + NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(obj); + char *bootindex = g_strdup_printf("/namespace@%d,0", + nsdev->params.nsid); - device_add_bootindex_property(obj, &ns->bootindex, "bootindex", + device_add_bootindex_property(obj, &nsdev->bootindex, "bootindex", bootindex, DEVICE(obj)); g_free(bootindex); } -static const TypeInfo nvme_ns_info = { - .name = TYPE_NVME_NS, +static const TypeInfo nvme_nsdev_info = { + .name = TYPE_NVME_NAMESPACE_DEVICE, .parent = TYPE_DEVICE, - .class_init = nvme_ns_class_init, - .instance_size = sizeof(NvmeNamespace), - .instance_init = nvme_ns_instance_init, + .class_init = nvme_nsdev_class_init, + .instance_size = sizeof(NvmeNamespaceDevice), + .instance_init = nvme_nsdev_instance_init, }; -static void nvme_ns_register_types(void) +static void register_types(void) { - type_register_static(&nvme_ns_info); + type_register_static(&nvme_nsdev_info); } -type_init(nvme_ns_register_types) +type_init(register_types) diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 525bfd0ca831..356d95805f9e 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -80,9 +80,8 @@ static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys, return subsys->namespaces[nsid]; } -#define TYPE_NVME_NS "nvme-ns" -#define NVME_NS(obj) \ - OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS) +#define TYPE_NVME_NAMESPACE_DEVICE "nvme-ns" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeNamespaceDevice, NVME_NAMESPACE_DEVICE) typedef struct NvmeNamespaceParams { bool detached; @@ -170,19 +169,25 @@ typedef struct NvmeNamespaceNvm { unsigned long flags; } NvmeNamespaceNvm; +enum NvmeNamespaceFlags { + NVME_NS_SHARED = 1 << 0, +}; + typedef struct NvmeNamespace { - DeviceState parent_obj; - BlockConf blkconf; - int32_t bootindex; + uint32_t nsid; + uint8_t csi; + QemuUUID uuid; + union { + uint64_t v; + uint8_t a[8]; + } eui64; + + unsigned long flags; + const uint32_t *iocs; - uint8_t csi; uint16_t status; int attached; - QTAILQ_ENTRY(NvmeNamespace) entry; - - NvmeNamespaceParams params; - struct { uint32_t err_rec; } features; @@ -199,10 +204,19 @@ static inline BlockBackend *nvme_blk(NvmeNamespace *ns) return NVME_NAMESPACE_NVM(ns)->blk; } +typedef struct NvmeNamespaceDevice { + DeviceState parent_obj; + BlockConf blkconf; + int32_t bootindex; + + NvmeNamespace ns; + NvmeNamespaceParams params; +} NvmeNamespaceDevice; + static inline uint32_t nvme_nsid(NvmeNamespace *ns) { if (ns) { - return ns->params.nsid; + return ns->nsid; } return 0; @@ -228,8 +242,8 @@ static inline bool nvme_ns_ext(NvmeNamespaceNvm *nvm) return !!NVME_ID_NS_FLBAS_EXTENDED(nvm->id_ns.flbas); } -void nvme_ns_init_format(NvmeNamespace *ns); -int nvme_ns_setup(NvmeNamespace *ns, Error **errp); +void nvme_ns_nvm_init_format(NvmeNamespaceNvm *nvm); +void nvme_ns_init(NvmeNamespace *ns); void nvme_ns_drain(NvmeNamespace *ns); void nvme_ns_shutdown(NvmeNamespace *ns); void nvme_ns_cleanup(NvmeNamespace *ns); @@ -424,7 +438,7 @@ typedef struct NvmeCtrl { NvmeSubsystem *subsys; - NvmeNamespace namespace; + NvmeNamespaceDevice namespace; NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; NvmeSQueue **sq; NvmeCQueue **cq; diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 6b2e4c975f5b..5a9405d05fbe 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -31,7 +31,7 @@ int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp) for (nsid = 1; nsid < ARRAY_SIZE(subsys->namespaces); nsid++) { NvmeNamespace *ns = subsys->namespaces[nsid]; - if (ns && ns->params.shared && !ns->params.detached) { + if (ns && (ns->flags & NVME_NS_SHARED)) { nvme_attach_ns(n, ns); } } From patchwork Mon Sep 27 05:17:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533189 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=b072BLFX; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=sUVpNTnb; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrfR3Bbhz9t5m for ; Mon, 27 Sep 2021 15:24:14 +1000 (AEST) Received: from localhost ([::1]:41866 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUj7Z-0006xb-Ro for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:24:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34200) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2M-0003MS-4y; Mon, 27 Sep 2021 01:18:46 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:39165) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2K-0000Ho-0l; Mon, 27 Sep 2021 01:18:45 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.west.internal (Postfix) with ESMTP id 890EF2B01210; Mon, 27 Sep 2021 01:18:41 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 27 Sep 2021 01:18:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=UR/e9aCVn9FNh TyZUBSq9J9lnVuyv15+sBoph5fvb8M=; b=b072BLFX3Wj6vnsjJyckizCNBNSx1 dhmrQYxFjRjjfGPCDPQLNu5V5tVZ4euTbeAmRxKk7pK+rr+ikIVELkGI1rtr15Q4 k9+QI/thbz4PLSDSjXjqgKLWwN7WY7n3YD5dW8q+y6rQ07ZZjwZMp49khsm9ujUB lxbRNUgiXeIppCpVnsAhYIn9eF/fFVWoT8/7o4XkPuo3Shn0CyzYZMaT9sSpOpIr bbqFN/5IZmrcKG8ZbIW1Ph8NVzn/ktha+mc6O+3e9EY2ttpSoHU9x/WPTHynmWqL HzFuJOQhA5IU3iXFXSOBmph/sPcn/nRHgghzgCtupUOKei6GCOvYJAWNw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=UR/e9aCVn9FNhTyZUBSq9J9lnVuyv15+sBoph5fvb8M=; b=sUVpNTnb Dof9QJm2EWTH2w6kAqKlAVI2igxQtIg8/jZ71jSCgd/UxwmiMtDffmVUJdF9Fnx2 5Soo124CxSbJFYJ1HEYwYnWn8OZCZkjhJh8iZ2k64IQ8DGI7yGOizxSv/SLDi2M1 7HIMV1+06ESRzTqgddQ1dtInJB64Xj+UZFgbRN/b7vl/aSUDZxfevoMTpaNP41be 3BWDKKVz7A+wcKMTXADF7TCzzdlO03ccRVEW0kNvUh/WSW0vTOxhB3DqPgCQYc3T tLFT/ZoTo2KJhSpOezBGGPGuUhmwIR/y9xjhtSGao22P65CvIwd7ugOaFR3669yt rfPdCiVqB/ZuvA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeltdetfeegkefguedvtdduffejiedvjeejudejieelveekhfekvdefleeludev ffenucffohhmrghinhepvddtudelqddtkedrohhrghenucevlhhushhtvghrufhiiigvpe dtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehithhssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:38 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 09/16] hw/nvme: hoist qdev state from subsystem Date: Mon, 27 Sep 2021 07:17:52 +0200 Message-Id: <20210927051759.447305-10-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 10 +++++++--- hw/nvme/ns.c | 2 +- hw/nvme/nvme.h | 24 +++++++++++++++--------- hw/nvme/subsys.c | 36 ++++++++++++++++++------------------ 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 67600d075d32..af2a783ba4c0 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -6539,7 +6539,7 @@ static int nvme_init_subsys(NvmeCtrl *n, Error **errp) return 0; } - cntlid = nvme_subsys_register_ctrl(n, errp); + cntlid = nvme_subsys_register_ctrl(n->subsys, n, errp); if (cntlid < 0) { return -1; } @@ -6567,6 +6567,10 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) NvmeCtrl *n = NVME(pci_dev); Error *local_err = NULL; + if (n->subsys_dev) { + n->subsys = &n->subsys_dev->subsys; + } + nvme_check_constraints(n, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -6637,8 +6641,8 @@ static Property nvme_props[] = { DEFINE_BLOCK_PROPERTIES(NvmeCtrl, namespace.blkconf), DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmr.dev, TYPE_MEMORY_BACKEND, HostMemoryBackend *), - DEFINE_PROP_LINK("subsys", NvmeCtrl, subsys, TYPE_NVME_SUBSYS, - NvmeSubsystem *), + DEFINE_PROP_LINK("subsys", NvmeCtrl, subsys_dev, TYPE_NVME_SUBSYSTEM_DEVICE, + NvmeSubsystemDevice *), DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial), DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, params.cmb_size_mb, 0), DEFINE_PROP_UINT32("num_queues", NvmeCtrl, params.num_queues, 0), diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 582ff7d0236b..d67632174530 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -509,7 +509,7 @@ static void nvme_nsdev_realize(DeviceState *dev, Error **errp) * If this namespace belongs to a subsystem (through a link on the * controller device), reparent the device. */ - if (!qdev_set_parent_bus(dev, &subsys->bus.parent_bus, errp)) { + if (!qdev_set_parent_bus(dev, &n->subsys_dev->bus.parent_bus, errp)) { return; } } diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 356d95805f9e..e8f4b8e3e2e0 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -40,24 +40,29 @@ typedef struct NvmeBus { BusState parent_bus; } NvmeBus; -#define TYPE_NVME_SUBSYS "nvme-subsys" -#define NVME_SUBSYS(obj) \ - OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS) - typedef struct NvmeSubsystem { - DeviceState parent_obj; - NvmeBus bus; uint8_t subnqn[256]; NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS]; NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; +} NvmeSubsystem; + +#define TYPE_NVME_SUBSYSTEM_DEVICE "nvme-subsys" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeSubsystemDevice, NVME_SUBSYSTEM_DEVICE) + +typedef struct NvmeSubsystemDevice { + DeviceState parent_obj; + NvmeBus bus; + + NvmeSubsystem subsys; struct { char *nqn; } params; -} NvmeSubsystem; +} NvmeSubsystemDevice; -int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp); +int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n, + Error **errp); void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n); static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys, @@ -436,7 +441,8 @@ typedef struct NvmeCtrl { #define NVME_CHANGED_NSID_SIZE (NVME_MAX_NAMESPACES + 1) DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE); - NvmeSubsystem *subsys; + NvmeSubsystem *subsys; + NvmeSubsystemDevice *subsys_dev; NvmeNamespaceDevice namespace; NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 5a9405d05fbe..4d73d14070dc 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -11,9 +11,8 @@ #include "nvme.h" -int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp) +int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n, Error **errp) { - NvmeSubsystem *subsys = n->subsys; int cntlid, nsid; for (cntlid = 0; cntlid < ARRAY_SIZE(subsys->ctrls); cntlid++) { @@ -45,53 +44,54 @@ void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n) n->cntlid = -1; } -static void nvme_subsys_setup(NvmeSubsystem *subsys) +static void nvme_subsys_device_setup(NvmeSubsystemDevice *dev) { - const char *nqn = subsys->params.nqn ? - subsys->params.nqn : subsys->parent_obj.id; + NvmeSubsystem *subsys = &dev->subsys; + const char *nqn = dev->params.nqn ? + dev->params.nqn : dev->parent_obj.id; snprintf((char *)subsys->subnqn, sizeof(subsys->subnqn), "nqn.2019-08.org.qemu:%s", nqn); } -static void nvme_subsys_realize(DeviceState *dev, Error **errp) +static void nvme_subsys_device_realize(DeviceState *dev, Error **errp) { - NvmeSubsystem *subsys = NVME_SUBSYS(dev); + NvmeSubsystemDevice *subsys = NVME_SUBSYSTEM_DEVICE(dev); qbus_create_inplace(&subsys->bus, sizeof(NvmeBus), TYPE_NVME_BUS, dev, dev->id); - nvme_subsys_setup(subsys); + nvme_subsys_device_setup(subsys); } -static Property nvme_subsystem_props[] = { - DEFINE_PROP_STRING("nqn", NvmeSubsystem, params.nqn), +static Property nvme_subsystem_device_props[] = { + DEFINE_PROP_STRING("nqn", NvmeSubsystemDevice, params.nqn), DEFINE_PROP_END_OF_LIST(), }; -static void nvme_subsys_class_init(ObjectClass *oc, void *data) +static void nvme_subsys_device_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->realize = nvme_subsys_realize; + dc->realize = nvme_subsys_device_realize; dc->desc = "Virtual NVMe subsystem"; dc->hotpluggable = false; - device_class_set_props(dc, nvme_subsystem_props); + device_class_set_props(dc, nvme_subsystem_device_props); } -static const TypeInfo nvme_subsys_info = { - .name = TYPE_NVME_SUBSYS, +static const TypeInfo nvme_subsys_device_info = { + .name = TYPE_NVME_SUBSYSTEM_DEVICE, .parent = TYPE_DEVICE, - .class_init = nvme_subsys_class_init, - .instance_size = sizeof(NvmeSubsystem), + .class_init = nvme_subsys_device_class_init, + .instance_size = sizeof(NvmeSubsystemDevice), }; static void nvme_subsys_register_types(void) { - type_register_static(&nvme_subsys_info); + type_register_static(&nvme_subsys_device_info); } type_init(nvme_subsys_register_types) From patchwork Mon Sep 27 05:17:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533193 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=oCRxbc9Q; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=gvV0g6tM; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHrpt3Xzpz9t5m for ; Mon, 27 Sep 2021 15:31:34 +1000 (AEST) Received: from localhost ([::1]:51762 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjEh-0005Cc-Td for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:31:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34234) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2T-0003cX-37; Mon, 27 Sep 2021 01:18:53 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:44667) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2O-0000KK-9S; Mon, 27 Sep 2021 01:18:52 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailnew.west.internal (Postfix) with ESMTP id AB41A2B01213; Mon, 27 Sep 2021 01:18:45 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Mon, 27 Sep 2021 01:18:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=KJigw2qACnPIh 8cp/H6Ol5pWa50HzJbNQOjjFBbC84g=; b=oCRxbc9QQ1hfF6/vcSsh1LlNgxJEj 6tGGMoRZ11X5qlG2bhIEVuv/XSwVPwI0WDIBfUNpmm1mMoiBTZU51zmC91igJVKz l9c+/760fcZjur7Ui8878Za1yo5f95VjT5qTnteoXVa31n3bHn63TsE8W7OJ6KQq wmQsv6MTjKXuhi0DhDJ/5QBYP3tWDlPHlO3TA7eeTpQi9rrOCvEHi6lKJu1FLlj3 OHKYb/p4cCx1LQ5HiogOLNTzsNP25OttPKGTSBpXa2Nzfe18cxd99bNa4mcpijof wb8ubHmZkseq8LtNNtYwTcRkPckAXyVmFAiFbxba+vQ7tvJeA3pGCXltg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=KJigw2qACnPIh8cp/H6Ol5pWa50HzJbNQOjjFBbC84g=; b=gvV0g6tM v/D19vdl6PeFzzqnHOgJc2rBDEZ97JryVmQ0MEw3IGcd3e8hOEBRZNqpgpKzxWgG 5ecyOu3llS5JixPXTv35Ndm5V+Ram2BNBQCZ0QEOAKlSp5A5fl9JNBArCK40NZyw dnjjePhRM/jgLZbHT17/5jDgZ/z0VfNkJWE48A0rhliGFCAGqQFAWWkTCat49gpK UW6NcLt0U0iwgITP2Nson/DpjABDoM58JPDWU/B7JnACahS859eqCJ4XuPD+NDh0 aKpjODJU3Tgku4oAIB6UjgHH7ABf85HrXIeU8n3IU++vEBGSu3dQwJK4ViAyOgt2 G7QcLG1S5yK5Sw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeduieetfeejjeegvefhjeeuvdeuiefgfffgvdetteevteejjeeugeduhfehgeff keenucffohhmrghinhepqhguvghvrdhiugenucevlhhushhtvghrufhiiigvpedtnecurf grrhgrmhepmhgrihhlfhhrohhmpehithhssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:42 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 10/16] hw/nvme: hoist qdev state from controller Date: Mon, 27 Sep 2021 07:17:53 +0200 Message-Id: <20210927051759.447305-11-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add an abstract object NvmeState. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 382 +++++++++++++++++++++++++---------------------- hw/nvme/dif.c | 4 +- hw/nvme/dif.h | 2 +- hw/nvme/ns.c | 4 +- hw/nvme/nvme.h | 52 ++++--- hw/nvme/subsys.c | 4 +- 6 files changed, 239 insertions(+), 209 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index af2a783ba4c0..b27bf00f623f 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -323,7 +323,7 @@ static int nvme_zns_aor_check(NvmeNamespaceZoned *zoned, uint32_t act, return NVME_SUCCESS; } -static bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr) +static bool nvme_addr_is_cmb(NvmeState *n, hwaddr addr) { hwaddr hi, lo; @@ -337,13 +337,13 @@ static bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr) return addr >= lo && addr < hi; } -static inline void *nvme_addr_to_cmb(NvmeCtrl *n, hwaddr addr) +static inline void *nvme_addr_to_cmb(NvmeState *n, hwaddr addr) { hwaddr base = n->params.legacy_cmb ? n->cmb.mem.addr : n->cmb.cba; return &n->cmb.buf[addr - base]; } -static bool nvme_addr_is_pmr(NvmeCtrl *n, hwaddr addr) +static bool nvme_addr_is_pmr(NvmeState *n, hwaddr addr) { hwaddr hi; @@ -356,12 +356,12 @@ static bool nvme_addr_is_pmr(NvmeCtrl *n, hwaddr addr) return addr >= n->pmr.cba && addr < hi; } -static inline void *nvme_addr_to_pmr(NvmeCtrl *n, hwaddr addr) +static inline void *nvme_addr_to_pmr(NvmeState *n, hwaddr addr) { return memory_region_get_ram_ptr(&n->pmr.dev->mr) + (addr - n->pmr.cba); } -static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) +static int nvme_addr_read(NvmeState *n, hwaddr addr, void *buf, int size) { hwaddr hi = addr + size - 1; if (hi < addr) { @@ -381,7 +381,7 @@ static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size) return pci_dma_read(&n->parent_obj, addr, buf, size); } -static int nvme_addr_write(NvmeCtrl *n, hwaddr addr, void *buf, int size) +static int nvme_addr_write(NvmeState *n, hwaddr addr, void *buf, int size) { hwaddr hi = addr + size - 1; if (hi < addr) { @@ -401,18 +401,18 @@ static int nvme_addr_write(NvmeCtrl *n, hwaddr addr, void *buf, int size) return pci_dma_write(&n->parent_obj, addr, buf, size); } -static bool nvme_nsid_valid(NvmeCtrl *n, uint32_t nsid) +static bool nvme_nsid_valid(NvmeState *n, uint32_t nsid) { return nsid && (nsid == NVME_NSID_BROADCAST || nsid <= NVME_MAX_NAMESPACES); } -static int nvme_check_sqid(NvmeCtrl *n, uint16_t sqid) +static int nvme_check_sqid(NvmeState *n, uint16_t sqid) { return sqid < n->params.max_ioqpairs + 1 && n->sq[sqid] != NULL ? 0 : -1; } -static int nvme_check_cqid(NvmeCtrl *n, uint16_t cqid) +static int nvme_check_cqid(NvmeState *n, uint16_t cqid) { return cqid < n->params.max_ioqpairs + 1 && n->cq[cqid] != NULL ? 0 : -1; } @@ -441,7 +441,7 @@ static uint8_t nvme_sq_empty(NvmeSQueue *sq) return sq->head == sq->tail; } -static void nvme_irq_check(NvmeCtrl *n) +static void nvme_irq_check(NvmeState *n) { uint32_t intms = ldl_le_p(&n->bar.intms); @@ -455,7 +455,7 @@ static void nvme_irq_check(NvmeCtrl *n) } } -static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq) +static void nvme_irq_assert(NvmeState *n, NvmeCQueue *cq) { if (cq->irq_enabled) { if (msix_enabled(&(n->parent_obj))) { @@ -472,7 +472,7 @@ static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq) } } -static void nvme_irq_deassert(NvmeCtrl *n, NvmeCQueue *cq) +static void nvme_irq_deassert(NvmeState *n, NvmeCQueue *cq) { if (cq->irq_enabled) { if (msix_enabled(&(n->parent_obj))) { @@ -496,7 +496,7 @@ static void nvme_req_clear(NvmeRequest *req) req->status = NVME_SUCCESS; } -static inline void nvme_sg_init(NvmeCtrl *n, NvmeSg *sg, bool dma) +static inline void nvme_sg_init(NvmeState *n, NvmeSg *sg, bool dma) { if (dma) { pci_dma_sglist_init(&sg->qsg, &n->parent_obj, 0); @@ -574,7 +574,7 @@ static void nvme_sg_split(NvmeSg *sg, NvmeNamespaceNvm *nvm, NvmeSg *data, } } -static uint16_t nvme_map_addr_cmb(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr, +static uint16_t nvme_map_addr_cmb(NvmeState *n, QEMUIOVector *iov, hwaddr addr, size_t len) { if (!len) { @@ -592,7 +592,7 @@ static uint16_t nvme_map_addr_cmb(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr, return NVME_SUCCESS; } -static uint16_t nvme_map_addr_pmr(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr, +static uint16_t nvme_map_addr_pmr(NvmeState *n, QEMUIOVector *iov, hwaddr addr, size_t len) { if (!len) { @@ -608,7 +608,7 @@ static uint16_t nvme_map_addr_pmr(NvmeCtrl *n, QEMUIOVector *iov, hwaddr addr, return NVME_SUCCESS; } -static uint16_t nvme_map_addr(NvmeCtrl *n, NvmeSg *sg, hwaddr addr, size_t len) +static uint16_t nvme_map_addr(NvmeState *n, NvmeSg *sg, hwaddr addr, size_t len) { bool cmb = false, pmr = false; @@ -658,12 +658,12 @@ max_mappings_exceeded: return NVME_INTERNAL_DEV_ERROR | NVME_DNR; } -static inline bool nvme_addr_is_dma(NvmeCtrl *n, hwaddr addr) +static inline bool nvme_addr_is_dma(NvmeState *n, hwaddr addr) { return !(nvme_addr_is_cmb(n, addr) || nvme_addr_is_pmr(n, addr)); } -static uint16_t nvme_map_prp(NvmeCtrl *n, NvmeSg *sg, uint64_t prp1, +static uint16_t nvme_map_prp(NvmeState *n, NvmeSg *sg, uint64_t prp1, uint64_t prp2, uint32_t len) { hwaddr trans_len = n->page_size - (prp1 % n->page_size); @@ -764,7 +764,7 @@ unmap: * Map 'nsgld' data descriptors from 'segment'. The function will subtract the * number of bytes mapped in len. */ -static uint16_t nvme_map_sgl_data(NvmeCtrl *n, NvmeSg *sg, +static uint16_t nvme_map_sgl_data(NvmeState *n, NvmeSg *sg, NvmeSglDescriptor *segment, uint64_t nsgld, size_t *len, NvmeCmd *cmd) { @@ -834,7 +834,7 @@ next: return NVME_SUCCESS; } -static uint16_t nvme_map_sgl(NvmeCtrl *n, NvmeSg *sg, NvmeSglDescriptor sgl, +static uint16_t nvme_map_sgl(NvmeState *n, NvmeSg *sg, NvmeSglDescriptor sgl, size_t len, NvmeCmd *cmd) { /* @@ -977,7 +977,7 @@ unmap: return status; } -uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, +uint16_t nvme_map_dptr(NvmeState *n, NvmeSg *sg, size_t len, NvmeCmd *cmd) { uint64_t prp1, prp2; @@ -996,7 +996,7 @@ uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, } } -static uint16_t nvme_map_mptr(NvmeCtrl *n, NvmeSg *sg, size_t len, +static uint16_t nvme_map_mptr(NvmeState *n, NvmeSg *sg, size_t len, NvmeCmd *cmd) { int psdt = NVME_CMD_FLAGS_PSDT(cmd->flags); @@ -1027,7 +1027,7 @@ static uint16_t nvme_map_mptr(NvmeCtrl *n, NvmeSg *sg, size_t len, return status; } -static uint16_t nvme_map_data(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) +static uint16_t nvme_map_data(NvmeState *n, uint32_t nlb, NvmeRequest *req) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; @@ -1056,7 +1056,7 @@ static uint16_t nvme_map_data(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) return nvme_map_dptr(n, &req->sg, len, &req->cmd); } -static uint16_t nvme_map_mdata(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) +static uint16_t nvme_map_mdata(NvmeState *n, uint32_t nlb, NvmeRequest *req) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); size_t len = nvme_m2b(nvm, nlb); @@ -1082,7 +1082,7 @@ static uint16_t nvme_map_mdata(NvmeCtrl *n, uint32_t nlb, NvmeRequest *req) return nvme_map_mptr(n, &req->sg, len, &req->cmd); } -static uint16_t nvme_tx_interleaved(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, +static uint16_t nvme_tx_interleaved(NvmeState *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, uint32_t bytes, int32_t skip_bytes, int64_t offset, NvmeTxDirection dir) @@ -1144,7 +1144,7 @@ static uint16_t nvme_tx_interleaved(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, return NVME_SUCCESS; } -static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, +static uint16_t nvme_tx(NvmeState *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, NvmeTxDirection dir) { assert(sg->flags & NVME_SG_ALLOC); @@ -1180,7 +1180,7 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, return NVME_SUCCESS; } -static inline uint16_t nvme_c2h(NvmeCtrl *n, uint8_t *ptr, uint32_t len, +static inline uint16_t nvme_c2h(NvmeState *n, uint8_t *ptr, uint32_t len, NvmeRequest *req) { uint16_t status; @@ -1193,7 +1193,7 @@ static inline uint16_t nvme_c2h(NvmeCtrl *n, uint8_t *ptr, uint32_t len, return nvme_tx(n, &req->sg, ptr, len, NVME_TX_DIRECTION_FROM_DEVICE); } -static inline uint16_t nvme_h2c(NvmeCtrl *n, uint8_t *ptr, uint32_t len, +static inline uint16_t nvme_h2c(NvmeState *n, uint8_t *ptr, uint32_t len, NvmeRequest *req) { uint16_t status; @@ -1206,7 +1206,7 @@ static inline uint16_t nvme_h2c(NvmeCtrl *n, uint8_t *ptr, uint32_t len, return nvme_tx(n, &req->sg, ptr, len, NVME_TX_DIRECTION_TO_DEVICE); } -uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len, +uint16_t nvme_bounce_data(NvmeState *n, uint8_t *ptr, uint32_t len, NvmeTxDirection dir, NvmeRequest *req) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); @@ -1222,7 +1222,7 @@ uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len, return nvme_tx(n, &req->sg, ptr, len, dir); } -uint16_t nvme_bounce_mdata(NvmeCtrl *n, uint8_t *ptr, uint32_t len, +uint16_t nvme_bounce_mdata(NvmeState *n, uint8_t *ptr, uint32_t len, NvmeTxDirection dir, NvmeRequest *req) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(req->ns); @@ -1272,7 +1272,7 @@ static inline void nvme_blk_write(BlockBackend *blk, int64_t offset, static void nvme_post_cqes(void *opaque) { NvmeCQueue *cq = opaque; - NvmeCtrl *n = cq->ctrl; + NvmeState *n = cq->ctrl; NvmeRequest *req, *next; bool pending = cq->head != cq->tail; int ret; @@ -1332,7 +1332,7 @@ static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req) static void nvme_process_aers(void *opaque) { - NvmeCtrl *n = opaque; + NvmeState *n = opaque; NvmeAsyncEvent *event, *next; trace_pci_nvme_process_aers(n->aer_queued); @@ -1374,7 +1374,7 @@ static void nvme_process_aers(void *opaque) } } -static void nvme_enqueue_event(NvmeCtrl *n, uint8_t event_type, +static void nvme_enqueue_event(NvmeState *n, uint8_t event_type, uint8_t event_info, uint8_t log_page) { NvmeAsyncEvent *event; @@ -1399,7 +1399,7 @@ static void nvme_enqueue_event(NvmeCtrl *n, uint8_t event_type, nvme_process_aers(n); } -static void nvme_smart_event(NvmeCtrl *n, uint8_t event) +static void nvme_smart_event(NvmeState *n, uint8_t event) { uint8_t aer_info; @@ -1428,7 +1428,7 @@ static void nvme_smart_event(NvmeCtrl *n, uint8_t event) nvme_enqueue_event(n, NVME_AER_TYPE_SMART, aer_info, NVME_LOG_SMART_INFO); } -static void nvme_clear_events(NvmeCtrl *n, uint8_t event_type) +static void nvme_clear_events(NvmeState *n, uint8_t event_type) { n->aer_mask &= ~(1 << event_type); if (!QTAILQ_EMPTY(&n->aer_queue)) { @@ -1436,7 +1436,7 @@ static void nvme_clear_events(NvmeCtrl *n, uint8_t event_type) } } -static inline uint16_t nvme_check_mdts(NvmeCtrl *n, size_t len) +static inline uint16_t nvme_check_mdts(NvmeState *n, size_t len) { uint8_t mdts = n->params.mdts; @@ -1745,7 +1745,7 @@ enum { NVME_ZRM_AUTO = 1 << 0, }; -static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespaceZoned *zoned, +static uint16_t nvme_zrm_open_flags(NvmeState *n, NvmeNamespaceZoned *zoned, NvmeZone *zone, int flags) { int act = 0; @@ -1796,13 +1796,13 @@ static uint16_t nvme_zrm_open_flags(NvmeCtrl *n, NvmeNamespaceZoned *zoned, } } -static inline uint16_t nvme_zrm_auto(NvmeCtrl *n, NvmeNamespaceZoned *zoned, +static inline uint16_t nvme_zrm_auto(NvmeState *n, NvmeNamespaceZoned *zoned, NvmeZone *zone) { return nvme_zrm_open_flags(n, zoned, zone, NVME_ZRM_AUTO); } -static inline uint16_t nvme_zrm_open(NvmeCtrl *n, NvmeNamespaceZoned *zoned, +static inline uint16_t nvme_zrm_open(NvmeState *n, NvmeNamespaceZoned *zoned, NvmeZone *zone) { return nvme_zrm_open_flags(n, zoned, zone, 0); @@ -1918,7 +1918,7 @@ static void nvme_rw_cb(void *opaque, int ret) uint16_t status; nvme_sg_unmap(&req->sg); - status = nvme_map_mdata(nvme_ctrl(req), nlb, req); + status = nvme_map_mdata(nvme_state(req), nlb, req); if (status) { ret = -EFAULT; goto out; @@ -2038,7 +2038,7 @@ static void nvme_compare_mdata_cb(void *opaque, int ret) NvmeRequest *req = opaque; NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - NvmeCtrl *n = nvme_ctrl(req); + NvmeState *n = nvme_state(req); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); uint16_t apptag = le16_to_cpu(rw->apptag); @@ -2123,7 +2123,7 @@ out: static void nvme_compare_data_cb(void *opaque, int ret) { NvmeRequest *req = opaque; - NvmeCtrl *n = nvme_ctrl(req); + NvmeState *n = nvme_state(req); NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockBackend *blk = nvme_blk(ns); @@ -2286,7 +2286,7 @@ static void nvme_dsm_cb(void *opaque, int ret) { NvmeDSMAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; - NvmeCtrl *n = nvme_ctrl(req); + NvmeState *n = nvme_state(req); NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeDsmRange *range; @@ -2330,7 +2330,7 @@ done: qemu_bh_schedule(iocb->bh); } -static uint16_t nvme_dsm(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_dsm(NvmeState *n, NvmeRequest *req) { NvmeNamespace *ns = req->ns; NvmeDsmCmd *dsm = (NvmeDsmCmd *) &req->cmd; @@ -2366,7 +2366,7 @@ static uint16_t nvme_dsm(NvmeCtrl *n, NvmeRequest *req) return status; } -static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_verify(NvmeState *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; @@ -2774,8 +2774,7 @@ done: } } - -static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_copy(NvmeState *n, NvmeRequest *req) { NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); @@ -2863,7 +2862,7 @@ invalid: return status; } -static uint16_t nvme_compare(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_compare(NvmeState *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; @@ -2984,7 +2983,7 @@ static void nvme_flush_bh(void *opaque) { NvmeFlushAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; - NvmeCtrl *n = nvme_ctrl(req); + NvmeState *n = nvme_state(req); int i; if (iocb->ret < 0) { @@ -3019,7 +3018,7 @@ done: return; } -static uint16_t nvme_flush(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_flush(NvmeState *n, NvmeRequest *req) { NvmeFlushAIOCB *iocb; uint32_t nsid = le32_to_cpu(req->cmd.nsid); @@ -3062,7 +3061,7 @@ out: return status; } -static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_read(NvmeState *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; @@ -3136,7 +3135,7 @@ invalid: return status | NVME_DNR; } -static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest *req, bool append, +static uint16_t nvme_do_write(NvmeState *n, NvmeRequest *req, bool append, bool wrz) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; @@ -3272,17 +3271,17 @@ invalid: return status | NVME_DNR; } -static inline uint16_t nvme_write(NvmeCtrl *n, NvmeRequest *req) +static inline uint16_t nvme_write(NvmeState *n, NvmeRequest *req) { return nvme_do_write(n, req, false, false); } -static inline uint16_t nvme_write_zeroes(NvmeCtrl *n, NvmeRequest *req) +static inline uint16_t nvme_write_zeroes(NvmeState *n, NvmeRequest *req) { return nvme_do_write(n, req, false, true); } -static inline uint16_t nvme_zone_append(NvmeCtrl *n, NvmeRequest *req) +static inline uint16_t nvme_zone_append(NvmeState *n, NvmeRequest *req) { return nvme_do_write(n, req, true, false); } @@ -3330,7 +3329,7 @@ enum NvmeZoneProcessingMask { static uint16_t nvme_open_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone, NvmeZoneState state, NvmeRequest *req) { - return nvme_zrm_open(nvme_ctrl(req), zoned, zone); + return nvme_zrm_open(nvme_state(req), zoned, zone); } static uint16_t nvme_close_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone, @@ -3609,7 +3608,7 @@ done: } } -static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_zone_mgmt_send(NvmeState *n, NvmeRequest *req) { NvmeCmd *cmd = (NvmeCmd *)&req->cmd; NvmeNamespace *ns = req->ns; @@ -3758,7 +3757,7 @@ static bool nvme_zone_matches_filter(uint32_t zafs, NvmeZone *zl) } } -static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_zone_mgmt_recv(NvmeState *n, NvmeRequest *req) { NvmeCmd *cmd = (NvmeCmd *)&req->cmd; NvmeNamespace *ns = req->ns; @@ -3866,7 +3865,7 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n, NvmeRequest *req) return status; } -static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_io_cmd(NvmeState *n, NvmeRequest *req) { NvmeNamespace *ns; uint32_t nsid = le32_to_cpu(req->cmd.nsid); @@ -3949,7 +3948,7 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) return NVME_INVALID_OPCODE | NVME_DNR; } -static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n) +static void nvme_free_sq(NvmeSQueue *sq, NvmeState *n) { n->sq[sq->sqid] = NULL; timer_free(sq->timer); @@ -3959,7 +3958,7 @@ static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n) } } -static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_del_sq(NvmeState *n, NvmeRequest *req) { NvmeDeleteQ *c = (NvmeDeleteQ *)&req->cmd; NvmeRequest *r, *next; @@ -4000,7 +3999,7 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeRequest *req) return NVME_SUCCESS; } -static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, +static void nvme_init_sq(NvmeSQueue *sq, NvmeState *n, uint64_t dma_addr, uint16_t sqid, uint16_t cqid, uint16_t size) { int i; @@ -4028,7 +4027,7 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, n->sq[sqid] = sq; } -static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_create_sq(NvmeState *n, NvmeRequest *req) { NvmeSQueue *sq; NvmeCreateSq *c = (NvmeCreateSq *)&req->cmd; @@ -4084,7 +4083,7 @@ static void nvme_set_blk_stats(NvmeNamespace *ns, struct nvme_stats *stats) stats->write_commands += s->nr_ops[BLOCK_ACCT_WRITE]; } -static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, +static uint16_t nvme_smart_info(NvmeState *n, uint8_t rae, uint32_t buf_len, uint64_t off, NvmeRequest *req) { uint32_t nsid = le32_to_cpu(req->cmd.nsid); @@ -4144,7 +4143,7 @@ static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, return nvme_c2h(n, (uint8_t *) &smart + off, trans_len, req); } -static uint16_t nvme_fw_log_info(NvmeCtrl *n, uint32_t buf_len, uint64_t off, +static uint16_t nvme_fw_log_info(NvmeState *n, uint32_t buf_len, uint64_t off, NvmeRequest *req) { uint32_t trans_len; @@ -4162,7 +4161,7 @@ static uint16_t nvme_fw_log_info(NvmeCtrl *n, uint32_t buf_len, uint64_t off, return nvme_c2h(n, (uint8_t *) &fw_log + off, trans_len, req); } -static uint16_t nvme_error_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, +static uint16_t nvme_error_info(NvmeState *n, uint8_t rae, uint32_t buf_len, uint64_t off, NvmeRequest *req) { uint32_t trans_len; @@ -4182,7 +4181,7 @@ static uint16_t nvme_error_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, return nvme_c2h(n, (uint8_t *)&errlog, trans_len, req); } -static uint16_t nvme_changed_nslist(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, +static uint16_t nvme_changed_nslist(NvmeState *n, uint8_t rae, uint32_t buf_len, uint64_t off, NvmeRequest *req) { uint32_t nslist[1024]; @@ -4224,7 +4223,7 @@ static uint16_t nvme_changed_nslist(NvmeCtrl *n, uint8_t rae, uint32_t buf_len, return nvme_c2h(n, ((uint8_t *)nslist) + off, trans_len, req); } -static uint16_t nvme_cmd_effects(NvmeCtrl *n, uint8_t csi, uint32_t buf_len, +static uint16_t nvme_cmd_effects(NvmeState *n, uint8_t csi, uint32_t buf_len, uint64_t off, NvmeRequest *req) { NvmeEffectsLog log = {}; @@ -4264,7 +4263,7 @@ static uint16_t nvme_cmd_effects(NvmeCtrl *n, uint8_t csi, uint32_t buf_len, return nvme_c2h(n, ((uint8_t *)&log) + off, trans_len, req); } -static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_get_log(NvmeState *n, NvmeRequest *req) { NvmeCmd *cmd = &req->cmd; @@ -4317,7 +4316,7 @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req) } } -static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n) +static void nvme_free_cq(NvmeCQueue *cq, NvmeState *n) { n->cq[cq->cqid] = NULL; timer_free(cq->timer); @@ -4329,7 +4328,7 @@ static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n) } } -static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_del_cq(NvmeState *n, NvmeRequest *req) { NvmeDeleteQ *c = (NvmeDeleteQ *)&req->cmd; NvmeCQueue *cq; @@ -4356,7 +4355,7 @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeRequest *req) return NVME_SUCCESS; } -static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr, +static void nvme_init_cq(NvmeCQueue *cq, NvmeState *n, uint64_t dma_addr, uint16_t cqid, uint16_t vector, uint16_t size, uint16_t irq_enabled) { @@ -4380,7 +4379,7 @@ static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr, cq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_post_cqes, cq); } -static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_create_cq(NvmeState *n, NvmeRequest *req) { NvmeCQueue *cq; NvmeCreateCq *c = (NvmeCreateCq *)&req->cmd; @@ -4432,21 +4431,21 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeRequest *req) return NVME_SUCCESS; } -static uint16_t nvme_rpt_empty_id_struct(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_rpt_empty_id_struct(NvmeState *n, NvmeRequest *req) { uint8_t id[NVME_IDENTIFY_DATA_SIZE] = {}; return nvme_c2h(n, id, sizeof(id), req); } -static uint16_t nvme_identify_ctrl(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_identify_ctrl(NvmeState *n, NvmeRequest *req) { trace_pci_nvme_identify_ctrl(); return nvme_c2h(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl), req); } -static uint16_t nvme_identify_ctrl_csi(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_identify_ctrl_csi(NvmeState *n, NvmeRequest *req) { NvmeIdentify *c = (NvmeIdentify *)&req->cmd; uint8_t id[NVME_IDENTIFY_DATA_SIZE] = {}; @@ -4471,7 +4470,7 @@ static uint16_t nvme_identify_ctrl_csi(NvmeCtrl *n, NvmeRequest *req) return nvme_c2h(n, id, sizeof(id), req); } -static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req, bool active) +static uint16_t nvme_identify_ns(NvmeState *n, NvmeRequest *req, bool active) { NvmeNamespace *ns; NvmeIdentify *c = (NvmeIdentify *)&req->cmd; @@ -4503,7 +4502,7 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req, bool active) return NVME_INVALID_CMD_SET | NVME_DNR; } -static uint16_t nvme_identify_ctrl_list(NvmeCtrl *n, NvmeRequest *req, +static uint16_t nvme_identify_ctrl_list(NvmeState *n, NvmeRequest *req, bool attached) { NvmeIdentify *c = (NvmeIdentify *)&req->cmd; @@ -4512,7 +4511,7 @@ static uint16_t nvme_identify_ctrl_list(NvmeCtrl *n, NvmeRequest *req, uint16_t list[NVME_CONTROLLER_LIST_SIZE] = {}; uint16_t *ids = &list[1]; NvmeNamespace *ns; - NvmeCtrl *ctrl; + NvmeState *ctrl; int cntlid, nr_ids = 0; trace_pci_nvme_identify_ctrl_list(c->cns, min_id); @@ -4550,7 +4549,7 @@ static uint16_t nvme_identify_ctrl_list(NvmeCtrl *n, NvmeRequest *req, return nvme_c2h(n, (uint8_t *)list, sizeof(list), req); } -static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req, +static uint16_t nvme_identify_ns_csi(NvmeState *n, NvmeRequest *req, bool active) { NvmeNamespace *ns; @@ -4585,7 +4584,7 @@ static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req, return NVME_INVALID_FIELD | NVME_DNR; } -static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req, +static uint16_t nvme_identify_nslist(NvmeState *n, NvmeRequest *req, bool active) { NvmeNamespace *ns; @@ -4632,7 +4631,7 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req, return nvme_c2h(n, list, data_len, req); } -static uint16_t nvme_identify_nslist_csi(NvmeCtrl *n, NvmeRequest *req, +static uint16_t nvme_identify_nslist_csi(NvmeState *n, NvmeRequest *req, bool active) { NvmeNamespace *ns; @@ -4680,7 +4679,7 @@ static uint16_t nvme_identify_nslist_csi(NvmeCtrl *n, NvmeRequest *req, return nvme_c2h(n, list, data_len, req); } -static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_identify_ns_descr_list(NvmeState *n, NvmeRequest *req) { NvmeNamespace *ns; NvmeIdentify *c = (NvmeIdentify *)&req->cmd; @@ -4739,7 +4738,7 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req) return nvme_c2h(n, list, sizeof(list), req); } -static uint16_t nvme_identify_cmd_set(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_identify_cmd_set(NvmeState *n, NvmeRequest *req) { uint8_t list[NVME_IDENTIFY_DATA_SIZE] = {}; static const int data_len = sizeof(list); @@ -4752,7 +4751,7 @@ static uint16_t nvme_identify_cmd_set(NvmeCtrl *n, NvmeRequest *req) return nvme_c2h(n, list, data_len, req); } -static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_identify(NvmeState *n, NvmeRequest *req) { NvmeIdentify *c = (NvmeIdentify *)&req->cmd; @@ -4794,7 +4793,7 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req) } } -static uint16_t nvme_abort(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_abort(NvmeState *n, NvmeRequest *req) { uint16_t sqid = le32_to_cpu(req->cmd.cdw10) & 0xffff; @@ -4806,7 +4805,7 @@ static uint16_t nvme_abort(NvmeCtrl *n, NvmeRequest *req) return NVME_SUCCESS; } -static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts) +static inline void nvme_set_timestamp(NvmeState *n, uint64_t ts) { trace_pci_nvme_setfeat_timestamp(ts); @@ -4814,7 +4813,7 @@ static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts) n->timestamp_set_qemu_clock_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); } -static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n) +static inline uint64_t nvme_get_timestamp(const NvmeState *n) { uint64_t current_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); uint64_t elapsed_time = current_time - n->timestamp_set_qemu_clock_ms; @@ -4841,14 +4840,14 @@ static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n) return cpu_to_le64(ts.all); } -static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_get_feature_timestamp(NvmeState *n, NvmeRequest *req) { uint64_t timestamp = nvme_get_timestamp(n); return nvme_c2h(n, (uint8_t *)×tamp, sizeof(timestamp), req); } -static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_get_feature(NvmeState *n, NvmeRequest *req) { NvmeCmd *cmd = &req->cmd; uint32_t dw10 = le32_to_cpu(cmd->cdw10); @@ -4998,7 +4997,7 @@ out: return NVME_SUCCESS; } -static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_set_feature_timestamp(NvmeState *n, NvmeRequest *req) { uint16_t ret; uint64_t timestamp; @@ -5013,7 +5012,7 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeRequest *req) return NVME_SUCCESS; } -static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_set_feature(NvmeState *n, NvmeRequest *req) { NvmeNamespace *ns = NULL; NvmeNamespaceNvm *nvm; @@ -5160,7 +5159,7 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req) return NVME_SUCCESS; } -static uint16_t nvme_aer(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_aer(NvmeState *n, NvmeRequest *req) { trace_pci_nvme_aer(nvme_cid(req)); @@ -5179,7 +5178,7 @@ static uint16_t nvme_aer(NvmeCtrl *n, NvmeRequest *req) return NVME_NO_COMPLETE; } -static void nvme_update_dmrsl(NvmeCtrl *n) +static void nvme_update_dmrsl(NvmeState *n) { int nsid; @@ -5197,7 +5196,7 @@ static void nvme_update_dmrsl(NvmeCtrl *n) } } -static void nvme_select_iocs_ns(NvmeCtrl *n, NvmeNamespace *ns) +static void nvme_select_iocs_ns(NvmeState *n, NvmeNamespace *ns) { uint32_t cc = ldl_le_p(&n->bar.cc); @@ -5218,10 +5217,10 @@ static void nvme_select_iocs_ns(NvmeCtrl *n, NvmeNamespace *ns) } } -static uint16_t nvme_ns_attachment(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_ns_attachment(NvmeState *n, NvmeRequest *req) { NvmeNamespace *ns; - NvmeCtrl *ctrl; + NvmeState *ctrl; uint16_t list[NVME_CONTROLLER_LIST_SIZE] = {}; uint32_t nsid = le32_to_cpu(req->cmd.nsid); uint32_t dw10 = le32_to_cpu(req->cmd.cdw10); @@ -5413,7 +5412,7 @@ static void nvme_format_bh(void *opaque) { NvmeFormatAIOCB *iocb = opaque; NvmeRequest *req = iocb->req; - NvmeCtrl *n = nvme_ctrl(req); + NvmeState *n = nvme_state(req); uint32_t dw10 = le32_to_cpu(req->cmd.cdw10); uint8_t lbaf = dw10 & 0xf; uint8_t pi = (dw10 >> 5) & 0x7; @@ -5457,7 +5456,7 @@ done: qemu_aio_unref(iocb); } -static uint16_t nvme_format(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_format(NvmeState *n, NvmeRequest *req) { NvmeFormatAIOCB *iocb; uint32_t nsid = le32_to_cpu(req->cmd.nsid); @@ -5498,7 +5497,7 @@ out: return status; } -static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req) +static uint16_t nvme_admin_cmd(NvmeState *n, NvmeRequest *req) { trace_pci_nvme_admin_cmd(nvme_cid(req), nvme_sqid(req), req->cmd.opcode, nvme_adm_opc_str(req->cmd.opcode)); @@ -5552,7 +5551,7 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeRequest *req) static void nvme_process_sq(void *opaque) { NvmeSQueue *sq = opaque; - NvmeCtrl *n = sq->ctrl; + NvmeState *n = sq->ctrl; NvmeCQueue *cq = n->cq[sq->cqid]; uint16_t status; @@ -5586,7 +5585,7 @@ static void nvme_process_sq(void *opaque) } } -static void nvme_ctrl_reset(NvmeCtrl *n) +static void nvme_ctrl_reset(NvmeState *n) { NvmeNamespace *ns; int i; @@ -5622,7 +5621,7 @@ static void nvme_ctrl_reset(NvmeCtrl *n) n->qs_created = false; } -static void nvme_ctrl_shutdown(NvmeCtrl *n) +static void nvme_ctrl_shutdown(NvmeState *n) { NvmeNamespace *ns; int i; @@ -5641,7 +5640,7 @@ static void nvme_ctrl_shutdown(NvmeCtrl *n) } } -static void nvme_select_iocs(NvmeCtrl *n) +static void nvme_select_iocs(NvmeState *n) { NvmeNamespace *ns; int i; @@ -5656,7 +5655,7 @@ static void nvme_select_iocs(NvmeCtrl *n) } } -static int nvme_start_ctrl(NvmeCtrl *n) +static int nvme_start_ctrl(NvmeState *n) { uint64_t cap = ldq_le_p(&n->bar.cap); uint32_t cc = ldl_le_p(&n->bar.cc); @@ -5753,7 +5752,7 @@ static int nvme_start_ctrl(NvmeCtrl *n) return 0; } -static void nvme_cmb_enable_regs(NvmeCtrl *n) +static void nvme_cmb_enable_regs(NvmeState *n) { uint32_t cmbloc = ldl_le_p(&n->bar.cmbloc); uint32_t cmbsz = ldl_le_p(&n->bar.cmbsz); @@ -5773,7 +5772,7 @@ static void nvme_cmb_enable_regs(NvmeCtrl *n) stl_le_p(&n->bar.cmbsz, cmbsz); } -static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, +static void nvme_write_bar(NvmeState *n, hwaddr offset, uint64_t data, unsigned size) { uint64_t cap = ldq_le_p(&n->bar.cap); @@ -6023,7 +6022,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data, static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) { - NvmeCtrl *n = (NvmeCtrl *)opaque; + NvmeState *n = (NvmeState *)opaque; uint8_t *ptr = (uint8_t *)&n->bar; trace_pci_nvme_mmio_read(addr, size); @@ -6061,7 +6060,7 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size) return ldn_le_p(ptr + addr, size); } -static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) +static void nvme_process_db(NvmeState *n, hwaddr addr, int val) { uint32_t qid; @@ -6193,7 +6192,7 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) static void nvme_mmio_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { - NvmeCtrl *n = (NvmeCtrl *)opaque; + NvmeState *n = (NvmeState *)opaque; trace_pci_nvme_mmio_write(addr, data, size); @@ -6217,13 +6216,13 @@ static const MemoryRegionOps nvme_mmio_ops = { static void nvme_cmb_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { - NvmeCtrl *n = (NvmeCtrl *)opaque; + NvmeState *n = (NvmeState *)opaque; stn_le_p(&n->cmb.buf[addr], size, data); } static uint64_t nvme_cmb_read(void *opaque, hwaddr addr, unsigned size) { - NvmeCtrl *n = (NvmeCtrl *)opaque; + NvmeState *n = (NvmeState *)opaque; return ldn_le_p(&n->cmb.buf[addr], size); } @@ -6237,7 +6236,7 @@ static const MemoryRegionOps nvme_cmb_ops = { }, }; -static void nvme_check_constraints(NvmeCtrl *n, Error **errp) +static int nvme_check_constraints(NvmeState *n, Error **errp) { NvmeParams *params = &n->params; @@ -6248,41 +6247,35 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp) params->max_ioqpairs = params->num_queues - 1; } - if (n->namespace.blkconf.blk && n->subsys) { - error_setg(errp, "subsystem support is unavailable with legacy " - "namespace ('drive' property)"); - return; - } - if (params->max_ioqpairs < 1 || params->max_ioqpairs > NVME_MAX_IOQPAIRS) { error_setg(errp, "max_ioqpairs must be between 1 and %d", NVME_MAX_IOQPAIRS); - return; + return -1; } if (params->msix_qsize < 1 || params->msix_qsize > PCI_MSIX_FLAGS_QSIZE + 1) { error_setg(errp, "msix_qsize must be between 1 and %d", PCI_MSIX_FLAGS_QSIZE + 1); - return; + return -1; } if (!params->serial) { error_setg(errp, "serial property not set"); - return; + return -1; } if (n->pmr.dev) { if (host_memory_backend_is_mapped(n->pmr.dev)) { error_setg(errp, "can't use already busy memdev: %s", object_get_canonical_path_component(OBJECT(n->pmr.dev))); - return; + return -1; } if (!is_power_of_2(n->pmr.dev->size)) { error_setg(errp, "pmr backend size needs to be power of 2 in size"); - return; + return -1; } host_memory_backend_set_mapped(n->pmr.dev, true); @@ -6291,16 +6284,18 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp) if (n->params.zasl > n->params.mdts) { error_setg(errp, "zoned.zasl (Zone Append Size Limit) must be less " "than or equal to mdts (Maximum Data Transfer Size)"); - return; + return -1; } if (!n->params.vsl) { error_setg(errp, "vsl must be non-zero"); - return; + return -1; } + + return 0; } -static void nvme_init_state(NvmeCtrl *n) +static void nvme_init_state(NvmeState *n) { /* add one to max_ioqpairs to account for the admin queue pair */ n->reg_size = pow2ceil(sizeof(NvmeBar) + @@ -6313,7 +6308,7 @@ static void nvme_init_state(NvmeCtrl *n) n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1); } -static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev) +static void nvme_init_cmb(NvmeState *n, PCIDevice *pci_dev) { uint64_t cmb_size = n->params.cmb_size_mb * MiB; uint64_t cap = ldq_le_p(&n->bar.cap); @@ -6335,7 +6330,7 @@ static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev) } } -static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev) +static void nvme_init_pmr(NvmeState *n, PCIDevice *pci_dev) { uint32_t pmrcap = ldl_le_p(&n->bar.pmrcap); @@ -6355,7 +6350,7 @@ static void nvme_init_pmr(NvmeCtrl *n, PCIDevice *pci_dev) memory_region_set_enabled(&n->pmr.dev->mr, false); } -static int nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp) +static int nvme_init_pci(NvmeState *n, PCIDevice *pci_dev, Error **errp) { uint8_t *pci_conf = pci_dev->config; uint64_t bar_size, msix_table_size, msix_pba_size; @@ -6420,7 +6415,7 @@ static int nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp) return 0; } -static void nvme_init_subnqn(NvmeCtrl *n) +static void nvme_init_subnqn(NvmeState *n) { NvmeSubsystem *subsys = n->subsys; NvmeIdCtrl *id = &n->id_ctrl; @@ -6433,7 +6428,7 @@ static void nvme_init_subnqn(NvmeCtrl *n) } } -static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) +static void nvme_init_ctrl(NvmeState *n, PCIDevice *pci_dev) { NvmeIdCtrl *id = &n->id_ctrl; uint8_t *pci_conf = pci_dev->config; @@ -6531,7 +6526,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) n->bar.intmc = n->bar.intms = 0; } -static int nvme_init_subsys(NvmeCtrl *n, Error **errp) +static int nvme_init_subsys(NvmeState *n, Error **errp) { int cntlid; @@ -6549,7 +6544,7 @@ static int nvme_init_subsys(NvmeCtrl *n, Error **errp) return 0; } -void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns) +void nvme_attach_ns(NvmeState *n, NvmeNamespace *ns) { NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); uint32_t nsid = ns->nsid; @@ -6564,20 +6559,24 @@ void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns) static void nvme_realize(PCIDevice *pci_dev, Error **errp) { - NvmeCtrl *n = NVME(pci_dev); - Error *local_err = NULL; + NvmeCtrl *ctrl = NVME_DEVICE(pci_dev); + NvmeState *n = NVME_STATE(ctrl); if (n->subsys_dev) { n->subsys = &n->subsys_dev->subsys; } - nvme_check_constraints(n, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (ctrl->namespace.blkconf.blk && n->subsys) { + error_setg(errp, "subsystem support is unavailable with legacy " + "namespace ('drive' property)"); return; } - qbus_create_inplace(&n->bus, sizeof(NvmeBus), TYPE_NVME_BUS, + if (nvme_check_constraints(n, errp)) { + return; + } + + qbus_create_inplace(&ctrl->bus, sizeof(NvmeBus), TYPE_NVME_BUS, &pci_dev->qdev, n->parent_obj.qdev.id); nvme_init_state(n); @@ -6586,14 +6585,13 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) } if (nvme_init_subsys(n, errp)) { - error_propagate(errp, local_err); return; } nvme_init_ctrl(n, pci_dev); /* setup a namespace if the controller drive property was given */ - if (n->namespace.blkconf.blk) { - NvmeNamespaceDevice *nsdev = &n->namespace; + if (ctrl->namespace.blkconf.blk) { + NvmeNamespaceDevice *nsdev = &ctrl->namespace; NvmeNamespace *ns = &nsdev->ns; ns->nsid = 1; @@ -6605,7 +6603,7 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) static void nvme_exit(PCIDevice *pci_dev) { - NvmeCtrl *n = NVME(pci_dev); + NvmeState *n = NVME_STATE(pci_dev); NvmeNamespace *ns; int i; @@ -6637,33 +6635,37 @@ static void nvme_exit(PCIDevice *pci_dev) memory_region_del_subregion(&n->bar0, &n->iomem); } +static Property nvme_state_props[] = { + DEFINE_PROP_LINK("pmrdev", NvmeState, pmr.dev, TYPE_MEMORY_BACKEND, + HostMemoryBackend *), + DEFINE_PROP_LINK("subsys", NvmeState, subsys_dev, + TYPE_NVME_SUBSYSTEM_DEVICE, NvmeSubsystemDevice *), + DEFINE_PROP_STRING("serial", NvmeState, params.serial), + DEFINE_PROP_UINT32("cmb_size_mb", NvmeState, params.cmb_size_mb, 0), + DEFINE_PROP_UINT32("num_queues", NvmeState, params.num_queues, 0), + DEFINE_PROP_UINT32("max_ioqpairs", NvmeState, params.max_ioqpairs, 64), + DEFINE_PROP_UINT16("msix_qsize", NvmeState, params.msix_qsize, 65), + DEFINE_PROP_UINT8("aerl", NvmeState, params.aerl, 3), + DEFINE_PROP_UINT32("aer_max_queued", NvmeState, params.aer_max_queued, 64), + DEFINE_PROP_UINT8("mdts", NvmeState, params.mdts, 7), + DEFINE_PROP_UINT8("vsl", NvmeState, params.vsl, 7), + DEFINE_PROP_BOOL("use-intel-id", NvmeState, params.use_intel_id, false), + DEFINE_PROP_BOOL("legacy-cmb", NvmeState, params.legacy_cmb, false), + DEFINE_PROP_UINT8("zoned.zasl", NvmeState, params.zasl, 0), + DEFINE_PROP_BOOL("zoned.auto_transition", NvmeState, + params.auto_transition_zones, true), + DEFINE_PROP_END_OF_LIST(), +}; + static Property nvme_props[] = { DEFINE_BLOCK_PROPERTIES(NvmeCtrl, namespace.blkconf), - DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmr.dev, TYPE_MEMORY_BACKEND, - HostMemoryBackend *), - DEFINE_PROP_LINK("subsys", NvmeCtrl, subsys_dev, TYPE_NVME_SUBSYSTEM_DEVICE, - NvmeSubsystemDevice *), - DEFINE_PROP_STRING("serial", NvmeCtrl, params.serial), - DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, params.cmb_size_mb, 0), - DEFINE_PROP_UINT32("num_queues", NvmeCtrl, params.num_queues, 0), - DEFINE_PROP_UINT32("max_ioqpairs", NvmeCtrl, params.max_ioqpairs, 64), - DEFINE_PROP_UINT16("msix_qsize", NvmeCtrl, params.msix_qsize, 65), - DEFINE_PROP_UINT8("aerl", NvmeCtrl, params.aerl, 3), - DEFINE_PROP_UINT32("aer_max_queued", NvmeCtrl, params.aer_max_queued, 64), - DEFINE_PROP_UINT8("mdts", NvmeCtrl, params.mdts, 7), - DEFINE_PROP_UINT8("vsl", NvmeCtrl, params.vsl, 7), - DEFINE_PROP_BOOL("use-intel-id", NvmeCtrl, params.use_intel_id, false), - DEFINE_PROP_BOOL("legacy-cmb", NvmeCtrl, params.legacy_cmb, false), - DEFINE_PROP_UINT8("zoned.zasl", NvmeCtrl, params.zasl, 0), - DEFINE_PROP_BOOL("zoned.auto_transition", NvmeCtrl, - params.auto_transition_zones, true), DEFINE_PROP_END_OF_LIST(), }; static void nvme_get_smart_warning(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - NvmeCtrl *n = NVME(obj); + NvmeState *n = NVME_STATE(obj); uint8_t value = n->smart_critical_warning; visit_type_uint8(v, name, &value, errp); @@ -6672,7 +6674,7 @@ static void nvme_get_smart_warning(Object *obj, Visitor *v, const char *name, static void nvme_set_smart_warning(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - NvmeCtrl *n = NVME(obj); + NvmeState *n = NVME_STATE(obj); uint8_t value, old_value, cap = 0, index, event; if (!visit_type_uint8(v, name, &value, errp)) { @@ -6707,7 +6709,7 @@ static const VMStateDescription nvme_vmstate = { .unmigratable = 1, }; -static void nvme_class_init(ObjectClass *oc, void *data) +static void nvme_state_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); @@ -6719,35 +6721,54 @@ static void nvme_class_init(ObjectClass *oc, void *data) set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); dc->desc = "Non-Volatile Memory Express"; - device_class_set_props(dc, nvme_props); + device_class_set_props(dc, nvme_state_props); dc->vmsd = &nvme_vmstate; } -static void nvme_instance_init(Object *obj) +static void nvme_state_instance_init(Object *obj) { - NvmeCtrl *n = NVME(obj); - - device_add_bootindex_property(obj, &n->namespace.blkconf.bootindex, - "bootindex", "/namespace@1,0", - DEVICE(obj)); - object_property_add(obj, "smart_critical_warning", "uint8", nvme_get_smart_warning, nvme_set_smart_warning, NULL, NULL); } -static const TypeInfo nvme_info = { - .name = TYPE_NVME, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(NvmeCtrl), - .instance_init = nvme_instance_init, - .class_init = nvme_class_init, +static const TypeInfo nvme_state_info = { + .name = TYPE_NVME_STATE, + .parent = TYPE_PCI_DEVICE, + .abstract = true, + .class_init = nvme_state_class_init, + .instance_size = sizeof(NvmeState), + .instance_init = nvme_state_instance_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_PCIE_DEVICE }, - { } + { }, }, }; +static void nvme_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + device_class_set_props(dc, nvme_props); +} + +static void nvme_instance_init(Object *obj) +{ + NvmeCtrl *ctrl = NVME_DEVICE(obj); + + device_add_bootindex_property(obj, &ctrl->namespace.blkconf.bootindex, + "bootindex", "/namespace@1,0", + DEVICE(obj)); +} + +static const TypeInfo nvme_info = { + .name = TYPE_NVME_DEVICE, + .parent = TYPE_NVME_STATE, + .class_init = nvme_class_init, + .instance_size = sizeof(NvmeCtrl), + .instance_init = nvme_instance_init, + .class_init = nvme_class_init, +}; + static const TypeInfo nvme_bus_info = { .name = TYPE_NVME_BUS, .parent = TYPE_BUS, @@ -6756,6 +6777,7 @@ static const TypeInfo nvme_bus_info = { static void nvme_register_types(void) { + type_register_static(&nvme_state_info); type_register_static(&nvme_info); type_register_static(&nvme_bus_info); } diff --git a/hw/nvme/dif.c b/hw/nvme/dif.c index 1b8f9ba2fb44..8ad517232c1d 100644 --- a/hw/nvme/dif.c +++ b/hw/nvme/dif.c @@ -248,7 +248,7 @@ static void nvme_dif_rw_check_cb(void *opaque, int ret) NvmeRequest *req = ctx->req; NvmeNamespace *ns = req->ns; NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - NvmeCtrl *n = nvme_ctrl(req); + NvmeState *n = nvme_state(req); NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; uint64_t slba = le64_to_cpu(rw->slba); uint8_t prinfo = NVME_RW_PRINFO(le16_to_cpu(rw->control)); @@ -357,7 +357,7 @@ out: nvme_dif_rw_cb(ctx, ret); } -uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req) +uint16_t nvme_dif_rw(NvmeState *n, NvmeRequest *req) { NvmeRwCmd *rw = (NvmeRwCmd *)&req->cmd; NvmeNamespace *ns = req->ns; diff --git a/hw/nvme/dif.h b/hw/nvme/dif.h index 7d47299252ae..53a22bc7c78e 100644 --- a/hw/nvme/dif.h +++ b/hw/nvme/dif.h @@ -48,6 +48,6 @@ uint16_t nvme_dif_check(NvmeNamespaceNvm *nvm, uint8_t *buf, size_t len, uint8_t *mbuf, size_t mlen, uint8_t prinfo, uint64_t slba, uint16_t apptag, uint16_t appmask, uint32_t *reftag); -uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req); +uint16_t nvme_dif_rw(NvmeState *n, NvmeRequest *req); #endif /* HW_NVME_DIF_H */ diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index d67632174530..efbe9b3808e4 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -493,7 +493,7 @@ static void nvme_nsdev_realize(DeviceState *dev, Error **errp) NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev); NvmeNamespace *ns = &nsdev->ns; BusState *s = qdev_get_parent_bus(dev); - NvmeCtrl *n = NVME(s->parent); + NvmeState *n = NVME_STATE(s->parent); NvmeSubsystem *subsys = n->subsys; uint32_t nsid = nsdev->params.nsid; int i; @@ -552,7 +552,7 @@ static void nvme_nsdev_realize(DeviceState *dev, Error **errp) if (nsdev->params.shared) { for (i = 0; i < ARRAY_SIZE(subsys->ctrls); i++) { - NvmeCtrl *ctrl = subsys->ctrls[i]; + NvmeState *ctrl = subsys->ctrls[i]; if (ctrl) { nvme_attach_ns(ctrl, ns); diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index e8f4b8e3e2e0..a0c34a49772f 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -30,9 +30,14 @@ QEMU_BUILD_BUG_ON(NVME_MAX_NAMESPACES > NVME_NSID_BROADCAST - 1); -typedef struct NvmeCtrl NvmeCtrl; typedef struct NvmeNamespace NvmeNamespace; +#define TYPE_NVME_STATE "nvme-state" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeState, NVME_STATE) + +#define TYPE_NVME_DEVICE "nvme" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeCtrl, NVME_DEVICE) + #define TYPE_NVME_BUS "nvme-bus" OBJECT_DECLARE_SIMPLE_TYPE(NvmeBus, NVME_BUS) @@ -43,7 +48,7 @@ typedef struct NvmeBus { typedef struct NvmeSubsystem { uint8_t subnqn[256]; - NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS]; + NvmeState *ctrls[NVME_MAX_CONTROLLERS]; NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; } NvmeSubsystem; @@ -61,12 +66,12 @@ typedef struct NvmeSubsystemDevice { } params; } NvmeSubsystemDevice; -int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n, +int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeState *n, Error **errp); -void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n); +void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeState *n); -static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys, - uint32_t cntlid) +static inline NvmeState *nvme_subsys_ctrl(NvmeSubsystem *subsys, + uint32_t cntlid) { if (!subsys || cntlid >= NVME_MAX_CONTROLLERS) { return NULL; @@ -342,7 +347,7 @@ static inline const char *nvme_io_opc_str(uint8_t opc) } typedef struct NvmeSQueue { - struct NvmeCtrl *ctrl; + NvmeState *ctrl; uint16_t sqid; uint16_t cqid; uint32_t head; @@ -357,7 +362,7 @@ typedef struct NvmeSQueue { } NvmeSQueue; typedef struct NvmeCQueue { - struct NvmeCtrl *ctrl; + NvmeState *ctrl; uint8_t phase; uint16_t cqid; uint16_t irq_enabled; @@ -371,10 +376,6 @@ typedef struct NvmeCQueue { QTAILQ_HEAD(, NvmeRequest) req_list; } NvmeCQueue; -#define TYPE_NVME "nvme" -#define NVME(obj) \ - OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) - typedef struct NvmeParams { char *serial; uint32_t num_queues; /* deprecated since 5.1 */ @@ -391,13 +392,12 @@ typedef struct NvmeParams { bool legacy_cmb; } NvmeParams; -typedef struct NvmeCtrl { +typedef struct NvmeState { PCIDevice parent_obj; MemoryRegion bar0; MemoryRegion iomem; NvmeBar bar; NvmeParams params; - NvmeBus bus; uint16_t cntlid; bool qs_created; @@ -444,7 +444,6 @@ typedef struct NvmeCtrl { NvmeSubsystem *subsys; NvmeSubsystemDevice *subsys_dev; - NvmeNamespaceDevice namespace; NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; NvmeSQueue **sq; NvmeCQueue **cq; @@ -459,9 +458,18 @@ typedef struct NvmeCtrl { }; uint32_t async_config; } features; +} NvmeState; + +typedef struct NvmeCtrl { + NvmeState parent_obj; + + NvmeBus bus; + + /* for use with legacy single namespace (-device nvme,drive=...) setups */ + NvmeNamespaceDevice namespace; } NvmeCtrl; -static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) +static inline NvmeNamespace *nvme_ns(NvmeState *n, uint32_t nsid) { if (!nsid || nsid > NVME_MAX_NAMESPACES) { return NULL; @@ -473,12 +481,12 @@ static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid) static inline NvmeCQueue *nvme_cq(NvmeRequest *req) { NvmeSQueue *sq = req->sq; - NvmeCtrl *n = sq->ctrl; + NvmeState *n = sq->ctrl; return n->cq[sq->cqid]; } -static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req) +static inline NvmeState *nvme_state(NvmeRequest *req) { NvmeSQueue *sq = req->sq; return sq->ctrl; @@ -493,13 +501,13 @@ static inline uint16_t nvme_cid(NvmeRequest *req) return le16_to_cpu(req->cqe.cid); } -void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns); -uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len, +void nvme_attach_ns(NvmeState *n, NvmeNamespace *ns); +uint16_t nvme_bounce_data(NvmeState *n, uint8_t *ptr, uint32_t len, NvmeTxDirection dir, NvmeRequest *req); -uint16_t nvme_bounce_mdata(NvmeCtrl *n, uint8_t *ptr, uint32_t len, +uint16_t nvme_bounce_mdata(NvmeState *n, uint8_t *ptr, uint32_t len, NvmeTxDirection dir, NvmeRequest *req); void nvme_rw_complete_cb(void *opaque, int ret); -uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len, +uint16_t nvme_map_dptr(NvmeState *n, NvmeSg *sg, size_t len, NvmeCmd *cmd); #endif /* HW_NVME_INTERNAL_H */ diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 4d73d14070dc..3e1736d846b7 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -11,7 +11,7 @@ #include "nvme.h" -int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n, Error **errp) +int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeState *n, Error **errp) { int cntlid, nsid; @@ -38,7 +38,7 @@ int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n, Error **errp) return cntlid; } -void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n) +void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeState *n) { subsys->ctrls[n->cntlid] = NULL; n->cntlid = -1; From patchwork Mon Sep 27 05:17:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533208 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=YzpALq4G; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=vb49OF4i; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHsCM0z4hz9tD5 for ; Mon, 27 Sep 2021 15:49:19 +1000 (AEST) Received: from localhost ([::1]:41634 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjVs-00014h-OP for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:49:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34252) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2U-0003fU-LY; Mon, 27 Sep 2021 01:18:54 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:47465) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2S-0000Os-7K; Mon, 27 Sep 2021 01:18:54 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.west.internal (Postfix) with ESMTP id B89682B01215; Mon, 27 Sep 2021 01:18:49 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 27 Sep 2021 01:18:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=v+TeP58r9HCCS zTGXmrxPSlB17ufLDToEjdmHrP2U0E=; b=YzpALq4GcKPAVc1ndvmaw4Yr2IO9H 5Ay4oVzG4t4iSA4lnHJ210piZCIGOGr8SsHaBuXAlyl7V/wtfzpcIj4R9n9QouCy AYTCTQlPwsZjuWu15OSHCPHHkoSxGkTU3fl4IIv2ZNBgL8VnLlBxKZFEqUUsYONM pr3m9osrGsmixahoY50B3RHny9HRiNKAWJjU4RLJharjtkfRdtf3/Bv7LPyzrxZC LWtNq2O5jfgVz3PDytzaexaRT5u0rxx2LZuPba5JReXzc76Ra6nPR7cmXtWUwaaY AK0mzzccHOOIEDM7HFm0nsxWUv19X7iIYKGjztM/+31Cp0aIh7tmg/JAw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=v+TeP58r9HCCSzTGXmrxPSlB17ufLDToEjdmHrP2U0E=; b=vb49OF4i OfIoDQmw+Bl8mNE9IgVfRBo68huEsAFBBqc3xCyjmnISe7YjC6r+PmIFVOmPvbc/ Lfg8VxaKb7DgHad+/nrimqEOYBuF4sLXq3W9pvf7viQzWur0bEQFaFCLTD1C2VBq 0Wzo+d62NwJLXNRkCM1lPNaVzEIGIrhXiQXayPzbVhHwn+AT0jMydXnA7mgxCnTj q2Q2Eetch/V8cNQjv9+xmNuuY1qD8ozL7M+gJjLSYZ4/M79dW1wBRLK08FoZevVQ RIDJDGKAVtZbg1VbQlcyAEwupAXcoYiThhsP8DRulTSGJfBI78Rh943tGiHp1+pC 9BxDsBD5JjurEg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgleefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeivdekgeethfevfeelhfejudehieefjeelffevieduueffueffveeihfejudet vdenucffohhmrghinhepvddtudegqddtkedrohhrghenucevlhhushhtvghrufhiiigvpe dtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehithhssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:47 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 11/16] hw/nvme: add experimental object x-nvme-subsystem Date: Mon, 27 Sep 2021 07:17:54 +0200 Message-Id: <20210927051759.447305-12-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add a basic user creatable object that models an NVMe NVM subsystem. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 14 ++--- hw/nvme/ns.c | 5 +- hw/nvme/nvme.h | 10 +++- hw/nvme/subsys.c | 144 +++++++++++++++++++++++++++++++++++++++++++++-- qapi/qom.json | 17 ++++++ 5 files changed, 175 insertions(+), 15 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index b27bf00f623f..c798aeb095e1 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -6562,14 +6562,14 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) NvmeCtrl *ctrl = NVME_DEVICE(pci_dev); NvmeState *n = NVME_STATE(ctrl); - if (n->subsys_dev) { - n->subsys = &n->subsys_dev->subsys; - } + if (ctrl->subsys_dev) { + if (ctrl->namespace.blkconf.blk) { + error_setg(errp, "subsystem support is unavailable with legacy " + "namespace ('drive' property)"); + return; + } - if (ctrl->namespace.blkconf.blk && n->subsys) { - error_setg(errp, "subsystem support is unavailable with legacy " - "namespace ('drive' property)"); - return; + n->subsys = &ctrl->subsys_dev->subsys; } if (nvme_check_constraints(n, errp)) { diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index efbe9b3808e4..09556f0ec7c9 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -493,7 +493,8 @@ static void nvme_nsdev_realize(DeviceState *dev, Error **errp) NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev); NvmeNamespace *ns = &nsdev->ns; BusState *s = qdev_get_parent_bus(dev); - NvmeState *n = NVME_STATE(s->parent); + NvmeCtrl *ctrl = NVME_DEVICE(s->parent); + NvmeState *n = NVME_STATE(ctrl); NvmeSubsystem *subsys = n->subsys; uint32_t nsid = nsdev->params.nsid; int i; @@ -509,7 +510,7 @@ static void nvme_nsdev_realize(DeviceState *dev, Error **errp) * If this namespace belongs to a subsystem (through a link on the * controller device), reparent the device. */ - if (!qdev_set_parent_bus(dev, &n->subsys_dev->bus.parent_bus, errp)) { + if (!qdev_set_parent_bus(dev, &ctrl->subsys_dev->bus.parent_bus, errp)) { return; } } diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index a0c34a49772f..b67e5900a01d 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -45,8 +45,14 @@ typedef struct NvmeBus { BusState parent_bus; } NvmeBus; +#define TYPE_NVME_SUBSYSTEM "x-nvme-subsystem" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeSubsystem, NVME_SUBSYSTEM) + typedef struct NvmeSubsystem { - uint8_t subnqn[256]; + Object parent_obj; + + QemuUUID uuid; + uint8_t subnqn[256]; NvmeState *ctrls[NVME_MAX_CONTROLLERS]; NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1]; @@ -467,6 +473,8 @@ typedef struct NvmeCtrl { /* for use with legacy single namespace (-device nvme,drive=...) setups */ NvmeNamespaceDevice namespace; + + NvmeSubsystemDevice *subsys_dev; } NvmeCtrl; static inline NvmeNamespace *nvme_ns(NvmeState *n, uint32_t nsid) diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 3e1736d846b7..2599b83c348e 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -8,10 +8,13 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/qapi-builtin-visit.h" +#include "qom/object_interfaces.h" #include "nvme.h" -int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeState *n, Error **errp) +int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeState *n, + Error **errp) { int cntlid, nsid; @@ -44,6 +47,136 @@ void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeState *n) n->cntlid = -1; } +static void get_controllers(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeSubsystem *subsys = NVME_SUBSYSTEM(obj); + strList *paths = NULL; + strList **tail = &paths; + unsigned cntlid; + + for (cntlid = 0; cntlid < NVME_MAX_CONTROLLERS; cntlid++) { + NvmeState *n = subsys->ctrls[cntlid]; + if (!n) { + continue; + } + + QAPI_LIST_APPEND(tail, object_get_canonical_path(OBJECT(n))); + } + + visit_type_strList(v, name, &paths, errp); + qapi_free_strList(paths); +} + +static void get_namespaces(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeSubsystem *subsys = NVME_SUBSYSTEM(obj); + strList *paths = NULL; + strList **tail = &paths; + unsigned nsid; + + for (nsid = 1; nsid <= NVME_MAX_NAMESPACES; nsid++) { + NvmeNamespace *ns = subsys->namespaces[nsid]; + if (!ns) { + continue; + } + + QAPI_LIST_APPEND(tail, object_get_canonical_path(OBJECT(ns))); + } + + visit_type_strList(v, name, &paths, errp); + qapi_free_strList(paths); +} + +static char *get_subnqn(Object *obj, Error **errp) +{ + NvmeSubsystem *subsys = NVME_SUBSYSTEM(obj); + return g_strdup((char *)subsys->subnqn); +} + +static void set_subnqn(Object *obj, const char *str, Error **errp) +{ + NvmeSubsystem *subsys = NVME_SUBSYSTEM(obj); + snprintf((char *)subsys->subnqn, sizeof(subsys->subnqn), "%s", str); +} + +static char *get_uuid(Object *obj, Error **errp) +{ + NvmeSubsystem *subsys = NVME_SUBSYSTEM(obj); + char buf[UUID_FMT_LEN + 1]; + + qemu_uuid_unparse(&subsys->uuid, buf); + + return g_strdup(buf); +} + +static void set_uuid(Object *obj, const char *str, Error **errp) +{ + NvmeSubsystem *subsys = NVME_SUBSYSTEM(obj); + + if (!strcmp(str, "auto")) { + qemu_uuid_generate(&subsys->uuid); + } else if (qemu_uuid_parse(str, &subsys->uuid) < 0) { + error_setg(errp, "invalid uuid"); + return; + } +} + +static void nvme_subsys_complete(UserCreatable *uc, Error **errp) +{ + NvmeSubsystem *subsys = NVME_SUBSYSTEM(uc); + + if (!strcmp((char *)subsys->subnqn, "")) { + char buf[UUID_FMT_LEN + 1]; + + qemu_uuid_unparse(&subsys->uuid, buf); + + snprintf((char *)subsys->subnqn, sizeof(subsys->subnqn), + "nqn.2014-08.org.nvmexpress:uuid:%s", buf); + } +} + +static void nvme_subsys_instance_init(Object *obj) +{ + object_property_add(obj, "controllers", "str", get_controllers, NULL, NULL, + NULL); + + object_property_add(obj, "namespaces", "str", get_namespaces, NULL, NULL, + NULL); +} + +static void nvme_subsys_class_init(ObjectClass *oc, void *data) +{ + ObjectProperty *op; + + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + ucc->complete = nvme_subsys_complete; + + object_class_property_add_str(oc, "subnqn", get_subnqn, set_subnqn); + object_class_property_set_description(oc, "subnqn", "the NVM Subsystem " + "NVMe Qualified Name; " + "(default: \"nqn.2014-08.org.nvmexpress:uuid:\")"); + + op = object_class_property_add_str(oc, "uuid", get_uuid, set_uuid); + object_property_set_default_str(op, "auto"); + object_class_property_set_description(oc, "subnqn", "NVM Subsystem UUID " + "(\"auto\" for random value; " + "default: \"auto\")"); +} + +static const TypeInfo nvme_subsys_info = { + .name = TYPE_NVME_SUBSYSTEM, + .parent = TYPE_OBJECT, + .class_init = nvme_subsys_class_init, + .instance_init = nvme_subsys_instance_init, + .instance_size = sizeof(NvmeSubsystem), + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { }, + } +}; + static void nvme_subsys_device_setup(NvmeSubsystemDevice *dev) { NvmeSubsystem *subsys = &dev->subsys; @@ -64,7 +197,7 @@ static void nvme_subsys_device_realize(DeviceState *dev, Error **errp) nvme_subsys_device_setup(subsys); } -static Property nvme_subsystem_device_props[] = { +static Property nvme_subsys_device_props[] = { DEFINE_PROP_STRING("nqn", NvmeSubsystemDevice, params.nqn), DEFINE_PROP_END_OF_LIST(), }; @@ -79,7 +212,7 @@ static void nvme_subsys_device_class_init(ObjectClass *oc, void *data) dc->desc = "Virtual NVMe subsystem"; dc->hotpluggable = false; - device_class_set_props(dc, nvme_subsystem_device_props); + device_class_set_props(dc, nvme_subsys_device_props); } static const TypeInfo nvme_subsys_device_info = { @@ -89,9 +222,10 @@ static const TypeInfo nvme_subsys_device_info = { .instance_size = sizeof(NvmeSubsystemDevice), }; -static void nvme_subsys_register_types(void) +static void register_types(void) { + type_register_static(&nvme_subsys_info); type_register_static(&nvme_subsys_device_info); } -type_init(nvme_subsys_register_types) +type_init(register_types) diff --git a/qapi/qom.json b/qapi/qom.json index a25616bc7a7d..d4c211fc38b1 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -647,6 +647,21 @@ '*hugetlbsize': 'size', '*seal': 'bool' } } +## +# @NvmeSubsystemProperties: +# +# Properties for nvme-subsys objects. +# +# @subnqn: the NVM Subsystem NVMe Qualified Name +# +# @uuid: the UUID of the subsystem. Used as default in subnqn. +# +# Since: 6.1 +## +{ 'struct': 'NvmeSubsystemProperties', + 'data': { '*subnqn': 'str', + '*uuid': 'str' } } + ## # @PrManagerHelperProperties: # @@ -797,6 +812,7 @@ { 'name': 'memory-backend-memfd', 'if': 'CONFIG_LINUX' }, 'memory-backend-ram', + 'x-nvme-subsystem', 'pef-guest', 'pr-manager-helper', 'qtest', @@ -855,6 +871,7 @@ 'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties', 'if': 'CONFIG_LINUX' }, 'memory-backend-ram': 'MemoryBackendProperties', + 'x-nvme-subsystem': 'NvmeSubsystemProperties', 'pr-manager-helper': 'PrManagerHelperProperties', 'qtest': 'QtestProperties', 'rng-builtin': 'RngProperties', From patchwork Mon Sep 27 05:17:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533195 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=ZaqDo+fi; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=dCLbfQ7B; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHryD2mRDz9t5m for ; Mon, 27 Sep 2021 15:37:56 +1000 (AEST) Received: from localhost ([::1]:59146 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjKr-0001qL-Lj for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:37:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34286) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2Y-0003nL-Li; Mon, 27 Sep 2021 01:18:58 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:58103) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2X-0000Rq-6E; Mon, 27 Sep 2021 01:18:58 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.west.internal (Postfix) with ESMTP id AC32A2B01216; Mon, 27 Sep 2021 01:18:53 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Mon, 27 Sep 2021 01:18:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=38nnrBM97XPIY VmHe5MfH0sS2KBUeMhYG5oVjJyrNKc=; b=ZaqDo+fislbzLHpRaZuubEQxX4744 lHwTVS2LND+Vu6q31g8mQuLXAdbzDd91lc1xITWvhGW0w06PNJMu4VKYQACHWHgG +YiACGr3RxZ5yD+f4q9UYA7IavVpBUdQaKyxNBGJu+TGPREZF8i3+dF8NxP9Gdsi 9PBUgiNdgZidAQ6kaIe0rUMx5nPBa2SCVB67SQx7MEEkioPBYMbc8a/CL9wwzCHB 6Qd7BC6yw9alxAroDQzdC0ZsYoNR0ZbJH/Q7VwmbNiHxOiBE8HSQLx/AeOtf7xjm Oe1n1wdcTPe0KpVGPb4Jdr0fu517FdiW69B44NS1VwHRnjCUdohtfn1Sw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=38nnrBM97XPIYVmHe5MfH0sS2KBUeMhYG5oVjJyrNKc=; b=dCLbfQ7B halFzTcuQLcV2h+VVjf0sxAp2nZ9Fnz0MypmDpk7ll1Nczwc+CeZ2rsk7XMbnQNq h0sW01k0gOLlIwbP7wvu/XNdCM/VnDJubSGbv5HDE6kZUNn75dgrWpfSVhpzjo5m CoXq1ePJjNMpKNAkFFTA5zRA8KkMdGybZ1Z9qq8FqD1WIaXHiEwBrFLoFrVd5CDn 0SCf1zyns7VCtRi4n0Of9YONWn7IAR/N+MVjtLLexrEbzlL4wd+0l4Efr/lKaA+Q IcA5jFCW+iPMqLNmt7oDXREu9E5ME70UkdYncX0I8VTjl6xWYPSQgObdROQIaTwq HWaGH8eTwV8Wng== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgleefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:51 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 12/16] nvme: add structured type for nguid Date: Mon, 27 Sep 2021 07:17:55 +0200 Message-Id: <20210927051759.447305-13-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add a structured type for NGUID. Signed-off-by: Klaus Jensen --- include/block/nvme.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/block/nvme.h b/include/block/nvme.h index 2bcabe561589..f41464ee19bd 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -1269,6 +1269,11 @@ typedef struct QEMU_PACKED NvmeLBAFE { #define NVME_NSID_BROADCAST 0xffffffff +typedef struct QEMU_PACKED NvmeNGUID { + uint8_t vspexid[8]; + uint64_t eui; +} NvmeNGUID; + typedef struct QEMU_PACKED NvmeIdNs { uint64_t nsze; uint64_t ncap; @@ -1300,7 +1305,7 @@ typedef struct QEMU_PACKED NvmeIdNs { uint32_t mcl; uint8_t msrc; uint8_t rsvd81[23]; - uint8_t nguid[16]; + NvmeNGUID nguid; uint64_t eui64; NvmeLBAF lbaf[16]; uint8_t rsvd192[192]; From patchwork Mon Sep 27 05:17:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533207 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=Y+G2c0/L; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=bTcrHwWZ; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHsBn6Lbmz9tD5 for ; Mon, 27 Sep 2021 15:48:49 +1000 (AEST) Received: from localhost ([::1]:40516 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjVP-0000DU-GO for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:48:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34318) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2c-0003vZ-Dr; Mon, 27 Sep 2021 01:19:02 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:48079) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2a-0000VF-5D; Mon, 27 Sep 2021 01:19:02 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.west.internal (Postfix) with ESMTP id A0B0C2B0121A; Mon, 27 Sep 2021 01:18:57 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 27 Sep 2021 01:18:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=9wR8Vc7/ABEF8 +JyTofZsGpn9fTcOeeRigMV4VuKm/I=; b=Y+G2c0/L8+ITiV1GWh/E3XhdwgZRA 9rD22hSiLz3aD2RSCSd36wQOmUSrZ5yao+AU6fEVKWAM62bbdcw5ypbyA2sZflMP TqFBu+ka/FudA+Bb841bN18evJg3twoBKIpowMwQ0t8kYvbboa8vfRM/q4xL2XNw D6XQv6Ng7sbv6kD39xK151Cy34Y+omwAh7d7+R7UzqhBvUUMBv1ZLZGGsTdbxAXf ZLiWOXC77WFmgvcoyhB3Bl9XE1Rd4/w5Jhs+a0W48SGf7O/jOdEYE7mJ6ToDpKuJ LUxCH+4k7Jdih4bI5lHsaDrlyYAQtcCsBkhLP3WH111JU+/ANE4tx6Ppg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=9wR8Vc7/ABEF8+JyTofZsGpn9fTcOeeRigMV4VuKm/I=; b=bTcrHwWZ z7INfvosRiwEzOrFA6PT+Aa7d/+tC98ij9wNhOFpW2a+phqUp3R02dF4lFV1gcIq kKa5UubUTryy+NPX5kfkCV8gDakoQ5jHhrK72WjXuvePGIWXOAK4ezuA6c2abRva VNNY9ekyqDbmrBt2YRCNl4nZZ5R3AbgRHKtHkwQPePLWvZM8Xj5HvtzvWcIAQJMM QUyGiC7lrJVC6PMBsxUGuyC9mZWolJFweUSOxmD44LYM1PBh9Onkp0bFUmaftILZ EZPfBYmRhUPl7lknVhL8N9V2/sJ0riXTi6mOAZzBkUSQHeWS4EYhiwiLemPQNEuB 6f2Ntn/yJvtuuw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgleefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:55 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 13/16] hw/nvme: add experimental abstract object x-nvme-ns Date: Mon, 27 Sep 2021 07:17:56 +0200 Message-Id: <20210927051759.447305-14-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add the abstract NvmeNamespace object to base proper namespace types on. Signed-off-by: Klaus Jensen --- hw/nvme/ns.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++ hw/nvme/nvme.h | 22 +++++ hw/nvme/subsys.c | 31 +++++++ qapi/qom.json | 17 ++++ 4 files changed, 286 insertions(+) diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 09556f0ec7c9..d75ff4f1cb74 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -13,9 +13,13 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qemu/ctype.h" #include "qemu/units.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include "qapi/qapi-builtin-visit.h" +#include "qom/object_interfaces.h" #include "sysemu/sysemu.h" #include "sysemu/block-backend.h" @@ -632,8 +636,220 @@ static const TypeInfo nvme_nsdev_info = { .instance_init = nvme_nsdev_instance_init, }; +bool nvme_ns_prop_writable(Object *obj, const char *name, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(obj); + + if (ns->realized) { + error_setg(errp, "attempt to set immutable property '%s' on " + "active namespace", name); + return false; + } + + return true; +} + +static char *nvme_ns_get_nsid(Object *obj, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(obj); + + return g_strdup_printf("%d\n", ns->nsid); +} + +static void nvme_ns_set_nsid(Object *obj, const char *v, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(obj); + unsigned long nsid; + + if (!nvme_ns_prop_writable(obj, "nsid", errp)) { + return; + } + + if (!strcmp(v, "auto")) { + ns->nsid = 0; + return; + } + + if (qemu_strtoul(v, NULL, 0, &nsid) < 0 || nsid > NVME_MAX_NAMESPACES) { + error_setg(errp, "invalid namespace identifier"); + return; + } + + ns->nsid = nsid; +} + +static char *nvme_ns_get_uuid(Object *obj, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(obj); + + char *str = g_malloc(UUID_FMT_LEN + 1); + + qemu_uuid_unparse(&ns->uuid, str); + + return str; +} + +static void nvme_ns_set_uuid(Object *obj, const char *v, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(obj); + + if (!nvme_ns_prop_writable(obj, "uuid", errp)) { + return; + } + + if (!strcmp(v, "auto")) { + qemu_uuid_generate(&ns->uuid); + } else if (qemu_uuid_parse(v, &ns->uuid) < 0) { + error_setg(errp, "invalid uuid"); + } +} + +static char *nvme_ns_get_eui64(Object *obj, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(obj); + + const int len = 2 * 8 + 7 + 1; /* "aa:bb:cc:dd:ee:ff:gg:hh\0" */ + char *str = g_malloc(len); + + snprintf(str, len, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + ns->eui64.a[0], ns->eui64.a[1], ns->eui64.a[2], ns->eui64.a[3], + ns->eui64.a[4], ns->eui64.a[5], ns->eui64.a[6], ns->eui64.a[7]); + + return str; +} + +static void nvme_ns_set_eui64(Object *obj, const char *v, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(obj); + + int i, pos; + + if (!nvme_ns_prop_writable(obj, "eui64", errp)) { + return; + } + + if (!strcmp(v, "auto")) { + ns->eui64.a[0] = 0x52; + ns->eui64.a[1] = 0x54; + ns->eui64.a[2] = 0x00; + + for (i = 0; i < 5; ++i) { + ns->eui64.a[3 + i] = g_random_int(); + } + + return; + } + + for (i = 0, pos = 0; i < 8; i++, pos += 3) { + long octet; + + if (!(qemu_isxdigit(v[pos]) && qemu_isxdigit(v[pos + 1]))) { + goto invalid; + } + + if (i == 7) { + if (v[pos + 2] != '\0') { + goto invalid; + } + } else { + if (!(v[pos + 2] == ':' || v[pos + 2] == '-')) { + goto invalid; + } + } + + if (qemu_strtol(v + pos, NULL, 16, &octet) < 0 || octet > 0xff) { + goto invalid; + } + + ns->eui64.a[i] = octet; + } + + return; + +invalid: + error_setg(errp, "invalid ieee extended unique identifier"); +} + +static void nvme_ns_set_identifiers_if_unset(NvmeNamespace *ns) +{ + ns->nguid.eui = ns->eui64.v; +} + +static void nvme_ns_complete(UserCreatable *uc, Error **errp) +{ + NvmeNamespace *ns = NVME_NAMESPACE(uc); + NvmeNamespaceClass *nc = NVME_NAMESPACE_GET_CLASS(ns); + + nvme_ns_set_identifiers_if_unset(ns); + + ns->flags |= NVME_NS_SHARED; + + if (nc->check_params && nc->check_params(ns, errp)) { + return; + } + + if (nvme_subsys_register_ns(ns->subsys, ns, errp)) { + return; + } + + if (nc->configure && nc->configure(ns, errp)) { + return; + } + + ns->realized = true; +} + +static void nvme_ns_class_init(ObjectClass *oc, void *data) +{ + ObjectProperty *op; + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + + ucc->complete = nvme_ns_complete; + + op = object_class_property_add_str(oc, "nsid", nvme_ns_get_nsid, + nvme_ns_set_nsid); + object_property_set_default_str(op, "auto"); + object_class_property_set_description(oc, "nsid", "namespace identifier " + "(\"auto\": assigned by controller " + "or subsystem; default: \"auto\")"); + + object_class_property_add_link(oc, "subsys", TYPE_NVME_SUBSYSTEM, + offsetof(NvmeNamespace, subsys), + object_property_allow_set_link, 0); + object_class_property_set_description(oc, "subsys", "link to " + "x-nvme-subsystem object"); + + op = object_class_property_add_str(oc, "uuid", nvme_ns_get_uuid, + nvme_ns_set_uuid); + object_property_set_default_str(op, "auto"); + object_class_property_set_description(oc, "uuid", "namespace uuid " + "(\"auto\" for random value; " + "default: \"auto\")"); + + op = object_class_property_add_str(oc, "eui64", nvme_ns_get_eui64, + nvme_ns_set_eui64); + object_property_set_default_str(op, "auto"); + object_class_property_set_description(oc, "eui64", "IEEE Extended Unique " + "Identifier (\"auto\" for random " + "value; default: \"auto\")"); +} + +static const TypeInfo nvme_ns_info = { + .name = TYPE_NVME_NAMESPACE, + .parent = TYPE_OBJECT, + .abstract = true, + .class_size = sizeof(NvmeNamespaceClass), + .class_init = nvme_ns_class_init, + .instance_size = sizeof(NvmeNamespace), + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { }, + }, +}; + static void register_types(void) { + type_register_static(&nvme_ns_info); type_register_static(&nvme_nsdev_info); } diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index b67e5900a01d..627b28649892 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -19,6 +19,8 @@ #define HW_NVME_INTERNAL_H #include "qemu/uuid.h" +#include "qemu/notify.h" +#include "qapi/qapi-builtin-visit.h" #include "hw/pci/pci.h" #include "hw/block/block.h" @@ -45,6 +47,16 @@ typedef struct NvmeBus { BusState parent_bus; } NvmeBus; +#define TYPE_NVME_NAMESPACE "x-nvme-ns" +OBJECT_DECLARE_TYPE(NvmeNamespace, NvmeNamespaceClass, NVME_NAMESPACE) + +struct NvmeNamespaceClass { + ObjectClass parent_class; + + int (*check_params)(NvmeNamespace *ns, Error **errp); + int (*configure)(NvmeNamespace *ns, Error **errp); +}; + #define TYPE_NVME_SUBSYSTEM "x-nvme-subsystem" OBJECT_DECLARE_SIMPLE_TYPE(NvmeSubsystem, NVME_SUBSYSTEM) @@ -75,6 +87,8 @@ typedef struct NvmeSubsystemDevice { int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeState *n, Error **errp); void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeState *n); +int nvme_subsys_register_ns(NvmeSubsystem *subsys, NvmeNamespace *ns, + Error **errp); static inline NvmeState *nvme_subsys_ctrl(NvmeSubsystem *subsys, uint32_t cntlid) @@ -190,6 +204,11 @@ enum NvmeNamespaceFlags { }; typedef struct NvmeNamespace { + Object parent_obj; + bool realized; + + NvmeSubsystem *subsys; + uint32_t nsid; uint8_t csi; QemuUUID uuid; @@ -197,6 +216,7 @@ typedef struct NvmeNamespace { uint64_t v; uint8_t a[8]; } eui64; + NvmeNGUID nguid; unsigned long flags; @@ -212,6 +232,8 @@ typedef struct NvmeNamespace { NvmeNamespaceZoned zoned; } NvmeNamespace; +bool nvme_ns_prop_writable(Object *obj, const char *name, Error **errp); + #define NVME_NAMESPACE_NVM(ns) (&(ns)->nvm) #define NVME_NAMESPACE_ZONED(ns) (&(ns)->zoned) diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index 2599b83c348e..e4dcd8fd20a5 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -47,6 +47,37 @@ void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeState *n) n->cntlid = -1; } +int nvme_subsys_register_ns(NvmeSubsystem *subsys, NvmeNamespace *ns, + Error **errp) +{ + int i; + + if (!ns->nsid) { + for (i = 1; i <= NVME_MAX_NAMESPACES; i++) { + if (!subsys->namespaces[i]) { + ns->nsid = i; + break; + } + } + + if (!ns->nsid) { + error_setg(errp, "no free namespace identifiers"); + return -1; + } + } else if (ns->nsid > NVME_MAX_NAMESPACES) { + error_setg(errp, "invalid namespace identifier '%d'", ns->nsid); + return -1; + } else if (subsys->namespaces[ns->nsid]) { + error_setg(errp, "namespace identifier '%d' already allocated", + ns->nsid); + return -1; + } + + subsys->namespaces[ns->nsid] = ns; + + return 0; +} + static void get_controllers(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { diff --git a/qapi/qom.json b/qapi/qom.json index d4c211fc38b1..6d5cef6b92ad 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -662,6 +662,23 @@ 'data': { '*subnqn': 'str', '*uuid': 'str' } } +## +# @NvmeNamespaceProperties: +# +# Properties for x-nvme-ns objects. +# +# @subsys: nvme controller to attach to +# +# @nsid: namespace identifier to assign +# +# Since: 6.1 +## +{ 'struct': 'NvmeNamespaceProperties', + 'data': { 'subsys': 'str', + '*nsid': 'str', + '*eui64': 'str', + '*uuid': 'str' } } + ## # @PrManagerHelperProperties: # From patchwork Mon Sep 27 05:17:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533211 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=L8YAFgAl; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=b8rp1lkB; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHsMz0ljBz9tkJ for ; Mon, 27 Sep 2021 15:56:45 +1000 (AEST) Received: from localhost ([::1]:49274 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjd3-0006JZ-Ha for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:56:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34366) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2i-0004AG-Vg; Mon, 27 Sep 2021 01:19:09 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:38493) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2e-0000ZB-AQ; Mon, 27 Sep 2021 01:19:08 -0400 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailnew.west.internal (Postfix) with ESMTP id C5C072B0121B; Mon, 27 Sep 2021 01:19:01 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute6.internal (MEProxy); Mon, 27 Sep 2021 01:19:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=E2wI6UDEUTIrj fcYDRKK0bcc4PiZ2X2D73AghsUvN7w=; b=L8YAFgAl19LJqZaER6tk8/eN5eT85 7xluDTUACfP5H45RP2gKIJBrVu3wXN0wU8fA2mHgLOLJAYzR8/aSTh0Ia8I8X+B3 RlSEjq5H2NH0e6fI9WLMgAOe5loK9BnoQL3d4h37aaea3iieQI4X0k79ZBT0zkZZ wT43wjFm/UcrpW8ANcBSlMd8XigEJaZt0JgFX/DZcDPp34qvx8YsXmHhxDAaHcNh btsZHwvTB844iUYQn11cualYM8wQHaDpxcjk6yisJWvecE186pg2BkZhoMHrEJIw m7DLpQPa5mK4atuZ9FBv55axRRVtWk4UWP3gzcbK22U6qN5jiuR49t4xQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=E2wI6UDEUTIrjfcYDRKK0bcc4PiZ2X2D73AghsUvN7w=; b=b8rp1lkB IlIq5CoKkeOYPtIZq9V0Pn5NYiArDwFBZCED3dkCs9zvWZeKyFGTEVoV1HrRup5q AygB1NaefMODu5TpHnyU0w4G7yHsykAoUtciIEc1tc8/sGz30pNAb0uPOD+QrmnA 1OywHtwbbp0K11zLwedhTkIprerDryNZA6v1vOe710kcxAbtuLT7e6o4KpAeNucf 6T+EVOaeLQY2tIYy+yLrG8kGSW3yIKaJP9wTPJGDmXeKJvB4LNHM+mQxraSp0xzF ic4CnflSTBUyZSQU5SEcZMCQTjdETpwU4GET19DeKWTYabgTMukj+ORI9KGE8gfh PJnRd5Fvt3K/ZQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgledvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpeefnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:18:59 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 14/16] hw/nvme: add experimental objects x-nvme-ns-{nvm, zoned} Date: Mon, 27 Sep 2021 07:17:57 +0200 Message-Id: <20210927051759.447305-15-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add implementations of namespaces that supports the NVM and Zoned Command Sets. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 11 +- hw/nvme/dif.h | 2 + hw/nvme/meson.build | 2 +- hw/nvme/ns-nvm.c | 354 +++++++++++++++++++++++++++++++++++ hw/nvme/ns-zoned.c | 443 ++++++++++++++++++++++++++++++++++++++++++++ hw/nvme/ns.c | 281 +++------------------------- hw/nvme/nvm.h | 65 +++++++ hw/nvme/nvme.h | 96 +--------- hw/nvme/zns.h | 48 +++++ qapi/qom.json | 48 +++++ softmmu/vl.c | 8 + 11 files changed, 1006 insertions(+), 352 deletions(-) create mode 100644 hw/nvme/ns-nvm.c create mode 100644 hw/nvme/ns-zoned.c create mode 100644 hw/nvme/nvm.h diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index c798aeb095e1..31499b10fc49 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -164,6 +164,7 @@ #include "nvme.h" #include "dif.h" +#include "nvm.h" #include "zns.h" #include "trace.h" @@ -5346,7 +5347,7 @@ static void nvme_format_set(NvmeNamespace *ns, NvmeCmd *cmd) nvm->id_ns.dps = (pil << 3) | pi; nvm->id_ns.flbas = lbaf | (mset << 4); - nvme_ns_nvm_init_format(nvm); + nvme_ns_nvm_configure_format(nvm); } static void nvme_format_ns_cb(void *opaque, int ret) @@ -6592,10 +6593,14 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) /* setup a namespace if the controller drive property was given */ if (ctrl->namespace.blkconf.blk) { NvmeNamespaceDevice *nsdev = &ctrl->namespace; - NvmeNamespace *ns = &nsdev->ns; + NvmeNamespace *ns = NVME_NAMESPACE(nsdev->ns); + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); ns->nsid = 1; - nvme_ns_init(ns); + ns->csi = NVME_CSI_NVM; + + nvme_ns_nvm_configure_identify(ns); + nvme_ns_nvm_configure_format(nvm); nvme_attach_ns(n, ns); } diff --git a/hw/nvme/dif.h b/hw/nvme/dif.h index 53a22bc7c78e..81efb95cd391 100644 --- a/hw/nvme/dif.h +++ b/hw/nvme/dif.h @@ -1,6 +1,8 @@ #ifndef HW_NVME_DIF_H #define HW_NVME_DIF_H +#include "nvm.h" + /* from Linux kernel (crypto/crct10dif_common.c) */ static const uint16_t t10_dif_crc_table[256] = { 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B, diff --git a/hw/nvme/meson.build b/hw/nvme/meson.build index 3cf40046eea9..2bb8354bcb57 100644 --- a/hw/nvme/meson.build +++ b/hw/nvme/meson.build @@ -1 +1 @@ -softmmu_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('ctrl.c', 'dif.c', 'ns.c', 'subsys.c')) +softmmu_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('ctrl.c', 'dif.c', 'ns.c', 'ns-nvm.c', 'ns-zoned.c', 'subsys.c')) diff --git a/hw/nvme/ns-nvm.c b/hw/nvme/ns-nvm.c new file mode 100644 index 000000000000..0d4f67d481cd --- /dev/null +++ b/hw/nvme/ns-nvm.c @@ -0,0 +1,354 @@ +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "qom/object_interfaces.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" + +#include "nvme.h" +#include "nvm.h" + +#include "trace.h" + +static char *get_blockdev(Object *obj, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + const char *value; + + value = blk_name(nvm->blk); + if (strcmp(value, "") == 0) { + BlockDriverState *bs = blk_bs(nvm->blk); + if (bs) { + value = bdrv_get_node_name(bs); + } + } + + return g_strdup(value); +} + +static void set_blockdev(Object *obj, const char *str, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + + g_free(nvm->blk_nodename); + nvm->blk_nodename = g_strdup(str); +} + +static void get_lba_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + uint64_t lba_size = nvm->lbasz; + + visit_type_size(v, name, &lba_size, errp); +} + +static void set_lba_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + uint64_t lba_size; + + if (!nvme_ns_prop_writable(obj, name, errp)) { + return; + } + + if (!visit_type_size(v, name, &lba_size, errp)) { + return; + } + + nvm->lbasz = lba_size; + nvm->lbaf.ds = 31 - clz32(nvm->lbasz); +} + +static void get_metadata_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + uint16_t value = nvm->lbaf.ms; + + visit_type_uint16(v, name, &value, errp); +} + +static void set_metadata_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + uint16_t value; + + if (!nvme_ns_prop_writable(obj, name, errp)) { + return; + } + + if (!visit_type_uint16(v, name, &value, errp)) { + return; + } + + nvm->lbaf.ms = value; +} + +static int get_pi(Object *obj, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + return nvm->id_ns.dps & NVME_ID_NS_DPS_TYPE_MASK; +} + +static void set_pi(Object *obj, int pi_type, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + + if (!nvme_ns_prop_writable(obj, "pi-type", errp)) { + return; + } + + nvm->id_ns.dps |= (nvm->id_ns.dps & ~NVME_ID_NS_DPS_TYPE_MASK) | pi_type; +} + +static bool get_pil(Object *obj, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + return nvm->id_ns.dps & NVME_ID_NS_DPS_FIRST_EIGHT; +} + +static void set_pil(Object *obj, bool first, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + + if (!nvme_ns_prop_writable(obj, "pi-first", errp)) { + return; + } + + if (!first) { + return; + } + + nvm->id_ns.dps |= NVME_NS_NVM_PI_FIRST; +} + +static bool get_extended_lba(Object *obj, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + return nvm->flags & NVME_NS_NVM_EXTENDED_LBA; +} + +static void set_extended_lba(Object *obj, bool extended, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + + if (!nvme_ns_prop_writable(obj, "extended-lba", errp)) { + return; + } + + if (extended) { + nvm->flags |= NVME_NS_NVM_EXTENDED_LBA; + } else { + nvm->flags &= ~NVME_NS_NVM_EXTENDED_LBA; + } +} + +void nvme_ns_nvm_configure_format(NvmeNamespaceNvm *nvm) +{ + NvmeIdNs *id_ns = &nvm->id_ns; + BlockDriverInfo bdi; + int npdg, nlbas, ret; + uint32_t discard_granularity = MAX(nvm->lbasz, 4096); + + nvm->lbaf = id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; + nvm->lbasz = 1 << nvm->lbaf.ds; + + if (nvm->lbaf.ms && nvm->flags & NVME_NS_NVM_EXTENDED_LBA) { + id_ns->flbas |= NVME_ID_NS_FLBAS_EXTENDED; + } + + nlbas = nvm->size / (nvm->lbasz + nvm->lbaf.ms); + + id_ns->nsze = cpu_to_le64(nlbas); + + /* no thin provisioning */ + id_ns->ncap = id_ns->nsze; + id_ns->nuse = id_ns->ncap; + + nvm->moff = nlbas * nvm->lbasz; + + npdg = discard_granularity / nvm->lbasz; + + ret = bdrv_get_info(blk_bs(nvm->blk), &bdi); + if (ret >= 0 && bdi.cluster_size > discard_granularity) { + npdg = bdi.cluster_size / nvm->lbasz; + } + + id_ns->npda = id_ns->npdg = npdg - 1; +} + +void nvme_ns_nvm_configure_identify(NvmeNamespace *ns) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + NvmeIdNs *id_ns = &nvm->id_ns; + + static const NvmeLBAF default_lba_formats[16] = { + [0] = { .ds = 9 }, + [1] = { .ds = 9, .ms = 8 }, + [2] = { .ds = 9, .ms = 16 }, + [3] = { .ds = 9, .ms = 64 }, + [4] = { .ds = 12 }, + [5] = { .ds = 12, .ms = 8 }, + [6] = { .ds = 12, .ms = 16 }, + [7] = { .ds = 12, .ms = 64 }, + }; + + id_ns->dlfeat = 0x1; + + /* support DULBE and I/O optimization fields */ + id_ns->nsfeat = 0x4 | 0x10; + + if (ns->flags & NVME_NS_SHARED) { + id_ns->nmic |= NVME_NMIC_NS_SHARED; + } + + /* eui64 is always stored in big-endian form */ + id_ns->eui64 = ns->eui64.v; + id_ns->nguid.eui = id_ns->eui64; + + id_ns->mc = NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE; + + id_ns->dpc = 0x1f; + + memcpy(&id_ns->lbaf, &default_lba_formats, sizeof(id_ns->lbaf)); + id_ns->nlbaf = 7; + + for (int i = 0; i <= id_ns->nlbaf; i++) { + NvmeLBAF *lbaf = &id_ns->lbaf[i]; + + if (lbaf->ds == nvm->lbaf.ds && lbaf->ms == nvm->lbaf.ms) { + id_ns->flbas |= i; + return; + } + } + + /* add non-standard lba format */ + id_ns->nlbaf++; + id_ns->lbaf[id_ns->nlbaf].ds = nvm->lbaf.ds; + id_ns->lbaf[id_ns->nlbaf].ms = nvm->lbaf.ms; + id_ns->flbas |= id_ns->nlbaf; +} + +int nvme_ns_nvm_configure(NvmeNamespace *ns, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + BlockBackend *blk; + int ret; + + blk = blk_by_name(nvm->blk_nodename); + if (!blk) { + BlockDriverState *bs = bdrv_lookup_bs(NULL, nvm->blk_nodename, NULL); + if (bs) { + blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); + + ret = blk_insert_bs(blk, bs, errp); + if (ret < 0) { + blk_unref(blk); + return -1; + } + } + } + + if (!blk) { + error_setg(errp, "invalid blockdev '%s'", nvm->blk_nodename); + return -1; + } + + blk_ref(blk); + blk_iostatus_reset(blk); + + nvm->blk = blk; + + nvm->size = blk_getlength(nvm->blk); + if (nvm->size < 0) { + error_setg_errno(errp, -(nvm->size), "could not get blockdev size"); + return -1; + } + + ns->csi = NVME_CSI_NVM; + + nvme_ns_nvm_configure_identify(ns); + nvme_ns_nvm_configure_format(nvm); + + return 0; +} + +int nvme_ns_nvm_check_params(NvmeNamespace *ns, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + int pi_type = nvm->id_ns.dps & NVME_ID_NS_DPS_TYPE_MASK; + + if (pi_type && nvm->lbaf.ms < 8) { + error_setg(errp, "at least 8 bytes of metadata required to enable " + "protection information"); + return -1; + } + + return 0; +} + +static void nvme_ns_nvm_class_init(ObjectClass *oc, void *data) +{ + ObjectProperty *op; + + NvmeNamespaceClass *nc = NVME_NAMESPACE_CLASS(oc); + + object_class_property_add_str(oc, "blockdev", get_blockdev, set_blockdev); + object_class_property_set_description(oc, "blockdev", + "node name or identifier of a " + "block device to use as a backend"); + + op = object_class_property_add(oc, "lba-size", "size", + get_lba_size, set_lba_size, + NULL, NULL); + object_property_set_default_uint(op, 4096); + object_class_property_set_description(oc, "lba-size", + "logical block size"); + + object_class_property_add(oc, "metadata-size", "uint16", + get_metadata_size, set_metadata_size, + NULL, NULL); + object_class_property_set_description(oc, "metadata-size", + "metadata size (default: 0)"); + + object_class_property_add_bool(oc, "extended-lba", + get_extended_lba, set_extended_lba); + object_class_property_set_description(oc, "extended-lba", + "use extended logical blocks " + "(default: off)"); + + object_class_property_add_enum(oc, "pi-type", "NvmeProtInfoType", + &NvmeProtInfoType_lookup, + get_pi, set_pi); + object_class_property_set_description(oc, "pi-type", + "protection information type " + "(default: none)"); + + object_class_property_add_bool(oc, "pi-first", get_pil, set_pil); + object_class_property_set_description(oc, "pi-first", + "transfer protection information " + "as the first eight bytes of " + "metadata (default: off)"); + + nc->check_params = nvme_ns_nvm_check_params; + nc->configure = nvme_ns_nvm_configure; +} + +static const TypeInfo nvme_ns_nvm_info = { + .name = TYPE_NVME_NAMESPACE_NVM, + .parent = TYPE_NVME_NAMESPACE, + .class_init = nvme_ns_nvm_class_init, + .instance_size = sizeof(NvmeNamespaceNvm), +}; + +static void register_types(void) +{ + type_register_static(&nvme_ns_nvm_info); +} + +type_init(register_types); diff --git a/hw/nvme/ns-zoned.c b/hw/nvme/ns-zoned.c new file mode 100644 index 000000000000..1403911c4f83 --- /dev/null +++ b/hw/nvme/ns-zoned.c @@ -0,0 +1,443 @@ +/* + * QEMU NVM Express Virtual Zoned Namespace + * + * Copyright (C) 2020 Western Digital Corporation or its affiliates. + * Copyright (c) 2021 Samsung Electronics + * + * Authors: + * Dmitry Fomichev + * Klaus Jensen + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" + +#include "nvme.h" +#include "zns.h" + +#include "trace.h" + +static void get_zone_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + uint64_t value = zoned->zone_size << nvm->lbaf.ds; + + visit_type_size(v, name, &value, errp); +} + +static void set_zone_size(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + uint64_t value; + + if (!nvme_ns_prop_writable(obj, name, errp)) { + return; + } + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + + zoned->zone_size = value >> nvm->lbaf.ds; +} + +static void get_zone_capacity(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + uint64_t value = zoned->zone_capacity << nvm->lbaf.ds; + + visit_type_size(v, name, &value, errp); +} + +static void set_zone_capacity(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(obj); + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + uint64_t value; + + if (!nvme_ns_prop_writable(obj, name, errp)) { + return; + } + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + + zoned->zone_capacity = value >> nvm->lbaf.ds; +} + +static void get_zone_max_active(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + + visit_type_uint32(v, name, &zoned->max_active_zones, errp); +} + +static void set_zone_max_active(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + + if (!nvme_ns_prop_writable(obj, name, errp)) { + return; + } + + if (!visit_type_uint32(v, name, &zoned->max_active_zones, errp)) { + return; + } +} + +static void get_zone_max_open(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + + visit_type_uint32(v, name, &zoned->max_open_zones, errp); +} + +static void set_zone_max_open(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + + if (!nvme_ns_prop_writable(obj, name, errp)) { + return; + } + + if (!visit_type_uint32(v, name, &zoned->max_open_zones, errp)) { + return; + } +} + +static bool get_zone_cross_read(Object *obj, Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + return zoned->flags & NVME_NS_ZONED_CROSS_READ; +} + +static void set_zone_cross_read(Object *obj, bool cross_read, Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + + if (!nvme_ns_prop_writable(obj, "zone-cross-read", errp)) { + return; + } + + if (cross_read) { + zoned->flags |= NVME_NS_ZONED_CROSS_READ; + } else { + zoned->flags &= ~NVME_NS_ZONED_CROSS_READ; + } +} + +static void get_zone_descriptor_extension_size(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + uint64_t value = zoned->zd_extension_size; + + visit_type_size(v, name, &value, errp); +} + +static void set_zone_descriptor_extension_size(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(obj); + uint64_t value; + + if (!nvme_ns_prop_writable(obj, name, errp)) { + return; + } + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + + if (value & 0x3f) { + error_setg(errp, "zone descriptor extension size must be a " + "multiple of 64 bytes"); + return; + } + if ((value >> 6) > 0xff) { + error_setg(errp, + "zone descriptor extension size is too large"); + return; + } + + zoned->zd_extension_size = value; +} + +void nvme_zns_init_state(NvmeNamespaceZoned *zoned) +{ + uint64_t start = 0, zone_size = zoned->zone_size; + uint64_t capacity = zoned->num_zones * zone_size; + NvmeZone *zone; + int i; + + zoned->zone_array = g_new0(NvmeZone, zoned->num_zones); + if (zoned->zd_extension_size) { + zoned->zd_extensions = g_malloc0(zoned->zd_extension_size * + zoned->num_zones); + } + + QTAILQ_INIT(&zoned->exp_open_zones); + QTAILQ_INIT(&zoned->imp_open_zones); + QTAILQ_INIT(&zoned->closed_zones); + QTAILQ_INIT(&zoned->full_zones); + + zone = zoned->zone_array; + for (i = 0; i < zoned->num_zones; i++, zone++) { + if (start + zone_size > capacity) { + zone_size = capacity - start; + } + zone->d.zt = NVME_ZONE_TYPE_SEQ_WRITE; + nvme_zns_set_state(zone, NVME_ZONE_STATE_EMPTY); + zone->d.za = 0; + zone->d.zcap = zoned->zone_capacity; + zone->d.zslba = start; + zone->d.wp = start; + zone->w_ptr = start; + start += zone_size; + } + + zoned->zone_size_log2 = 0; + if (is_power_of_2(zoned->zone_size)) { + zoned->zone_size_log2 = 63 - clz64(zoned->zone_size); + } +} + +int nvme_zns_configure(NvmeNamespace *ns, Error **errp) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + NvmeIdNsZoned *id_ns_z = &zoned->id_ns; + int i; + + if (nvme_ns_nvm_configure(ns, errp)) { + return -1; + } + + zoned->num_zones = le64_to_cpu(nvm->id_ns.nsze) / zoned->zone_size; + + if (zoned->max_active_zones && !zoned->max_open_zones) { + zoned->max_open_zones = zoned->max_active_zones; + } + + if (!zoned->num_zones) { + error_setg(errp, + "insufficient namespace size; must be at least the size " + "of one zone (%"PRIu64"B)", zoned->zone_size); + return -1; + } + + nvme_zns_init_state(zoned); + + /* MAR/MOR are zeroes-based, FFFFFFFFFh means no limit */ + id_ns_z->mar = cpu_to_le32(zoned->max_active_zones - 1); + id_ns_z->mor = cpu_to_le32(zoned->max_open_zones - 1); + id_ns_z->zoc = 0; + + if (zoned->flags & NVME_NS_ZONED_CROSS_READ) { + id_ns_z->ozcs |= NVME_ID_NS_ZONED_OZCS_CROSS_READ; + } + + for (i = 0; i <= nvm->id_ns.nlbaf; i++) { + id_ns_z->lbafe[i].zsze = cpu_to_le64(zoned->zone_size); + id_ns_z->lbafe[i].zdes = + zoned->zd_extension_size >> 6; /* Units of 64B */ + } + + ns->csi = NVME_CSI_ZONED; + nvm->id_ns.nsze = cpu_to_le64(zoned->num_zones * zoned->zone_size); + nvm->id_ns.ncap = nvm->id_ns.nsze; + nvm->id_ns.nuse = nvm->id_ns.ncap; + + /* + * The device uses the BDRV_BLOCK_ZERO flag to determine the "deallocated" + * status of logical blocks. Since the spec defines that logical blocks + * SHALL be deallocated when then zone is in the Empty or Offline states, + * we can only support DULBE if the zone size is a multiple of the + * calculated NPDG. + */ + if (zoned->zone_size % (nvm->id_ns.npdg + 1)) { + warn_report("the zone size (%"PRIu64" blocks) is not a multiple of " + "the calculated deallocation granularity (%d blocks); " + "DULBE support disabled", + zoned->zone_size, nvm->id_ns.npdg + 1); + + nvm->id_ns.nsfeat &= ~0x4; + } + + return 0; +} + +void nvme_zns_clear_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone) +{ + uint8_t state; + + zone->w_ptr = zone->d.wp; + state = nvme_zns_state(zone); + if (zone->d.wp != zone->d.zslba || + (zone->d.za & NVME_ZA_ZD_EXT_VALID)) { + if (state != NVME_ZONE_STATE_CLOSED) { + trace_pci_nvme_clear_ns_close(state, zone->d.zslba); + nvme_zns_set_state(zone, NVME_ZONE_STATE_CLOSED); + } + nvme_zns_aor_inc_active(zoned); + QTAILQ_INSERT_HEAD(&zoned->closed_zones, zone, entry); + } else { + trace_pci_nvme_clear_ns_reset(state, zone->d.zslba); + nvme_zns_set_state(zone, NVME_ZONE_STATE_EMPTY); + } +} + +/* + * Close all the zones that are currently open. + */ +void nvme_zns_shutdown(NvmeNamespace *ns) +{ + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + NvmeZone *zone, *next; + + QTAILQ_FOREACH_SAFE(zone, &zoned->closed_zones, entry, next) { + QTAILQ_REMOVE(&zoned->closed_zones, zone, entry); + nvme_zns_aor_dec_active(zoned); + nvme_zns_clear_zone(zoned, zone); + } + QTAILQ_FOREACH_SAFE(zone, &zoned->imp_open_zones, entry, next) { + QTAILQ_REMOVE(&zoned->imp_open_zones, zone, entry); + nvme_zns_aor_dec_open(zoned); + nvme_zns_aor_dec_active(zoned); + nvme_zns_clear_zone(zoned, zone); + } + QTAILQ_FOREACH_SAFE(zone, &zoned->exp_open_zones, entry, next) { + QTAILQ_REMOVE(&zoned->exp_open_zones, zone, entry); + nvme_zns_aor_dec_open(zoned); + nvme_zns_aor_dec_active(zoned); + nvme_zns_clear_zone(zoned, zone); + } + + assert(zoned->nr_open_zones == 0); +} + +static int nvme_zns_check_params(NvmeNamespace *ns, Error **errp) +{ + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); + + if (nvme_ns_nvm_check_params(ns, errp)) { + return -1; + } + + if (zoned->zone_size < nvm->lbaf.ds) { + error_setg(errp, "'zone-size' must be at least %"PRIu64" bytes", + nvm->lbasz); + return -1; + } + + if (zoned->zone_capacity < nvm->lbaf.ds) { + error_setg(errp, "'zone-capacity' must be at least %"PRIu64" bytes", + nvm->lbasz); + return -1; + } + + if (zoned->zone_capacity > zoned->zone_size) { + error_setg(errp, "'zone-capacity' must not exceed 'zone-size'"); + return -1; + } + + if (zoned->max_active_zones) { + if (zoned->max_open_zones > zoned->max_active_zones) { + error_setg(errp, "'zone-max-open' must not exceed 'zone-max-active'"); + return -1; + } + + if (!zoned->max_open_zones) { + zoned->max_open_zones = zoned->max_active_zones; + } + } + + return 0; +} + +static void nvme_zns_class_init(ObjectClass *oc, void *data) +{ + ObjectProperty *op; + + NvmeNamespaceClass *nc = NVME_NAMESPACE_CLASS(oc); + + op = object_class_property_add(oc, "zone-size", "size", + get_zone_size, set_zone_size, + NULL, NULL); + object_property_set_default_uint(op, 4096); + object_class_property_set_description(oc, "zone-size", "zone size"); + + op = object_class_property_add(oc, "zone-capacity", "size", + get_zone_capacity, set_zone_capacity, + NULL, NULL); + object_property_set_default_uint(op, 4096); + object_class_property_set_description(oc, "zone-capacity", + "zone capacity"); + + object_class_property_add_bool(oc, "zone-cross-read", + get_zone_cross_read, set_zone_cross_read); + object_class_property_set_description(oc, "zone-cross-read", + "allow reads to cross zone " + "boundaries"); + + object_class_property_add(oc, "zone-descriptor-extension-size", "size", + get_zone_descriptor_extension_size, + set_zone_descriptor_extension_size, + NULL, NULL); + object_class_property_set_description(oc, "zone-descriptor-extension-size", + "zone descriptor extension size"); + + object_class_property_add(oc, "zone-max-active", "uint32", + get_zone_max_active, set_zone_max_active, + NULL, NULL); + object_class_property_set_description(oc, "zone-max-active", + "maximum number of active zones"); + + object_class_property_add(oc, "zone-max-open", "uint32", + get_zone_max_open, set_zone_max_open, + NULL, NULL); + object_class_property_set_description(oc, "zone-max-open", + "maximum number of open zones"); + + nc->check_params = nvme_zns_check_params; + nc->configure = nvme_zns_configure; + nc->shutdown = nvme_zns_shutdown; +} + +static const TypeInfo nvme_zns_info = { + .name = TYPE_NVME_NAMESPACE_ZONED, + .parent = TYPE_NVME_NAMESPACE_NVM, + .class_init = nvme_zns_class_init, + .instance_size = sizeof(NvmeNamespaceZoned), +}; + +static void register_types(void) +{ + type_register_static(&nvme_zns_info); +} + +type_init(register_types); diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index d75ff4f1cb74..757a90b58ea8 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -30,107 +30,10 @@ #define MIN_DISCARD_GRANULARITY (4 * KiB) -void nvme_ns_nvm_init_format(NvmeNamespaceNvm *nvm) -{ - NvmeIdNs *id_ns = &nvm->id_ns; - BlockDriverInfo bdi; - int npdg, nlbas, ret; - - nvm->lbaf = id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; - nvm->lbasz = 1 << nvm->lbaf.ds; - - nlbas = nvm->size / (nvm->lbasz + nvm->lbaf.ms); - - id_ns->nsze = cpu_to_le64(nlbas); - - /* no thin provisioning */ - id_ns->ncap = id_ns->nsze; - id_ns->nuse = id_ns->ncap; - - nvm->moff = (int64_t)nlbas << nvm->lbaf.ds; - - npdg = nvm->discard_granularity / nvm->lbasz; - - ret = bdrv_get_info(blk_bs(nvm->blk), &bdi); - if (ret >= 0 && bdi.cluster_size > nvm->discard_granularity) { - npdg = bdi.cluster_size / nvm->lbasz; - } - - id_ns->npda = id_ns->npdg = npdg - 1; -} - -void nvme_ns_init(NvmeNamespace *ns) -{ - NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - NvmeIdNs *id_ns = &nvm->id_ns; - uint8_t ds; - uint16_t ms; - int i; - - id_ns->dlfeat = 0x1; - - /* support DULBE and I/O optimization fields */ - id_ns->nsfeat |= (0x4 | 0x10); - - if (ns->flags & NVME_NS_SHARED) { - id_ns->nmic |= NVME_NMIC_NS_SHARED; - } - - /* simple copy */ - id_ns->mssrl = cpu_to_le16(nvm->mssrl); - id_ns->mcl = cpu_to_le32(nvm->mcl); - id_ns->msrc = nvm->msrc; - id_ns->eui64 = cpu_to_be64(ns->eui64.v); - - ds = 31 - clz32(nvm->lbasz); - ms = nvm->lbaf.ms; - - id_ns->mc = NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE; - - if (ms && nvm->flags & NVME_NS_NVM_EXTENDED_LBA) { - id_ns->flbas |= NVME_ID_NS_FLBAS_EXTENDED; - } - - id_ns->dpc = 0x1f; - - static const NvmeLBAF lbaf[16] = { - [0] = { .ds = 9 }, - [1] = { .ds = 9, .ms = 8 }, - [2] = { .ds = 9, .ms = 16 }, - [3] = { .ds = 9, .ms = 64 }, - [4] = { .ds = 12 }, - [5] = { .ds = 12, .ms = 8 }, - [6] = { .ds = 12, .ms = 16 }, - [7] = { .ds = 12, .ms = 64 }, - }; - - memcpy(&id_ns->lbaf, &lbaf, sizeof(lbaf)); - id_ns->nlbaf = 7; - - for (i = 0; i <= id_ns->nlbaf; i++) { - NvmeLBAF *lbaf = &id_ns->lbaf[i]; - if (lbaf->ds == ds) { - if (lbaf->ms == ms) { - id_ns->flbas |= i; - goto lbaf_found; - } - } - } - - /* add non-standard lba format */ - id_ns->nlbaf++; - id_ns->lbaf[id_ns->nlbaf].ds = ds; - id_ns->lbaf[id_ns->nlbaf].ms = ms; - id_ns->flbas |= id_ns->nlbaf; - -lbaf_found: - nvme_ns_nvm_init_format(nvm); -} - static int nvme_nsdev_init_blk(NvmeNamespaceDevice *nsdev, Error **errp) { - NvmeNamespace *ns = &nsdev->ns; + NvmeNamespace *ns = NVME_NAMESPACE(nsdev->ns); NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); BlockConf *blkconf = &nsdev->blkconf; bool read_only; @@ -167,7 +70,7 @@ static int nvme_nsdev_init_blk(NvmeNamespaceDevice *nsdev, static int nvme_nsdev_zns_check_calc_geometry(NvmeNamespaceDevice *nsdev, Error **errp) { - NvmeNamespace *ns = &nsdev->ns; + NvmeNamespace *ns = NVME_NAMESPACE(nsdev->ns); NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); @@ -206,152 +109,10 @@ static int nvme_nsdev_zns_check_calc_geometry(NvmeNamespaceDevice *nsdev, */ zoned->zone_size = zone_size / nvm->lbasz; zoned->zone_capacity = zone_cap / nvm->lbasz; - zoned->num_zones = le64_to_cpu(nvm->id_ns.nsze) / zoned->zone_size; - - /* Do a few more sanity checks of ZNS properties */ - if (!zoned->num_zones) { - error_setg(errp, - "insufficient drive capacity, must be at least the size " - "of one zone (%"PRIu64"B)", zone_size); - return -1; - } return 0; } -static void nvme_zns_init_state(NvmeNamespaceZoned *zoned) -{ - uint64_t start = 0, zone_size = zoned->zone_size; - uint64_t capacity = zoned->num_zones * zone_size; - NvmeZone *zone; - int i; - - zoned->zone_array = g_new0(NvmeZone, zoned->num_zones); - if (zoned->zd_extension_size) { - zoned->zd_extensions = g_malloc0(zoned->zd_extension_size * - zoned->num_zones); - } - - QTAILQ_INIT(&zoned->exp_open_zones); - QTAILQ_INIT(&zoned->imp_open_zones); - QTAILQ_INIT(&zoned->closed_zones); - QTAILQ_INIT(&zoned->full_zones); - - zone = zoned->zone_array; - for (i = 0; i < zoned->num_zones; i++, zone++) { - if (start + zone_size > capacity) { - zone_size = capacity - start; - } - zone->d.zt = NVME_ZONE_TYPE_SEQ_WRITE; - nvme_zns_set_state(zone, NVME_ZONE_STATE_EMPTY); - zone->d.za = 0; - zone->d.zcap = zoned->zone_capacity; - zone->d.zslba = start; - zone->d.wp = start; - zone->w_ptr = start; - start += zone_size; - } - - zoned->zone_size_log2 = 0; - if (is_power_of_2(zoned->zone_size)) { - zoned->zone_size_log2 = 63 - clz64(zoned->zone_size); - } -} - -static void nvme_zns_init(NvmeNamespace *ns) -{ - NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); - NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); - NvmeIdNsZoned *id_ns_z = &zoned->id_ns; - int i; - - nvme_zns_init_state(zoned); - - /* MAR/MOR are zeroes-based, FFFFFFFFFh means no limit */ - id_ns_z->mar = cpu_to_le32(zoned->max_active_zones - 1); - id_ns_z->mor = cpu_to_le32(zoned->max_open_zones - 1); - id_ns_z->zoc = 0; - - if (zoned->flags & NVME_NS_ZONED_CROSS_READ) { - id_ns_z->ozcs |= NVME_ID_NS_ZONED_OZCS_CROSS_READ; - } - - for (i = 0; i <= nvm->id_ns.nlbaf; i++) { - id_ns_z->lbafe[i].zsze = cpu_to_le64(zoned->zone_size); - id_ns_z->lbafe[i].zdes = - zoned->zd_extension_size >> 6; /* Units of 64B */ - } - - ns->csi = NVME_CSI_ZONED; - nvm->id_ns.nsze = cpu_to_le64(zoned->num_zones * zoned->zone_size); - nvm->id_ns.ncap = nvm->id_ns.nsze; - nvm->id_ns.nuse = nvm->id_ns.ncap; - - /* - * The device uses the BDRV_BLOCK_ZERO flag to determine the "deallocated" - * status of logical blocks. Since the spec defines that logical blocks - * SHALL be deallocated when then zone is in the Empty or Offline states, - * we can only support DULBE if the zone size is a multiple of the - * calculated NPDG. - */ - if (zoned->zone_size % (nvm->id_ns.npdg + 1)) { - warn_report("the zone size (%"PRIu64" blocks) is not a multiple of " - "the calculated deallocation granularity (%d blocks); " - "DULBE support disabled", - zoned->zone_size, nvm->id_ns.npdg + 1); - - nvm->id_ns.nsfeat &= ~0x4; - } -} - -static void nvme_zns_clear_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone) -{ - uint8_t state; - - zone->w_ptr = zone->d.wp; - state = nvme_zns_state(zone); - if (zone->d.wp != zone->d.zslba || - (zone->d.za & NVME_ZA_ZD_EXT_VALID)) { - if (state != NVME_ZONE_STATE_CLOSED) { - trace_pci_nvme_clear_ns_close(state, zone->d.zslba); - nvme_zns_set_state(zone, NVME_ZONE_STATE_CLOSED); - } - nvme_zns_aor_inc_active(zoned); - QTAILQ_INSERT_HEAD(&zoned->closed_zones, zone, entry); - } else { - trace_pci_nvme_clear_ns_reset(state, zone->d.zslba); - nvme_zns_set_state(zone, NVME_ZONE_STATE_EMPTY); - } -} - -/* - * Close all the zones that are currently open. - */ -static void nvme_zns_shutdown(NvmeNamespaceZoned *zoned) -{ - NvmeZone *zone, *next; - - QTAILQ_FOREACH_SAFE(zone, &zoned->closed_zones, entry, next) { - QTAILQ_REMOVE(&zoned->closed_zones, zone, entry); - nvme_zns_aor_dec_active(zoned); - nvme_zns_clear_zone(zoned, zone); - } - QTAILQ_FOREACH_SAFE(zone, &zoned->imp_open_zones, entry, next) { - QTAILQ_REMOVE(&zoned->imp_open_zones, zone, entry); - nvme_zns_aor_dec_open(zoned); - nvme_zns_aor_dec_active(zoned); - nvme_zns_clear_zone(zoned, zone); - } - QTAILQ_FOREACH_SAFE(zone, &zoned->exp_open_zones, entry, next) { - QTAILQ_REMOVE(&zoned->exp_open_zones, zone, entry); - nvme_zns_aor_dec_open(zoned); - nvme_zns_aor_dec_active(zoned); - nvme_zns_clear_zone(zoned, zone); - } - - assert(zoned->nr_open_zones == 0); -} - static int nvme_nsdev_check_constraints(NvmeNamespaceDevice *nsdev, Error **errp) { @@ -405,7 +166,8 @@ static int nvme_nsdev_check_constraints(NvmeNamespaceDevice *nsdev, static int nvme_nsdev_setup(NvmeNamespaceDevice *nsdev, Error **errp) { - NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(&nsdev->ns); + NvmeNamespace *ns = NVME_NAMESPACE(nsdev->ns); + NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns); static uint64_t ns_count; if (nvme_nsdev_check_constraints(nsdev, errp)) { @@ -413,20 +175,20 @@ static int nvme_nsdev_setup(NvmeNamespaceDevice *nsdev, Error **errp) } if (nsdev->params.shared) { - nsdev->ns.flags |= NVME_NS_SHARED; + ns->flags |= NVME_NS_SHARED; } - nsdev->ns.nsid = nsdev->params.nsid; - memcpy(&nsdev->ns.uuid, &nsdev->params.uuid, sizeof(nsdev->ns.uuid)); + ns->nsid = nsdev->params.nsid; + memcpy(&ns->uuid, &nsdev->params.uuid, sizeof(ns->uuid)); if (nsdev->params.eui64) { - stq_be_p(&nsdev->ns.eui64.v, nsdev->params.eui64); + stq_be_p(&ns->eui64.v, nsdev->params.eui64); } /* Substitute a missing EUI-64 by an autogenerated one */ ++ns_count; - if (!nsdev->ns.eui64.v && nsdev->params.eui64_default) { - nsdev->ns.eui64.v = ns_count + NVME_EUI64_DEFAULT; + if (!ns->eui64.v && nsdev->params.eui64_default) { + ns->eui64.v = ns_count + NVME_EUI64_DEFAULT; } nvm->id_ns.dps = nsdev->params.pi; @@ -434,12 +196,13 @@ static int nvme_nsdev_setup(NvmeNamespaceDevice *nsdev, Error **errp) nvm->id_ns.dps |= NVME_ID_NS_DPS_FIRST_EIGHT; } - nsdev->ns.csi = NVME_CSI_NVM; + ns->csi = NVME_CSI_NVM; - nvme_ns_init(&nsdev->ns); + nvme_ns_nvm_configure_identify(ns); + nvme_ns_nvm_configure_format(nvm); if (nsdev->params.zoned) { - NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(&nsdev->ns); + NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns); if (nvme_nsdev_zns_check_calc_geometry(nsdev, errp) != 0) { return -1; @@ -453,7 +216,9 @@ static int nvme_nsdev_setup(NvmeNamespaceDevice *nsdev, Error **errp) zoned->flags |= NVME_NS_ZONED_CROSS_READ; } - nvme_zns_init(&nsdev->ns); + if (nvme_zns_configure(ns, errp)) { + return -1; + } } return 0; @@ -468,7 +233,7 @@ void nvme_ns_shutdown(NvmeNamespace *ns) { blk_flush(nvme_blk(ns)); if (nvme_ns_zoned(ns)) { - nvme_zns_shutdown(NVME_NAMESPACE_ZONED(ns)); + nvme_zns_shutdown(ns); } } @@ -485,7 +250,7 @@ void nvme_ns_cleanup(NvmeNamespace *ns) static void nvme_nsdev_unrealize(DeviceState *dev) { NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev); - NvmeNamespace *ns = &nsdev->ns; + NvmeNamespace *ns = NVME_NAMESPACE(nsdev->ns); nvme_ns_drain(ns); nvme_ns_shutdown(ns); @@ -495,7 +260,7 @@ static void nvme_nsdev_unrealize(DeviceState *dev) static void nvme_nsdev_realize(DeviceState *dev, Error **errp) { NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev); - NvmeNamespace *ns = &nsdev->ns; + NvmeNamespace *ns = NULL; BusState *s = qdev_get_parent_bus(dev); NvmeCtrl *ctrl = NVME_DEVICE(s->parent); NvmeState *n = NVME_STATE(ctrl); @@ -519,6 +284,12 @@ static void nvme_nsdev_realize(DeviceState *dev, Error **errp) } } + nsdev->ns = nsdev->params.zoned ? object_new(TYPE_NVME_NAMESPACE_ZONED) : + object_new(TYPE_NVME_NAMESPACE_NVM); + + ns = NVME_NAMESPACE(nsdev->ns); + ns->realized = true; + if (nvme_nsdev_init_blk(nsdev, errp)) { return; } diff --git a/hw/nvme/nvm.h b/hw/nvme/nvm.h new file mode 100644 index 000000000000..c3882ce5c21d --- /dev/null +++ b/hw/nvme/nvm.h @@ -0,0 +1,65 @@ +#ifndef HW_NVME_NVM_H +#define HW_NVME_NVM_H + +#include "nvme.h" + +#define TYPE_NVME_NAMESPACE_NVM "x-nvme-ns-nvm" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeNamespaceNvm, NVME_NAMESPACE_NVM) + +enum { + NVME_NS_NVM_EXTENDED_LBA = 1 << 0, + NVME_NS_NVM_PI_FIRST = 1 << 1, +}; + +typedef struct NvmeNamespaceNvm { + NvmeNamespace parent_obj; + + NvmeIdNs id_ns; + + char *blk_nodename; + BlockBackend *blk; + int64_t size; + int64_t moff; + + NvmeLBAF lbaf; + size_t lbasz; + uint32_t discard_granularity; + + uint16_t mssrl; + uint32_t mcl; + uint8_t msrc; + + unsigned long flags; +} NvmeNamespaceNvm; + +static inline BlockBackend *nvme_blk(NvmeNamespace *ns) +{ + return NVME_NAMESPACE_NVM(ns)->blk; +} + +static inline size_t nvme_l2b(NvmeNamespaceNvm *nvm, uint64_t lba) +{ + return lba << nvm->lbaf.ds; +} + +static inline size_t nvme_m2b(NvmeNamespaceNvm *nvm, uint64_t lba) +{ + return nvm->lbaf.ms * lba; +} + +static inline int64_t nvme_moff(NvmeNamespaceNvm *nvm, uint64_t lba) +{ + return nvm->moff + nvme_m2b(nvm, lba); +} + +static inline bool nvme_ns_ext(NvmeNamespaceNvm *nvm) +{ + return !!NVME_ID_NS_FLBAS_EXTENDED(nvm->id_ns.flbas); +} + +int nvme_ns_nvm_check_params(NvmeNamespace *ns, Error **errp); +int nvme_ns_nvm_configure(NvmeNamespace *ns, Error **errp); +void nvme_ns_nvm_configure_format(NvmeNamespaceNvm *nvm); +void nvme_ns_nvm_configure_identify(NvmeNamespace *ns); + +#endif /* HW_NVME_NVM_H */ diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 627b28649892..5e516f8fb377 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -21,6 +21,7 @@ #include "qemu/uuid.h" #include "qemu/notify.h" #include "qapi/qapi-builtin-visit.h" +#include "qapi/qapi-types-qom.h" #include "hw/pci/pci.h" #include "hw/block/block.h" @@ -55,6 +56,7 @@ struct NvmeNamespaceClass { int (*check_params)(NvmeNamespace *ns, Error **errp); int (*configure)(NvmeNamespace *ns, Error **errp); + void (*shutdown)(NvmeNamespace *ns); }; #define TYPE_NVME_SUBSYSTEM "x-nvme-subsystem" @@ -139,66 +141,6 @@ typedef struct NvmeNamespaceParams { uint32_t zd_extension_size; } NvmeNamespaceParams; -typedef struct NvmeZone { - NvmeZoneDescr d; - uint64_t w_ptr; - QTAILQ_ENTRY(NvmeZone) entry; -} NvmeZone; - -enum { - NVME_NS_ZONED_CROSS_READ = 1 << 0, -}; - -typedef struct NvmeNamespaceZoned { - NvmeIdNsZoned id_ns; - - uint32_t num_zones; - NvmeZone *zone_array; - - uint64_t zone_size; - uint32_t zone_size_log2; - - uint64_t zone_capacity; - - uint32_t zd_extension_size; - uint8_t *zd_extensions; - - uint32_t max_open_zones; - int32_t nr_open_zones; - uint32_t max_active_zones; - int32_t nr_active_zones; - - unsigned long flags; - - QTAILQ_HEAD(, NvmeZone) exp_open_zones; - QTAILQ_HEAD(, NvmeZone) imp_open_zones; - QTAILQ_HEAD(, NvmeZone) closed_zones; - QTAILQ_HEAD(, NvmeZone) full_zones; -} NvmeNamespaceZoned; - -enum { - NVME_NS_NVM_EXTENDED_LBA = 1 << 0, - NVME_NS_NVM_PI_FIRST = 1 << 1, -}; - -typedef struct NvmeNamespaceNvm { - NvmeIdNs id_ns; - - BlockBackend *blk; - int64_t size; - int64_t moff; - - NvmeLBAF lbaf; - size_t lbasz; - uint32_t discard_granularity; - - uint16_t mssrl; - uint32_t mcl; - uint8_t msrc; - - unsigned long flags; -} NvmeNamespaceNvm; - enum NvmeNamespaceFlags { NVME_NS_SHARED = 1 << 0, }; @@ -227,27 +169,16 @@ typedef struct NvmeNamespace { struct { uint32_t err_rec; } features; - - NvmeNamespaceNvm nvm; - NvmeNamespaceZoned zoned; } NvmeNamespace; bool nvme_ns_prop_writable(Object *obj, const char *name, Error **errp); -#define NVME_NAMESPACE_NVM(ns) (&(ns)->nvm) -#define NVME_NAMESPACE_ZONED(ns) (&(ns)->zoned) - -static inline BlockBackend *nvme_blk(NvmeNamespace *ns) -{ - return NVME_NAMESPACE_NVM(ns)->blk; -} - typedef struct NvmeNamespaceDevice { DeviceState parent_obj; BlockConf blkconf; int32_t bootindex; - NvmeNamespace ns; + Object *ns; NvmeNamespaceParams params; } NvmeNamespaceDevice; @@ -260,27 +191,6 @@ static inline uint32_t nvme_nsid(NvmeNamespace *ns) return 0; } -static inline size_t nvme_l2b(NvmeNamespaceNvm *nvm, uint64_t lba) -{ - return lba << nvm->lbaf.ds; -} - -static inline size_t nvme_m2b(NvmeNamespaceNvm *nvm, uint64_t lba) -{ - return nvm->lbaf.ms * lba; -} - -static inline int64_t nvme_moff(NvmeNamespaceNvm *nvm, uint64_t lba) -{ - return nvm->moff + nvme_m2b(nvm, lba); -} - -static inline bool nvme_ns_ext(NvmeNamespaceNvm *nvm) -{ - return !!NVME_ID_NS_FLBAS_EXTENDED(nvm->id_ns.flbas); -} - -void nvme_ns_nvm_init_format(NvmeNamespaceNvm *nvm); void nvme_ns_init(NvmeNamespace *ns); void nvme_ns_drain(NvmeNamespace *ns); void nvme_ns_shutdown(NvmeNamespace *ns); diff --git a/hw/nvme/zns.h b/hw/nvme/zns.h index 967adc62d730..1a040d900d5c 100644 --- a/hw/nvme/zns.h +++ b/hw/nvme/zns.h @@ -4,9 +4,52 @@ #include "qemu/units.h" #include "nvme.h" +#include "nvm.h" #define NVME_DEFAULT_ZONE_SIZE (128 * MiB) +#define TYPE_NVME_NAMESPACE_ZONED "x-nvme-ns-zoned" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeNamespaceZoned, NVME_NAMESPACE_ZONED) + +typedef struct NvmeZone { + NvmeZoneDescr d; + uint64_t w_ptr; + QTAILQ_ENTRY(NvmeZone) entry; +} NvmeZone; + +enum { + NVME_NS_ZONED_CROSS_READ = 1 << 0, +}; + +typedef struct NvmeNamespaceZoned { + NvmeNamespaceNvm parent_obj; + + NvmeIdNsZoned id_ns; + + uint32_t num_zones; + NvmeZone *zone_array; + + uint64_t zone_size; + uint32_t zone_size_log2; + + uint64_t zone_capacity; + + uint32_t zd_extension_size; + uint8_t *zd_extensions; + + uint32_t max_open_zones; + int32_t nr_open_zones; + uint32_t max_active_zones; + int32_t nr_active_zones; + + unsigned long flags; + + QTAILQ_HEAD(, NvmeZone) exp_open_zones; + QTAILQ_HEAD(, NvmeZone) imp_open_zones; + QTAILQ_HEAD(, NvmeZone) closed_zones; + QTAILQ_HEAD(, NvmeZone) full_zones; +} NvmeNamespaceZoned; + static inline NvmeZoneState nvme_zns_state(NvmeZone *zone) { return zone->d.zs >> 4; @@ -96,4 +139,9 @@ static inline void nvme_zns_aor_dec_active(NvmeNamespaceZoned *zoned) assert(zoned->nr_active_zones >= 0); } +void nvme_zns_init_state(NvmeNamespaceZoned *zoned); +int nvme_zns_configure(NvmeNamespace *ns, Error **errp); +void nvme_zns_clear_zone(NvmeNamespaceZoned *zoned, NvmeZone *zone); +void nvme_zns_shutdown(NvmeNamespace *ns); + #endif /* HW_NVME_ZNS_H */ diff --git a/qapi/qom.json b/qapi/qom.json index 6d5cef6b92ad..84bec3be8493 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -679,6 +679,50 @@ '*eui64': 'str', '*uuid': 'str' } } +## +# @NvmeProtInfoType: +# +# Indicates the namespace protection information type. +# +# Since: 6.1 +## +{ 'enum': 'NvmeProtInfoType', + 'data': [ 'none', 'type1', 'type2', 'type3' ] } + +## +# @NvmeNamespaceNvmProperties: +# +# Properties for x-nvme-ns-nvm objects. +# +# @pi-type: protection information type +# +# Since: 6.1 +## +{ 'struct': 'NvmeNamespaceNvmProperties', + 'base': 'NvmeNamespaceProperties', + 'data': { 'blockdev': 'str', + '*lba-size': 'size', + '*metadata-size': 'size', + '*extended-lba': 'bool', + '*pi-type': 'NvmeProtInfoType', + '*pi-first': 'bool' } } + +## +# @NvmeNamespaceZonedProperties: +# +# Properties for x-nvme-ns-zoned objects. +# +# Since: 6.1 +## +{ 'struct': 'NvmeNamespaceZonedProperties', + 'base': 'NvmeNamespaceNvmProperties', + 'data': { '*zone-size': 'size', + '*zone-capacity': 'size', + '*zone-cross-read': 'bool', + '*zone-descriptor-extension-size': 'size', + '*zone-max-active': 'uint32', + '*zone-max-open': 'uint32' } } + ## # @PrManagerHelperProperties: # @@ -830,6 +874,8 @@ 'if': 'CONFIG_LINUX' }, 'memory-backend-ram', 'x-nvme-subsystem', + 'x-nvme-ns-nvm', + 'x-nvme-ns-zoned', 'pef-guest', 'pr-manager-helper', 'qtest', @@ -889,6 +935,8 @@ 'if': 'CONFIG_LINUX' }, 'memory-backend-ram': 'MemoryBackendProperties', 'x-nvme-subsystem': 'NvmeSubsystemProperties', + 'x-nvme-ns-nvm': 'NvmeNamespaceNvmProperties', + 'x-nvme-ns-zoned': 'NvmeNamespaceZonedProperties', 'pr-manager-helper': 'PrManagerHelperProperties', 'qtest': 'QtestProperties', 'rng-builtin': 'RngProperties', diff --git a/softmmu/vl.c b/softmmu/vl.c index 55ab70eb97fe..24374189b1bf 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1833,6 +1833,14 @@ static bool object_create_early(const char *type) return false; } + /* + * Reason: x-nvme-ns-* property "blockdev" + */ + if (g_str_equal(type, "x-nvme-ns-nvm") || + g_str_equal(type, "x-nvme-ns-zoned")) { + return false; + } + /* * Allocation of large amounts of memory may delay * chardev initialization for too long, and trigger timeouts From patchwork Mon Sep 27 05:17:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533212 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=C5oWwc08; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=JmKlrCHq; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHsQ036HFz9tkD for ; Mon, 27 Sep 2021 15:58:32 +1000 (AEST) Received: from localhost ([::1]:52424 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjeo-0008Vr-26 for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:58:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34376) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2k-0004E7-S6; Mon, 27 Sep 2021 01:19:10 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:49231) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj2i-0000cV-Dx; Mon, 27 Sep 2021 01:19:10 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.west.internal (Postfix) with ESMTP id DA81A2B0121D; Mon, 27 Sep 2021 01:19:05 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Mon, 27 Sep 2021 01:19:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=s0AJ4WKeeSCB3 969Tlnnj33j2oRAr/BPhg8TLTc7dMo=; b=C5oWwc08wjCsgTHbTKiHzo0A/rihx v3hTGgTABAywALFPcXWMB7vV2sFbRtX1jyadn/9EbQNVPIIAoHE91k1pgrv2Aqdc bJq8wcGkBBkXn9I/DevjCdTTwdsb83JmJgCRrHoLNwB5uWv1w5PFA1nfMoD3WFo2 aY3AG3Tznh/GzXNIFu75hoaVdGG/MLxuufG+U0mKLOopF5avBUNhQ9lLYcJ1h+Ov gA4Abo3lhfE6PpNl+C4EkDkJ1CICU/EgsDG5PpDlr3KmS0Fpgufcdj7Egw5vRue2 OwdrrlkPC8KhUU+9SgSnftZL4V0CEcksWVJ4Im1cuK54RiBVNNcnZCldA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=s0AJ4WKeeSCB3969Tlnnj33j2oRAr/BPhg8TLTc7dMo=; b=JmKlrCHq rSj3DlMBO8TW+IvyHkmeXb8mFk6XAwEQNMOa8OO1SwKaVpf2dP7rIEQH0/2QKQqr KlrI9ceF4lw4VrhI5BuaeiKszE2BcjDcOKEQfpJVgX7QApqEM3b156VY8TMt4ymb mOzISf/KqdN7Tw81NFFcfrdQjt0NmK8Iu6aUGulJW4+8gBOxhw9gcXA5Ng46T9s/ vq0/yiPR2K2Uw/PdaxLNx3q8zOrUaDuAfkZfdVGAhXHkyOAt7YLm5XFKqWq1FiTZ C0qSxWPVqYvgZHoGM5Og8adsvXNUpHXUKDbBARWHe3VC+akQhwswzsguKqS7GhnM ARLiKrBAsV7WSw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgleefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:19:03 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 15/16] hw/nvme: add experimental device x-nvme-ctrl Date: Mon, 27 Sep 2021 07:17:58 +0200 Message-Id: <20210927051759.447305-16-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Add a new experimental 'x-nvme-ctrl' device which allows us to get rid of a bunch of legacy options and slightly change others to better use the qdev property system. Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 137 +++++++++++++++++++++++++++++++++++------------ hw/nvme/ns.c | 2 +- hw/nvme/nvme.h | 11 +++- hw/nvme/subsys.c | 27 ++++++---- 4 files changed, 130 insertions(+), 47 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 31499b10fc49..fa2f537f114d 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -6529,19 +6529,14 @@ static void nvme_init_ctrl(NvmeState *n, PCIDevice *pci_dev) static int nvme_init_subsys(NvmeState *n, Error **errp) { - int cntlid; - if (!n->subsys) { return 0; } - cntlid = nvme_subsys_register_ctrl(n->subsys, n, errp); - if (cntlid < 0) { + if (nvme_subsys_register_ctrl(n->subsys, n, errp)) { return -1; } - n->cntlid = cntlid; - return 0; } @@ -6560,8 +6555,39 @@ void nvme_attach_ns(NvmeState *n, NvmeNamespace *ns) static void nvme_realize(PCIDevice *pci_dev, Error **errp) { - NvmeCtrl *ctrl = NVME_DEVICE(pci_dev); - NvmeState *n = NVME_STATE(ctrl); + NvmeState *n = NVME_STATE(pci_dev); + const int SN_LEN = 12; + + if (!n->params.serial) { + int i; + + n->params.serial = g_malloc0(SN_LEN + 1); + + for (i = 0; i < SN_LEN; i++) { + n->params.serial[i] = g_random_int_range(0x41, 0x5A); + } + } + + if (nvme_check_constraints(n, errp)) { + return; + } + + nvme_init_state(n); + if (nvme_init_pci(n, pci_dev, errp)) { + return; + } + + if (nvme_init_subsys(n, errp)) { + return; + } + + nvme_init_ctrl(n, pci_dev); +} + +static void nvme_legacy_realize(PCIDevice *pci_dev, Error **errp) +{ + NvmeState *n = NVME_STATE(pci_dev); + NvmeCtrlLegacyDevice *ctrl = NVME_DEVICE_LEGACY(n); if (ctrl->subsys_dev) { if (ctrl->namespace.blkconf.blk) { @@ -6588,6 +6614,7 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) if (nvme_init_subsys(n, errp)) { return; } + nvme_init_ctrl(n, pci_dev); /* setup a namespace if the controller drive property was given */ @@ -6643,27 +6670,47 @@ static void nvme_exit(PCIDevice *pci_dev) static Property nvme_state_props[] = { DEFINE_PROP_LINK("pmrdev", NvmeState, pmr.dev, TYPE_MEMORY_BACKEND, HostMemoryBackend *), - DEFINE_PROP_LINK("subsys", NvmeState, subsys_dev, - TYPE_NVME_SUBSYSTEM_DEVICE, NvmeSubsystemDevice *), DEFINE_PROP_STRING("serial", NvmeState, params.serial), - DEFINE_PROP_UINT32("cmb_size_mb", NvmeState, params.cmb_size_mb, 0), - DEFINE_PROP_UINT32("num_queues", NvmeState, params.num_queues, 0), - DEFINE_PROP_UINT32("max_ioqpairs", NvmeState, params.max_ioqpairs, 64), - DEFINE_PROP_UINT16("msix_qsize", NvmeState, params.msix_qsize, 65), DEFINE_PROP_UINT8("aerl", NvmeState, params.aerl, 3), - DEFINE_PROP_UINT32("aer_max_queued", NvmeState, params.aer_max_queued, 64), DEFINE_PROP_UINT8("mdts", NvmeState, params.mdts, 7), - DEFINE_PROP_UINT8("vsl", NvmeState, params.vsl, 7), - DEFINE_PROP_BOOL("use-intel-id", NvmeState, params.use_intel_id, false), DEFINE_PROP_BOOL("legacy-cmb", NvmeState, params.legacy_cmb, false), - DEFINE_PROP_UINT8("zoned.zasl", NvmeState, params.zasl, 0), - DEFINE_PROP_BOOL("zoned.auto_transition", NvmeState, - params.auto_transition_zones, true), DEFINE_PROP_END_OF_LIST(), }; static Property nvme_props[] = { - DEFINE_BLOCK_PROPERTIES(NvmeCtrl, namespace.blkconf), + DEFINE_PROP_LINK("subsys", NvmeState, subsys, TYPE_NVME_SUBSYSTEM, + NvmeSubsystem *), + + DEFINE_PROP_UINT16("cntlid", NvmeState, cntlid, 0), + DEFINE_PROP_UINT32("cmb-size-mb", NvmeState, params.cmb_size_mb, 0), + DEFINE_PROP_UINT32("max-aen-retention", NvmeState, params.aer_max_queued, 64), + DEFINE_PROP_UINT32("max-ioqpairs", NvmeState, params.max_ioqpairs, 64), + DEFINE_PROP_UINT16("msix-vectors", NvmeState, params.msix_qsize, 2048), + + /* nvm command set specific properties */ + DEFINE_PROP_UINT8("nvm-vsl", NvmeState, params.vsl, 7), + + /* zoned command set specific properties */ + DEFINE_PROP_UINT8("zoned-zasl", NvmeState, params.zasl, 0), + DEFINE_PROP_BOOL("zoned-auto-transition-zones", NvmeState, + params.auto_transition_zones, true), + DEFINE_PROP_END_OF_LIST(), +}; + +static Property nvme_legacy_props[] = { + DEFINE_BLOCK_PROPERTIES(NvmeCtrlLegacyDevice, namespace.blkconf), + DEFINE_PROP_LINK("subsys", NvmeCtrlLegacyDevice, subsys_dev, + TYPE_NVME_SUBSYSTEM_DEVICE, NvmeSubsystemDevice *), + DEFINE_PROP_UINT32("cmb_size_mb", NvmeState, params.cmb_size_mb, 0), + DEFINE_PROP_UINT32("num_queues", NvmeState, params.num_queues, 0), + DEFINE_PROP_UINT32("aer_max_queued", NvmeState, params.aer_max_queued, 64), + DEFINE_PROP_UINT32("max_ioqpairs", NvmeState, params.max_ioqpairs, 64), + DEFINE_PROP_UINT16("msix_qsize", NvmeState, params.msix_qsize, 65), + DEFINE_PROP_BOOL("use-intel-id", NvmeState, params.use_intel_id, false), + DEFINE_PROP_UINT8("vsl", NvmeState, params.vsl, 7), + DEFINE_PROP_UINT8("zoned.zasl", NvmeState, params.zasl, 0), + DEFINE_PROP_BOOL("zoned.auto_transition", NvmeState, + params.auto_transition_zones, true), DEFINE_PROP_END_OF_LIST(), }; @@ -6719,7 +6766,6 @@ static void nvme_state_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); - pc->realize = nvme_realize; pc->exit = nvme_exit; pc->class_id = PCI_CLASS_STORAGE_EXPRESS; pc->revision = 2; @@ -6753,25 +6799,45 @@ static const TypeInfo nvme_state_info = { static void nvme_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); + + pc->realize = nvme_realize; + device_class_set_props(dc, nvme_props); } -static void nvme_instance_init(Object *obj) -{ - NvmeCtrl *ctrl = NVME_DEVICE(obj); - - device_add_bootindex_property(obj, &ctrl->namespace.blkconf.bootindex, - "bootindex", "/namespace@1,0", - DEVICE(obj)); -} - static const TypeInfo nvme_info = { .name = TYPE_NVME_DEVICE, .parent = TYPE_NVME_STATE, .class_init = nvme_class_init, .instance_size = sizeof(NvmeCtrl), - .instance_init = nvme_instance_init, - .class_init = nvme_class_init, +}; + +static void nvme_legacy_instance_init(Object *obj) +{ + NvmeCtrlLegacyDevice *ctrl = NVME_DEVICE_LEGACY(obj); + + device_add_bootindex_property(obj, &ctrl->namespace.blkconf.bootindex, + "bootindex", "/namespace@1,0", + DEVICE(obj)); +} + +static void nvme_legacy_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); + + pc->realize = nvme_legacy_realize; + + device_class_set_props(dc, nvme_legacy_props); +} + +static const TypeInfo nvme_legacy_info = { + .name = TYPE_NVME_DEVICE_LEGACY, + .parent = TYPE_NVME_STATE, + .class_init = nvme_legacy_class_init, + .instance_size = sizeof(NvmeCtrlLegacyDevice), + .instance_init = nvme_legacy_instance_init, }; static const TypeInfo nvme_bus_info = { @@ -6780,11 +6846,12 @@ static const TypeInfo nvme_bus_info = { .instance_size = sizeof(NvmeBus), }; -static void nvme_register_types(void) +static void register_types(void) { type_register_static(&nvme_state_info); type_register_static(&nvme_info); + type_register_static(&nvme_legacy_info); type_register_static(&nvme_bus_info); } -type_init(nvme_register_types) +type_init(register_types) diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 757a90b58ea8..90fc8d810ae0 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -262,7 +262,7 @@ static void nvme_nsdev_realize(DeviceState *dev, Error **errp) NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev); NvmeNamespace *ns = NULL; BusState *s = qdev_get_parent_bus(dev); - NvmeCtrl *ctrl = NVME_DEVICE(s->parent); + NvmeCtrlLegacyDevice *ctrl = NVME_DEVICE_LEGACY(s->parent); NvmeState *n = NVME_STATE(ctrl); NvmeSubsystem *subsys = n->subsys; uint32_t nsid = nsdev->params.nsid; diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 5e516f8fb377..613aaab3ccd2 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -38,9 +38,12 @@ typedef struct NvmeNamespace NvmeNamespace; #define TYPE_NVME_STATE "nvme-state" OBJECT_DECLARE_SIMPLE_TYPE(NvmeState, NVME_STATE) -#define TYPE_NVME_DEVICE "nvme" +#define TYPE_NVME_DEVICE "x-nvme-ctrl" OBJECT_DECLARE_SIMPLE_TYPE(NvmeCtrl, NVME_DEVICE) +#define TYPE_NVME_DEVICE_LEGACY "nvme" +OBJECT_DECLARE_SIMPLE_TYPE(NvmeCtrlLegacyDevice, NVME_DEVICE_LEGACY) + #define TYPE_NVME_BUS "nvme-bus" OBJECT_DECLARE_SIMPLE_TYPE(NvmeBus, NVME_BUS) @@ -400,6 +403,10 @@ typedef struct NvmeState { typedef struct NvmeCtrl { NvmeState parent_obj; +} NvmeCtrl; + +typedef struct NvmeCtrlLegacyDevice { + NvmeState parent_obj; NvmeBus bus; @@ -407,7 +414,7 @@ typedef struct NvmeCtrl { NvmeNamespaceDevice namespace; NvmeSubsystemDevice *subsys_dev; -} NvmeCtrl; +} NvmeCtrlLegacyDevice; static inline NvmeNamespace *nvme_ns(NvmeState *n, uint32_t nsid) { diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c index e4dcd8fd20a5..48700ca06aa6 100644 --- a/hw/nvme/subsys.c +++ b/hw/nvme/subsys.c @@ -16,20 +16,29 @@ int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeState *n, Error **errp) { - int cntlid, nsid; + int nsid; - for (cntlid = 0; cntlid < ARRAY_SIZE(subsys->ctrls); cntlid++) { - if (!subsys->ctrls[cntlid]) { - break; + if (!n->cntlid) { + int cntlid; + + for (cntlid = 0; cntlid < ARRAY_SIZE(subsys->ctrls); cntlid++) { + if (!subsys->ctrls[cntlid]) { + break; + } } - } - if (cntlid == ARRAY_SIZE(subsys->ctrls)) { - error_setg(errp, "no more free controller id"); + if (cntlid == ARRAY_SIZE(subsys->ctrls)) { + error_setg(errp, "no more free controller identifiers"); + return -1; + } + + n->cntlid = cntlid; + } else if (subsys->ctrls[n->cntlid]) { + error_setg(errp, "controller identifier already assigned"); return -1; } - subsys->ctrls[cntlid] = n; + subsys->ctrls[n->cntlid] = n; for (nsid = 1; nsid < ARRAY_SIZE(subsys->namespaces); nsid++) { NvmeNamespace *ns = subsys->namespaces[nsid]; @@ -38,7 +47,7 @@ int nvme_subsys_register_ctrl(NvmeSubsystem *subsys, NvmeState *n, } } - return cntlid; + return 0; } void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeState *n) From patchwork Mon Sep 27 05:17:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Jensen X-Patchwork-Id: 1533200 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=irrelevant.dk header.i=@irrelevant.dk header.a=rsa-sha256 header.s=fm1 header.b=YTUJ4pUu; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm3 header.b=ltOMuFaz; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HHs3j4xQpz9tD5 for ; Mon, 27 Sep 2021 15:42:40 +1000 (AEST) Received: from localhost ([::1]:33756 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mUjPQ-0003s7-Kb for incoming@patchwork.ozlabs.org; Mon, 27 Sep 2021 01:42:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34428) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj38-0004hZ-5g; Mon, 27 Sep 2021 01:19:36 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:57839) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mUj36-0000fX-C6; Mon, 27 Sep 2021 01:19:33 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailnew.west.internal (Postfix) with ESMTP id D13402B0121F; Mon, 27 Sep 2021 01:19:09 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute1.internal (MEProxy); Mon, 27 Sep 2021 01:19:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm1; bh=Xz3ePiKpJuH2U fpD1osQTpvITJuBpO640F6xyvxELF4=; b=YTUJ4pUu7Ky8H25J2VNHtaUdkZb2T AwM6tPdwG5m2vGUOwPT3hSn55a3cN7dqG/EREkM/981Lud2c7lvuPoQHVdryk3xm RDKf4QmIJqJsVGEcyVbAVY+E/3bxb1OLZDqLKtGIwjJim/VDpHPLwc3Hc1rx+Lnn L4BT417tIWu6Vu/JXLDTR8Mn9d0RgqPAggZhOvhHDRx+MjoH3q0XEz+qZUSptNR6 D6td9dIpKXnnW/sklmpAAg0ULH2+r2tQqvcfJn/TPcQHy59dIm3ifJHNVQiwOPqu yfTpXJ0q7bIqjhY3Ub14k0WsHHX3RRY6iDq3lOO25GXxfymyy9xLq2k2A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=Xz3ePiKpJuH2UfpD1osQTpvITJuBpO640F6xyvxELF4=; b=ltOMuFaz amP9lgJgl3niLwTPWiysLcKAR7tLMZ/HsWQ5RjEjM36LHloMh9vYVxagVLb8fpLL Wq2PNnLk5cAtpmMJRIHgVK6OP5w7u26DGMExZTSdjOPKHrkFPFRMQCukCmieJOEu AOhUfMrjA22Yba4Ro1b11rgoNOZ7vrNFOK58cNilf0PLMsNiKPrkXAqNfOtAg5yT TcAMF6SE9BCpSBmZkbBjRmo7rqgCbVG5VCS45Sw0AYrqN+msdUtvsLnuompeGkre Zz2XJzwMrN6aQlUu8RoFr2xFHY7U3IE8WGjh+UdtvrbmbxdRRbMN/q3IThiOlKuW DwGfFde2sjyEqA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvtddrudejjedgleefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefmlhgruhhs ucflvghnshgvnhcuoehithhssehirhhrvghlvghvrghnthdrughkqeenucggtffrrghtth gvrhhnpeeuleetgeeiuefhgfekfefgveejiefgteekiedtgfdtieefhfdthfefueffvefg keenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpehith hssehirhhrvghlvghvrghnthdrughk X-ME-Proxy: Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Sep 2021 01:19:07 -0400 (EDT) From: Klaus Jensen To: qemu-devel@nongnu.org Subject: [PATCH RFC v2 16/16] docs: add documentation for experimental nvme emulation Date: Mon, 27 Sep 2021 07:17:59 +0200 Message-Id: <20210927051759.447305-17-its@irrelevant.dk> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927051759.447305-1-its@irrelevant.dk> References: <20210927051759.447305-1-its@irrelevant.dk> MIME-Version: 1.0 Received-SPF: pass client-ip=64.147.123.17; envelope-from=its@irrelevant.dk; helo=wnew3-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, 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 Zheng , Kevin Wolf , =?utf-8?q?Dan?= =?utf-8?q?iel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , qemu-block@nongnu.org, =?utf-8?q?Phi?= =?utf-8?q?lippe_Mathieu-Daud=C3=A9?= , Markus Armbruster , Klaus Jensen , Hanna Reitz , Hannes Reinecke , Stefan Hajnoczi , Klaus Jensen , Keith Busch , Paolo Bonzini , Eric Blake Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Klaus Jensen Signed-off-by: Klaus Jensen --- docs/system/device-emulation.rst | 1 + docs/system/devices/nvme-experimental.rst | 107 ++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 docs/system/devices/nvme-experimental.rst diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst index 7afcfd8064ae..9a4e08e4ea44 100644 --- a/docs/system/device-emulation.rst +++ b/docs/system/device-emulation.rst @@ -85,6 +85,7 @@ Emulated Devices devices/ivshmem.rst devices/net.rst devices/nvme.rst + devices/nvme-experimental.rst devices/usb.rst devices/vhost-user.rst devices/virtio-pmem.rst diff --git a/docs/system/devices/nvme-experimental.rst b/docs/system/devices/nvme-experimental.rst new file mode 100644 index 000000000000..d3b94dc3ef59 --- /dev/null +++ b/docs/system/devices/nvme-experimental.rst @@ -0,0 +1,107 @@ +=========================== +Experimental NVMe Emulation +=========================== + +QEMU offers experimental NVMe emulation through the ``x-nvme-ctrl`` device and +the ``x-nvme-subsystem`` and ``x-nvme-ns-{nvm,zoned}`` objects. + + +Adding NVMe Devices +=================== + +Controller Emulation +-------------------- + +The QEMU emulated NVMe controller implements version 1.4 of the NVM Express +specification. All mandatory features are implement with a couple of exceptions +and limitations: + + * Accounting numbers in the SMART/Health log page are reset when the device + is power cycled. + * Interrupt Coalescing is not supported and is disabled by default. + +The simplest way to attach an NVMe controller on the QEMU PCI bus is to add the +following parameters: + +.. code-block:: console + + -object x-nvme-subsystem,id=nvme-subsys-0 + -device x-nvme-ctrl,subsys=nvme-subsys-0 + +There are a number of optional general parameters for the ``x-nvme-ctrl`` +device. Some are mentioned here, but see ``-device x-nvme-ctrl,help`` to list +all possible parameters. + +``max-ioqpairs=UINT32`` (default: ``64``) + Set the maximum number of allowed I/O queue pairs. + +``msix-vectors=UINT16`` (default: ``65``) + The number of MSI-X vectors that the device should support. + +``mdts=UINT8`` (default: ``7``) + Set the Maximum Data Transfer Size of the device. + + +Additional Namespaces +--------------------- + +The invocation sketched above does not add any namespaces to the subsystem. To +add these, add ``x-nvme-ns-NSTYPE`` (where ``NSTYPE`` is either ``nvm`` or +``zoned``) objects with attached blockdevs and a reference to the subsystem: + +.. code-block:: console + + -blockdev file,node-name=blk-file-nvm-1,filename=nvm-1.img + -blockdev raw,node-name=blk-nvm-1,file=blk-file-nvm-1 + -object x-nvme-ns-nvm,id=nvm-1,blockdev=blk-nvm-1,subsys=nvme-subsys-0 + +There are a number of optional parameters available (common to both the ``nvm`` +and ``zoned`` namespace types): + +``nsid`` (default: ``"auto"``) + Explicitly set the namespace identifier. If left at the default, the + subsystem will allocate the next available identifier. + +``uuid`` (default: ``"auto"``) + Set the UUID of the namespace. This will be reported as a "Namespace UUID" + descriptor in the Namespace Identification Descriptor List. If left at the + default, a UUID will be generated. + +``eui64`` (default: ``"auto"``) + Set the EUI-64 of the namespace. This will be reported as a "IEEE Extended + Unique Identifier" descriptor in the Namespace Identification Descriptor + List. If left at the default, an identifier prefixed with the QEMU IEEE OUI + (``52:54:00``) will be generated. + +``lba-size`` (default: ``4096``) + Set the logical block size. + +Namespaces support LBA metadata in the form separate metadata (``MPTR``-based) +and extended LBAs. + +``metadata-size`` (default: ``0``) + Defines the number of metadata bytes per LBA. + +``extended-lba`` (default: ``off/false``) + Set to ``on/true`` to enable extended LBAs. + +With metadata configured, namespaces support DIF- and DIX-based protection +information (depending on ``extended-lba``). + +``pi-type`` (default: ``"none"``) + Enable protection information of the specified type (type ``"type1"``, + ``"type2"`` or ``"type3"``). + +``pi-first`` (default: ``off/false``) + Controls the location of the protection information within the metadata. Set + to ``on/true`` to transfer protection information as the first eight bytes of + metadata. Otherwise, the protection information is transferred as the last + eight bytes. + +The ``zoned`` namespace type has additional parameters: + +``zone-size`` (default: ``4096``) + The number of LBAs in a zone. + +``zone-capacity`` (default: ``4096``) + The number of writable LBAs in a zone.