[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