[PATCH] nvme-multipath: report "none" iopolicy for discovery subsystems
Martin George
martinus.gpy at gmail.com
Wed Sep 30 08:36:58 PDT 2026
A discovery subsystem never exposes namespaces, so it has no multipath
head and no I/O paths to select between. Nevertheless the per-subsystem
iopolicy attribute is registered unconditionally and reads back the
driver-wide default which is 'numa' for the discovery subsystems too.
This can be misleading as it suggests a path selection policy is in
effect when nothing is ever selected, and writing the attribute silently
mutates state that can never be used.
Report "none" instead for a discovery subsystem, and reject writes
with -EOPNOTSUPP. Report "none" from iopolicies as well, so that the
value read from iopolicy always remains a member of the set advertised
by iopolicies; otherwise userspace validating the current policy
against the available ones would reject its own subsystem.
And while at it, document iopolicies too, which was not covered when it
was added previously.
Signed-off-by: Martin George <marting at netapp.com>
---
Documentation/ABI/stable/sysfs-nvme | 15 +++++++++++++++
drivers/nvme/host/multipath.c | 12 ++++++++++++
2 files changed, 27 insertions(+)
diff --git a/Documentation/ABI/stable/sysfs-nvme b/Documentation/ABI/stable/sysfs-nvme
index a0bb88ca1694..67795a2dd905 100644
--- a/Documentation/ABI/stable/sysfs-nvme
+++ b/Documentation/ABI/stable/sysfs-nvme
@@ -465,6 +465,21 @@ Description:
selections. Only available when CONFIG_NVME_MULTIPATH is
enabled.
+ A discovery subsystem has no namespaces and hence no I/O
+ paths to select from: reading returns "none" and writing
+ fails with EOPNOTSUPP.
+
+What: /sys/class/nvme-subsystem/nvme-subsysX/iopolicies
+Date: September 2026
+KernelVersion: 7.4
+Contact: Laurence Oberman <loberman at redhat.com>
+Description:
+ Shows the I/O path selection policies that may be written
+ to the iopolicy attribute of this subsystem, separated by
+ spaces: "numa round-robin queue-depth". A discovery
+ subsystem accepts no policy at all and reports "none".
+ Only available when CONFIG_NVME_MULTIPATH is enabled.
+
What: /sys/class/nvme-subsystem/nvme-subsysX/subsystype
Date: September 2021
KernelVersion: 5.16
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 11871f5f18c2..56ee25b448ad 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -1054,6 +1054,10 @@ static ssize_t nvme_subsys_iopolicy_show(struct device *dev,
struct nvme_subsystem *subsys =
container_of(dev, struct nvme_subsystem, dev);
+ /* A discovery subsystem has no namespaces and hence no I/O paths */
+ if (subsys->subtype == NVME_NQN_DISC)
+ return sysfs_emit(buf, "none\n");
+
return sysfs_emit(buf, "%s\n",
nvme_iopolicy_names[READ_ONCE(subsys->iopolicy)]);
}
@@ -1088,6 +1092,9 @@ static ssize_t nvme_subsys_iopolicy_store(struct device *dev,
container_of(dev, struct nvme_subsystem, dev);
int policy;
+ if (subsys->subtype == NVME_NQN_DISC)
+ return -EOPNOTSUPP;
+
policy = nvme_iopolicy_parse(buf);
if (policy < 0)
return policy;
@@ -1101,8 +1108,13 @@ SUBSYS_ATTR_RW(iopolicy, S_IRUGO | S_IWUSR,
static ssize_t iopolicies_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct nvme_subsystem *subsys =
+ container_of(dev, struct nvme_subsystem, dev);
int i, len = 0;
+ if (subsys->subtype == NVME_NQN_DISC)
+ return sysfs_emit(buf, "none\n");
+
for (i = 0; i < ARRAY_SIZE(nvme_iopolicy_names); i++)
len += sysfs_emit_at(buf, len, "%s%s", i ? " " : "",
nvme_iopolicy_names[i]);
--
2.43.0
More information about the Linux-nvme
mailing list