hw/block/nvme: support allocated namespace type
From NVMe spec 1.4b "6.1.5. NSID and Namespace Relationships" defines valid namespace types: - Unallocated: Not exists in the NVMe subsystem - Allocated: Exists in the NVMe subsystem - Inactive: Not attached to the controller - Active: Attached to the controller This patch added support for allocated, but not attached namespace type: !nvme_ns(n, nsid) && nvme_subsys_ns(n->subsys, nsid) nvme_ns() returns attached namespace instance of the given controller and nvme_subsys_ns() returns allocated namespace instance in the subsystem. Signed-off-by: Minwoo Im <minwoo.im.dev@gmail.com> Reviewed-by: Keith Busch <kbusch@kernel.org> Reviewed-by: Klaus Jensen <k.jensen@samsung.com> Tested-by: Klaus Jensen <k.jensen@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
This commit is contained in:
parent
92cad003c1
commit
94d8d6d167
@ -34,4 +34,17 @@ typedef struct NvmeSubsystem {
|
||||
int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp);
|
||||
int nvme_subsys_register_ns(NvmeNamespace *ns, Error **errp);
|
||||
|
||||
/*
|
||||
* Return allocated namespace of the specified nsid in the subsystem.
|
||||
*/
|
||||
static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
|
||||
uint32_t nsid)
|
||||
{
|
||||
if (!subsys) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return subsys->namespaces[nsid];
|
||||
}
|
||||
|
||||
#endif /* NVME_SUBSYS_H */
|
||||
|
@ -3262,7 +3262,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)
|
||||
static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req, bool active)
|
||||
{
|
||||
NvmeNamespace *ns;
|
||||
NvmeIdentify *c = (NvmeIdentify *)&req->cmd;
|
||||
@ -3276,7 +3276,14 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req)
|
||||
|
||||
ns = nvme_ns(n, nsid);
|
||||
if (unlikely(!ns)) {
|
||||
return nvme_rpt_empty_id_struct(n, req);
|
||||
if (!active) {
|
||||
ns = nvme_subsys_ns(n->subsys, nsid);
|
||||
if (!ns) {
|
||||
return nvme_rpt_empty_id_struct(n, req);
|
||||
}
|
||||
} else {
|
||||
return nvme_rpt_empty_id_struct(n, req);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->csi == NVME_CSI_NVM && nvme_csi_has_nvm_support(ns)) {
|
||||
@ -3286,7 +3293,8 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeRequest *req)
|
||||
return NVME_INVALID_CMD_SET | NVME_DNR;
|
||||
}
|
||||
|
||||
static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req)
|
||||
static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req,
|
||||
bool active)
|
||||
{
|
||||
NvmeNamespace *ns;
|
||||
NvmeIdentify *c = (NvmeIdentify *)&req->cmd;
|
||||
@ -3300,7 +3308,14 @@ static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req)
|
||||
|
||||
ns = nvme_ns(n, nsid);
|
||||
if (unlikely(!ns)) {
|
||||
return nvme_rpt_empty_id_struct(n, req);
|
||||
if (!active) {
|
||||
ns = nvme_subsys_ns(n->subsys, nsid);
|
||||
if (!ns) {
|
||||
return nvme_rpt_empty_id_struct(n, req);
|
||||
}
|
||||
} else {
|
||||
return nvme_rpt_empty_id_struct(n, req);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->csi == NVME_CSI_NVM && nvme_csi_has_nvm_support(ns)) {
|
||||
@ -3313,7 +3328,8 @@ 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(NvmeCtrl *n, NvmeRequest *req,
|
||||
bool active)
|
||||
{
|
||||
NvmeNamespace *ns;
|
||||
NvmeIdentify *c = (NvmeIdentify *)&req->cmd;
|
||||
@ -3338,7 +3354,14 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req)
|
||||
for (i = 1; i <= n->num_namespaces; i++) {
|
||||
ns = nvme_ns(n, i);
|
||||
if (!ns) {
|
||||
continue;
|
||||
if (!active) {
|
||||
ns = nvme_subsys_ns(n->subsys, i);
|
||||
if (!ns) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ns->params.nsid <= min_nsid) {
|
||||
continue;
|
||||
@ -3352,7 +3375,8 @@ 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(NvmeCtrl *n, NvmeRequest *req,
|
||||
bool active)
|
||||
{
|
||||
NvmeNamespace *ns;
|
||||
NvmeIdentify *c = (NvmeIdentify *)&req->cmd;
|
||||
@ -3378,7 +3402,14 @@ static uint16_t nvme_identify_nslist_csi(NvmeCtrl *n, NvmeRequest *req)
|
||||
for (i = 1; i <= n->num_namespaces; i++) {
|
||||
ns = nvme_ns(n, i);
|
||||
if (!ns) {
|
||||
continue;
|
||||
if (!active) {
|
||||
ns = nvme_subsys_ns(n->subsys, i);
|
||||
if (!ns) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ns->params.nsid <= min_nsid || c->csi != ns->csi) {
|
||||
continue;
|
||||
@ -3461,25 +3492,25 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req)
|
||||
|
||||
switch (c->cns) {
|
||||
case NVME_ID_CNS_NS:
|
||||
/* fall through */
|
||||
return nvme_identify_ns(n, req, true);
|
||||
case NVME_ID_CNS_NS_PRESENT:
|
||||
return nvme_identify_ns(n, req);
|
||||
return nvme_identify_ns(n, req, false);
|
||||
case NVME_ID_CNS_CS_NS:
|
||||
/* fall through */
|
||||
return nvme_identify_ns_csi(n, req, true);
|
||||
case NVME_ID_CNS_CS_NS_PRESENT:
|
||||
return nvme_identify_ns_csi(n, req);
|
||||
return nvme_identify_ns_csi(n, req, false);
|
||||
case NVME_ID_CNS_CTRL:
|
||||
return nvme_identify_ctrl(n, req);
|
||||
case NVME_ID_CNS_CS_CTRL:
|
||||
return nvme_identify_ctrl_csi(n, req);
|
||||
case NVME_ID_CNS_NS_ACTIVE_LIST:
|
||||
/* fall through */
|
||||
return nvme_identify_nslist(n, req, true);
|
||||
case NVME_ID_CNS_NS_PRESENT_LIST:
|
||||
return nvme_identify_nslist(n, req);
|
||||
return nvme_identify_nslist(n, req, false);
|
||||
case NVME_ID_CNS_CS_NS_ACTIVE_LIST:
|
||||
/* fall through */
|
||||
return nvme_identify_nslist_csi(n, req, true);
|
||||
case NVME_ID_CNS_CS_NS_PRESENT_LIST:
|
||||
return nvme_identify_nslist_csi(n, req);
|
||||
return nvme_identify_nslist_csi(n, req, false);
|
||||
case NVME_ID_CNS_NS_DESCR_LIST:
|
||||
return nvme_identify_ns_descr_list(n, req);
|
||||
case NVME_ID_CNS_IO_COMMAND_SET:
|
||||
|
Loading…
Reference in New Issue
Block a user