mirror of https://github.com/xemu-project/xemu.git
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_BLOCK_PROPERTIES(NvmeNamespace, blkconf),
|
||||||
DEFINE_PROP_LINK("subsys", NvmeNamespace, subsys, TYPE_NVME_SUBSYS,
|
DEFINE_PROP_LINK("subsys", NvmeNamespace, subsys, TYPE_NVME_SUBSYS,
|
||||||
NvmeSubsystem *),
|
NvmeSubsystem *),
|
||||||
|
DEFINE_PROP_BOOL("detached", NvmeNamespace, params.detached, false),
|
||||||
DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0),
|
DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0),
|
||||||
DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid),
|
DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid),
|
||||||
DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128),
|
DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128),
|
||||||
|
|
|
@ -26,6 +26,7 @@ typedef struct NvmeZone {
|
||||||
} NvmeZone;
|
} NvmeZone;
|
||||||
|
|
||||||
typedef struct NvmeNamespaceParams {
|
typedef struct NvmeNamespaceParams {
|
||||||
|
bool detached;
|
||||||
uint32_t nsid;
|
uint32_t nsid;
|
||||||
QemuUUID uuid;
|
QemuUUID uuid;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ typedef struct NvmeSubsystem {
|
||||||
uint8_t subnqn[256];
|
uint8_t subnqn[256];
|
||||||
|
|
||||||
NvmeCtrl *ctrls[NVME_SUBSYS_MAX_CTRLS];
|
NvmeCtrl *ctrls[NVME_SUBSYS_MAX_CTRLS];
|
||||||
|
/* Allocated namespaces for this subsystem */
|
||||||
NvmeNamespace *namespaces[NVME_SUBSYS_MAX_NAMESPACES];
|
NvmeNamespace *namespaces[NVME_SUBSYS_MAX_NAMESPACES];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
* subsys=<subsys_id>
|
* subsys=<subsys_id>
|
||||||
* -device nvme-ns,drive=<drive_id>,bus=<bus_name>,nsid=<nsid>,\
|
* -device nvme-ns,drive=<drive_id>,bus=<bus_name>,nsid=<nsid>,\
|
||||||
* zoned=<true|false[optional]>, \
|
* 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
|
* 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
|
* 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
|
* subsystem. Otherwise, `bus` must be given to attach this namespace to a
|
||||||
* specific controller as a non-shared namespace.
|
* 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.
|
* Setting `zoned` to true selects Zoned Command Set at the namespace.
|
||||||
* In this case, the following namespace properties are available to configure
|
* In this case, the following namespace properties are available to configure
|
||||||
* zoned operation:
|
* zoned operation:
|
||||||
|
@ -4655,6 +4662,20 @@ static void nvme_init_state(NvmeCtrl *n)
|
||||||
n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1);
|
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)
|
int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp)
|
||||||
{
|
{
|
||||||
uint32_t nsid = nvme_nsid(ns);
|
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);
|
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,
|
n->dmrsl = MIN_NON_ZERO(n->dmrsl,
|
||||||
BDRV_REQUEST_MAX_BYTES / nvme_l2b(ns, 1));
|
BDRV_REQUEST_MAX_BYTES / nvme_l2b(ns, 1));
|
||||||
|
|
|
@ -189,6 +189,10 @@ typedef struct NvmeCtrl {
|
||||||
NvmeSubsystem *subsys;
|
NvmeSubsystem *subsys;
|
||||||
|
|
||||||
NvmeNamespace namespace;
|
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];
|
NvmeNamespace *namespaces[NVME_MAX_NAMESPACES];
|
||||||
NvmeSQueue **sq;
|
NvmeSQueue **sq;
|
||||||
NvmeCQueue **cq;
|
NvmeCQueue **cq;
|
||||||
|
@ -207,6 +211,24 @@ static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
|
||||||
return n->namespaces[nsid - 1];
|
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)
|
static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
|
||||||
{
|
{
|
||||||
NvmeSQueue *sq = req->sq;
|
NvmeSQueue *sq = req->sq;
|
||||||
|
|
Loading…
Reference in New Issue