2021-01-24 05:54:45 +03:00
|
|
|
/*
|
|
|
|
* QEMU NVM Express Subsystem: nvme-subsys
|
|
|
|
*
|
|
|
|
* Copyright (c) 2021 Minwoo Im <minwoo.im.dev@gmail.com>
|
|
|
|
*
|
|
|
|
* This code is licensed under the GNU GPL v2. Refer COPYING.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef NVME_SUBSYS_H
|
|
|
|
#define NVME_SUBSYS_H
|
|
|
|
|
|
|
|
#define TYPE_NVME_SUBSYS "nvme-subsys"
|
|
|
|
#define NVME_SUBSYS(obj) \
|
|
|
|
OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS)
|
|
|
|
|
|
|
|
#define NVME_SUBSYS_MAX_CTRLS 32
|
hw/block/nvme: fix handling of private namespaces
Prior to this patch, if a private nvme-ns device (that is, a namespace
that is not linked to a subsystem) is wired up to an nvme-subsys linked
nvme controller device, the device fails to verify that the namespace id
is unique within the subsystem. NVM Express v1.4b, Section 6.1.6 ("NSID
and Namespace Usage") states that because the device supports Namespace
Management, "NSIDs *shall* be unique within the NVM subsystem".
Additionally, prior to this patch, private namespaces are not known to
the subsystem and the namespace is considered exclusive to the
controller with which it is initially wired up to. However, this is not
the definition of a private namespace; per Section 1.6.33 ("private
namespace"), a private namespace is just a namespace that does not
support multipath I/O or namespace sharing, which means "that it is only
able to be attached to one controller at a time".
Fix this by always allocating namespaces in the subsystem (if one is
linked to the controller), regardless of the shared/private status of
the namespace. Whether or not the namespace is shareable is controlled
by a new `shared` nvme-ns parameter.
Finally, this fix allows the nvme-ns `subsys` parameter to be removed,
since the `shared` parameter now serves the purpose of attaching the
namespace to all controllers in the subsystem upon device realization.
It is invalid to have an nvme-ns namespace device with a linked
subsystem without the parent nvme controller device also being linked to
one and since the nvme-ns devices will unconditionally be "attached" (in
QEMU terms that is) to an nvme controller device through an NvmeBus, the
nvme-ns namespace device can always get a reference to the subsystem of
the controller it is explicitly (using 'bus=' parameter) or implicitly
attaching to.
Fixes: e570768566b3 ("hw/block/nvme: support for shared namespace in subsystem")
Cc: Minwoo Im <minwoo.im.dev@gmail.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Minwoo Im <minwoo.im.dev@gmail.com>
2021-03-23 14:43:24 +03:00
|
|
|
#define NVME_MAX_NAMESPACES 256
|
2021-01-24 05:54:45 +03:00
|
|
|
|
|
|
|
typedef struct NvmeCtrl NvmeCtrl;
|
|
|
|
typedef struct NvmeNamespace NvmeNamespace;
|
|
|
|
typedef struct NvmeSubsystem {
|
|
|
|
DeviceState parent_obj;
|
|
|
|
uint8_t subnqn[256];
|
|
|
|
|
2021-01-24 05:54:48 +03:00
|
|
|
NvmeCtrl *ctrls[NVME_SUBSYS_MAX_CTRLS];
|
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>
2021-02-05 18:30:10 +03:00
|
|
|
/* Allocated namespaces for this subsystem */
|
hw/block/nvme: fix handling of private namespaces
Prior to this patch, if a private nvme-ns device (that is, a namespace
that is not linked to a subsystem) is wired up to an nvme-subsys linked
nvme controller device, the device fails to verify that the namespace id
is unique within the subsystem. NVM Express v1.4b, Section 6.1.6 ("NSID
and Namespace Usage") states that because the device supports Namespace
Management, "NSIDs *shall* be unique within the NVM subsystem".
Additionally, prior to this patch, private namespaces are not known to
the subsystem and the namespace is considered exclusive to the
controller with which it is initially wired up to. However, this is not
the definition of a private namespace; per Section 1.6.33 ("private
namespace"), a private namespace is just a namespace that does not
support multipath I/O or namespace sharing, which means "that it is only
able to be attached to one controller at a time".
Fix this by always allocating namespaces in the subsystem (if one is
linked to the controller), regardless of the shared/private status of
the namespace. Whether or not the namespace is shareable is controlled
by a new `shared` nvme-ns parameter.
Finally, this fix allows the nvme-ns `subsys` parameter to be removed,
since the `shared` parameter now serves the purpose of attaching the
namespace to all controllers in the subsystem upon device realization.
It is invalid to have an nvme-ns namespace device with a linked
subsystem without the parent nvme controller device also being linked to
one and since the nvme-ns devices will unconditionally be "attached" (in
QEMU terms that is) to an nvme controller device through an NvmeBus, the
nvme-ns namespace device can always get a reference to the subsystem of
the controller it is explicitly (using 'bus=' parameter) or implicitly
attaching to.
Fixes: e570768566b3 ("hw/block/nvme: support for shared namespace in subsystem")
Cc: Minwoo Im <minwoo.im.dev@gmail.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Reviewed-by: Minwoo Im <minwoo.im.dev@gmail.com>
2021-03-23 14:43:24 +03:00
|
|
|
NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1];
|
2021-01-24 05:54:48 +03:00
|
|
|
|
2021-01-24 05:54:45 +03:00
|
|
|
struct {
|
|
|
|
char *nqn;
|
|
|
|
} params;
|
|
|
|
} NvmeSubsystem;
|
|
|
|
|
2021-01-24 05:54:48 +03:00
|
|
|
int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp);
|
|
|
|
|
2021-02-06 06:18:09 +03:00
|
|
|
static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys,
|
|
|
|
uint32_t cntlid)
|
|
|
|
{
|
2021-04-07 08:16:14 +03:00
|
|
|
if (!subsys || cntlid >= NVME_SUBSYS_MAX_CTRLS) {
|
2021-02-06 06:18:09 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return subsys->ctrls[cntlid];
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:15:10 +03:00
|
|
|
/*
|
|
|
|
* Return allocated namespace of the specified nsid in the subsystem.
|
|
|
|
*/
|
|
|
|
static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
|
|
|
|
uint32_t nsid)
|
|
|
|
{
|
2021-04-07 08:07:43 +03:00
|
|
|
if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) {
|
2021-02-05 20:15:10 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return subsys->namespaces[nsid];
|
|
|
|
}
|
|
|
|
|
2021-01-24 05:54:45 +03:00
|
|
|
#endif /* NVME_SUBSYS_H */
|