@@ -5063,7 +5063,8 @@ static uint16_t nvme_endgrp_info(NvmeCtrl *n,
uint8_t rae, uint32_t buf_len,
}
for (i = 1; i <= NVME_MAX_NAMESPACES; i++) {
- NvmeNamespace *ns = nvme_subsys_ns(n->subsys, i);
+ NvmeNamespace *ns = nvme_subsys_ns(n, i);
+
if (!ns) {
continue;
}
@@ -5700,7 +5701,7 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n,
NvmeRequest *req, bool active)
ns = nvme_ns(n, nsid);
if (unlikely(!ns)) {
if (!active) {
- ns = nvme_subsys_ns(n->subsys, nsid);
+ ns = nvme_subsys_ns(n, nsid);
if (!ns) {
[root@localhost qemu-subsys]# git log -p
f4b9f10a80c30f1d6b9850d476eb8226bda3f553 > /tmp/p
^C
[root@localhost qemu-subsys]# vi /tmp/p
[root@localhost qemu-subsys]# cat /tmp/p
commit f4b9f10a80c30f1d6b9850d476eb8226bda3f553
Author: Alan Adamson <alan.adamson@oracle.com>
Date: 2025-04-03 14:10:30 -0400
subsys multi controller shared fix
@@ -5063,7 +5063,8 @@ static uint16_t nvme_endgrp_info(NvmeCtrl *n,
uint8_t rae, uint32_t buf_len,
}
for (i = 1; i <= NVME_MAX_NAMESPACES; i++) {
- NvmeNamespace *ns = nvme_subsys_ns(n->subsys, i);
+ NvmeNamespace *ns = nvme_subsys_ns(n, i);
+
if (!ns) {
continue;
}
@@ -5700,7 +5701,7 @@ static uint16_t nvme_identify_ns(NvmeCtrl *n,
NvmeRequest *req, bool active)
ns = nvme_ns(n, nsid);
if (unlikely(!ns)) {
if (!active) {
- ns = nvme_subsys_ns(n->subsys, nsid);
+ ns = nvme_subsys_ns(n, nsid);
if (!ns) {
return nvme_rpt_empty_id_struct(n, req);
}
@@ -5739,7 +5740,7 @@ static uint16_t nvme_identify_ctrl_list(NvmeCtrl
*n, NvmeRequest *req,
return NVME_INVALID_FIELD | NVME_DNR;
}
- ns = nvme_subsys_ns(n->subsys, nsid);
+ ns = nvme_subsys_ns(n, nsid);
if (!ns) {
return NVME_INVALID_FIELD | NVME_DNR;
}
@@ -5809,7 +5810,7 @@ static uint16_t nvme_identify_ns_ind(NvmeCtrl *n,
NvmeRequest *req, bool alloc)
ns = nvme_ns(n, nsid);
if (unlikely(!ns)) {
if (alloc) {
- ns = nvme_subsys_ns(n->subsys, nsid);
+ ns = nvme_subsys_ns(n, nsid);
if (!ns) {
return nvme_rpt_empty_id_struct(n, req);
}
@@ -5837,7 +5838,7 @@ static uint16_t nvme_identify_ns_csi(NvmeCtrl *n,
NvmeRequest *req,
ns = nvme_ns(n, nsid);
if (unlikely(!ns)) {
if (!active) {
- ns = nvme_subsys_ns(n->subsys, nsid);
+ ns = nvme_subsys_ns(n, nsid);
if (!ns) {
return nvme_rpt_empty_id_struct(n, req);
}
@@ -5884,7 +5885,7 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n,
NvmeRequest *req,
ns = nvme_ns(n, i);
if (!ns) {
if (!active) {
- ns = nvme_subsys_ns(n->subsys, i);
+ ns = nvme_subsys_ns(n, i);
if (!ns) {
continue;
}
@@ -5932,7 +5933,7 @@ static uint16_t nvme_identify_nslist_csi(NvmeCtrl
*n, NvmeRequest *req,
ns = nvme_ns(n, i);
if (!ns) {
if (!active) {
- ns = nvme_subsys_ns(n->subsys, i);
+ ns = nvme_subsys_ns(n, i);
if (!ns) {
continue;
}
@@ -6793,7 +6794,7 @@ static uint16_t nvme_ns_attachment(NvmeCtrl *n,
NvmeRequest *req)
return NVME_INVALID_NSID | NVME_DNR;
}
- ns = nvme_subsys_ns(n->subsys, nsid);
+ ns = nvme_subsys_ns(n, nsid);
if (!ns) {
return NVME_INVALID_FIELD | NVME_DNR;
}
@@ -7751,17 +7752,23 @@ static int nvme_start_ctrl(NvmeCtrl *n)
nvme_set_timestamp(n, 0ULL);
- /* verify that the command sets of attached namespaces are supported */
- for (int i = 1; i <= NVME_MAX_NAMESPACES; i++) {
- NvmeNamespace *ns = nvme_subsys_ns(n->subsys, i);
+ if (n->subsys) {
+ for (int i = 1; i <= NVME_MAX_NAMESPACES; i++) {
+ NvmeNamespace *ns = n->subsys->namespaces[i].namespace;
- if (ns && nvme_csi_supported(n, ns->csi) && !ns->params.detached) {
- if (!ns->attached || ns->params.shared) {
- nvme_attach_ns(n, ns);
+ if (!ns) {
+ continue;
}
+ if (!(n->subsys->namespaces[i].ctrl == n) && !ns->params.shared) {
+ continue;
+ }
+ if (nvme_csi_supported(n, ns->csi) && !ns->params.detached) {
+ if (!ns->attached || ns->params.shared) {
+ nvme_attach_ns(n, ns);
+ }
+ }
}
}
-
nvme_update_dsm_limits(n, NULL);
return 0;
@@ -8993,7 +9000,8 @@ static void nvme_realize(PCIDevice *pci_dev, Error
**errp)
return;
}
- n->subsys->namespaces[ns->params.nsid] = ns;
+ n->subsys->namespaces[ns->params.nsid].namespace = ns;
+ n->subsys->namespaces[ns->params.nsid].ctrl = n;
}
}
@@ -742,7 +742,7 @@ static void nvme_ns_realize(DeviceState *dev, Error
**errp)
if (!nsid) {
for (i = 1; i <= NVME_MAX_NAMESPACES; i++) {
- if (nvme_subsys_ns(subsys, i)) {
+ if (nvme_subsys_ns(n, i)) {
continue;
}
@@ -754,12 +754,13 @@ static void nvme_ns_realize(DeviceState *dev,
Error **errp)
error_setg(errp, "no free namespace id");
return;
}
- } else if (nvme_subsys_ns(subsys, nsid)) {
+ } else if (nvme_subsys_ns(n, nsid)) {
error_setg(errp, "namespace id '%d' already allocated", nsid);
return;
}
- subsys->namespaces[nsid] = ns;
+ subsys->namespaces[nsid].namespace = ns;
+ subsys->namespaces[nsid].ctrl = n;
ns->id_ns.endgid = cpu_to_le16(0x1);
ns->id_ns_ind.endgrpid = cpu_to_le16(0x1);
@@ -97,6 +97,11 @@ typedef struct NvmeEnduranceGroup {
} fdp;
} NvmeEnduranceGroup;
+typedef struct Namespaces {
+ NvmeCtrl *ctrl;
+ NvmeNamespace *namespace;
+} Namespaces;
+
typedef struct NvmeSubsystem {
DeviceState parent_obj;
NvmeBus bus;
@@ -104,7 +109,7 @@ typedef struct NvmeSubsystem {
char *serial;
NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS];
- NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1];
+ Namespaces namespaces[NVME_MAX_NAMESPACES + 1];
NvmeEnduranceGroup endgrp;
struct {
@@ -136,16 +141,6 @@ static inline NvmeCtrl
*nvme_subsys_ctrl(NvmeSubsystem *subsys,
return subsys->ctrls[cntlid];
}
-static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
- uint32_t nsid)
-{
- if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) {
- return NULL;
- }
-
- return subsys->namespaces[nsid];
-}
-
#define TYPE_NVME_NS "nvme-ns"
#define NVME_NS(obj) \
OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
@@ -711,6 +706,14 @@ static inline NvmeSecCtrlEntry
*nvme_sctrl_for_cntlid(NvmeCtrl *n,
return NULL;
}
+static inline NvmeNamespace *nvme_subsys_ns(NvmeCtrl *n, uint32_t nsid)
+{
+ if (!n->subsys || !nsid || nsid > NVME_MAX_NAMESPACES) {
+ return NULL;
+ }
+ return n->subsys->namespaces[nsid].namespace;
+}
+
void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns);
uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len,
NvmeTxDirection dir, NvmeRequest *req);
@@ -92,13 +92,19 @@ 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);
+ for (nsid = 1; nsid <= NVME_MAX_NAMESPACES; nsid++) {
+ NvmeNamespace *ns = subsys->namespaces[nsid].namespace;
+
+ if (!ns) {
+ continue;
+ }
+ if (!(subsys->namespaces[nsid].ctrl == n) && !ns->params.shared) {
+ continue;
}
+ if (ns->params.shared && !ns->params.detached) {
+ nvme_attach_ns(n, ns);
+ }
}
-
return cntlid;
}