[PATCHv2 2/3] nvme-multipath: rescan siblings on last path removal
Nilay Shroff
nilay at linux.ibm.com
Thu Feb 26 22:59:00 PST 2026
On 2/27/26 12:02 AM, Keith Busch wrote:
> 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 {
Should we consider reordering patches 2/3 and 3/3? It seems like this
patch depends on the changes introduced in 3/3.
Without the updates from 3/3, if delayed head removal is still in effect
and the NSIDs are recycled with mismatched identifiers, a forced rescan
of the sibling controller may still fail to instantiate the namespace.
In that case, requeueing the scan alone might not be sufficient.
Thanks,
--Nilay
More information about the Linux-nvme
mailing list