hw/block/nvme: support namespace detach
Given that now we have nvme-subsys device supported, we can manage namespace allocated, but not attached: detached. This patch introduced a parameter for nvme-ns device named 'detached'. This parameter indicates whether the given namespace device is detached from a entire NVMe subsystem('subsys' given case, shared namespace) or a controller('bus' given case, private namespace). - Allocated namespace 1) Shared ns in the subsystem 'subsys0': -device nvme-ns,id=ns1,drive=blknvme0,nsid=1,subsys=subsys0,detached=true 2) Private ns for the controller 'nvme0' of the subsystem 'subsys0': -device nvme-subsys,id=subsys0 -device nvme,serial=foo,id=nvme0,subsys=subsys0 -device nvme-ns,id=ns1,drive=blknvme0,nsid=1,bus=nvme0,detached=true 3) (Invalid case) Controller 'nvme0' has no subsystem to manage ns: -device nvme,serial=foo,id=nvme0 -device nvme-ns,id=ns1,drive=blknvme0,nsid=1,bus=nvme0,detached=true Signed-off-by: Minwoo Im <minwoo.im.dev@gmail.com> Reviewed-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
This commit is contained in:
parent
81d07f4ff5
commit
037953b5b2
@ -399,6 +399,7 @@ static Property nvme_ns_props[] = {
|
||||
DEFINE_BLOCK_PROPERTIES(NvmeNamespace, blkconf),
|
||||
DEFINE_PROP_LINK("subsys", NvmeNamespace, subsys, TYPE_NVME_SUBSYS,
|
||||
NvmeSubsystem *),
|
||||
DEFINE_PROP_BOOL("detached", NvmeNamespace, params.detached, false),
|
||||
DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0),
|
||||
DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid),
|
||||
DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128),
|
||||
|
@ -26,6 +26,7 @@ typedef struct NvmeZone {
|
||||
} NvmeZone;
|
||||
|
||||
typedef struct NvmeNamespaceParams {
|
||||
bool detached;
|
||||
uint32_t nsid;
|
||||
QemuUUID uuid;
|
||||
|
||||
|
@ -23,6 +23,7 @@ typedef struct NvmeSubsystem {
|
||||
uint8_t subnqn[256];
|
||||
|
||||
NvmeCtrl *ctrls[NVME_SUBSYS_MAX_CTRLS];
|
||||
/* Allocated namespaces for this subsystem */
|
||||
NvmeNamespace *namespaces[NVME_SUBSYS_MAX_NAMESPACES];
|
||||
|
||||
struct {
|
||||
|
@ -27,7 +27,7 @@
|
||||
* subsys=<subsys_id>
|
||||
* -device nvme-ns,drive=<drive_id>,bus=<bus_name>,nsid=<nsid>,\
|
||||
* zoned=<true|false[optional]>, \
|
||||
* subsys=<subsys_id>
|
||||
* subsys=<subsys_id>,detached=<true|false[optional]>
|
||||
*
|
||||
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
|
||||
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now. By default, the
|
||||
@ -91,6 +91,13 @@
|
||||
* subsystem. Otherwise, `bus` must be given to attach this namespace to a
|
||||
* specific controller as a non-shared namespace.
|
||||
*
|
||||
* - `detached`
|
||||
* This parameter is only valid together with the `subsys` parameter. If left
|
||||
* at the default value (`false/off`), the namespace will be attached to all
|
||||
* controllers in the NVMe subsystem at boot-up. If set to `true/on`, the
|
||||
* namespace will be be available in the subsystem not not attached to any
|
||||
* controllers.
|
||||
*
|
||||
* Setting `zoned` to true selects Zoned Command Set at the namespace.
|
||||
* In this case, the following namespace properties are available to configure
|
||||
* zoned operation:
|
||||
@ -4655,6 +4662,20 @@ static void nvme_init_state(NvmeCtrl *n)
|
||||
n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1);
|
||||
}
|
||||
|
||||
static int nvme_attach_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp)
|
||||
{
|
||||
if (nvme_ns_is_attached(n, ns)) {
|
||||
error_setg(errp,
|
||||
"namespace %d is already attached to controller %d",
|
||||
nvme_nsid(ns), n->cntlid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nvme_ns_attach(n, ns);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp)
|
||||
{
|
||||
uint32_t nsid = nvme_nsid(ns);
|
||||
@ -4686,7 +4707,23 @@ int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp)
|
||||
|
||||
trace_pci_nvme_register_namespace(nsid);
|
||||
|
||||
n->namespaces[nsid - 1] = ns;
|
||||
/*
|
||||
* If subsys is not given, namespae is always attached to the controller
|
||||
* because there's no subsystem to manage namespace allocation.
|
||||
*/
|
||||
if (!n->subsys) {
|
||||
if (ns->params.detached) {
|
||||
error_setg(errp,
|
||||
"detached needs nvme-subsys specified nvme or nvme-ns");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nvme_attach_namespace(n, ns, errp);
|
||||
} else {
|
||||
if (!ns->params.detached) {
|
||||
return nvme_attach_namespace(n, ns, errp);
|
||||
}
|
||||
}
|
||||
|
||||
n->dmrsl = MIN_NON_ZERO(n->dmrsl,
|
||||
BDRV_REQUEST_MAX_BYTES / nvme_l2b(ns, 1));
|
||||
|
@ -189,6 +189,10 @@ typedef struct NvmeCtrl {
|
||||
NvmeSubsystem *subsys;
|
||||
|
||||
NvmeNamespace namespace;
|
||||
/*
|
||||
* Attached namespaces to this controller. If subsys is not given, all
|
||||
* namespaces in this list will always be attached.
|
||||
*/
|
||||
NvmeNamespace *namespaces[NVME_MAX_NAMESPACES];
|
||||
NvmeSQueue **sq;
|
||||
NvmeCQueue **cq;
|
||||
@ -207,6 +211,24 @@ static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
|
||||
return n->namespaces[nsid - 1];
|
||||
}
|
||||
|
||||
static inline bool nvme_ns_is_attached(NvmeCtrl *n, NvmeNamespace *ns)
|
||||
{
|
||||
int nsid;
|
||||
|
||||
for (nsid = 1; nsid <= n->num_namespaces; nsid++) {
|
||||
if (nvme_ns(n, nsid) == ns) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void nvme_ns_attach(NvmeCtrl *n, NvmeNamespace *ns)
|
||||
{
|
||||
n->namespaces[nvme_nsid(ns) - 1] = ns;
|
||||
}
|
||||
|
||||
static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
|
||||
{
|
||||
NvmeSQueue *sq = req->sq;
|
||||
|
Loading…
Reference in New Issue
Block a user