[PATCHv2 2/3] nvme-multipath: rescan siblings on last path removal
Keith Busch
kbusch at meta.com
Thu Feb 26 10:32:15 PST 2026
From: Keith Busch <kbusch at kernel.org>
When a controller's scan removes the last path to a multipath namespace
head, sibling controllers in the same subsystem may need to rescan. A
concurrent scan on another controller could have encountered the stale
head with mismatched identifiers (e.g. from a recycled NSID) and failed
to set up the namespace. Without notification, the sibling won't retry
until the next AEN or explicit rescan.
After a scan that performed last-path removals, notify all controllers
in the subsystem to rescan by requeueing their scan work. This ensures
that recycled NSIDs are promptly discovered by sibling controllers.
Signed-off-by: Keith Busch <kbusch at kernel.org>
---
drivers/nvme/host/core.c | 19 ++++++++++++++++++-
drivers/nvme/host/nvme.h | 1 +
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 3de52f1d27234..5bb4b18511b7b 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -4262,8 +4262,10 @@ static void nvme_ns_remove(struct nvme_ns *ns)
mutex_unlock(&ns->ctrl->namespaces_lock);
synchronize_srcu(&ns->ctrl->srcu);
- if (last_path)
+ if (last_path) {
nvme_mpath_remove_disk(ns->head);
+ set_bit(NVME_CTRL_SCAN_REMOVED_NS, &ns->ctrl->flags);
+ }
nvme_put_ns(ns);
}
@@ -4530,6 +4532,21 @@ static void nvme_scan_work(struct work_struct *work)
}
mutex_unlock(&ctrl->scan_lock);
+ /*
+ * If the scan removed the last path to a namespace, notify all
+ * controllers in the subsystem to rescan. A controller that is
+ * concurrently scanning may have missed the namespace due to the
+ * stale head still occupying the NSID in the subsystem list.
+ */
+ if (test_and_clear_bit(NVME_CTRL_SCAN_REMOVED_NS, &ctrl->flags)) {
+ struct nvme_ctrl *tmp;
+
+ mutex_lock(&ctrl->subsys->lock);
+ list_for_each_entry(tmp, &ctrl->subsys->ctrls, subsys_entry)
+ nvme_queue_scan(tmp);
+ mutex_unlock(&ctrl->subsys->lock);
+ }
+
/* Requeue if we have missed AENs */
if (test_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events))
nvme_queue_scan(ctrl);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 9971045dbc05e..e73cc2e67ac51 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -329,6 +329,7 @@ enum nvme_ctrl_flags {
NVME_CTRL_SKIP_ID_CNS_CS = 4,
NVME_CTRL_DIRTY_CAPABILITY = 5,
NVME_CTRL_FROZEN = 6,
+ NVME_CTRL_SCAN_REMOVED_NS = 7,
};
struct nvme_ctrl {
--
2.47.3
More information about the Linux-nvme
mailing list