[PATCHv2 3/3] nvme: fix unmatched id's under delayed path deletion
Keith Busch
kbusch at meta.com
Thu Feb 26 10:32:16 PST 2026
From: Keith Busch <kbusch at kernel.org>
The NVMe controller is allowed to reuse an NSID for a new namespace after
deleting the previous namespace that had been using it. The delayed removal may
have the stale namespace head in the subsystem list pending the timer, which
would cause the scan to falsely report an ID mismatch error for the new
namespace. Flush the pending removal work and retry to resolve this.
Signed-off-by: Keith Busch <kbusch at kernel.org>
---
drivers/nvme/host/core.c | 18 ++++++++++++++++++
drivers/nvme/host/nvme.h | 8 ++++++++
2 files changed, 26 insertions(+)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 5bb4b18511b7b..906421047debd 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3968,6 +3968,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
{
struct nvme_ctrl *ctrl = ns->ctrl;
struct nvme_ns_head *head = NULL;
+ bool retried = false;
int ret;
ret = nvme_global_check_duplicate_ids(ctrl->subsys, &info->ids);
@@ -4008,6 +4009,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
ctrl->quirks |= NVME_QUIRK_BOGUS_NID;
}
+again:
mutex_lock(&ctrl->subsys->lock);
head = nvme_find_ns_head(ctrl, info->nsid);
if (!head) {
@@ -4033,6 +4035,22 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
goto out_put_ns_head;
}
if (!nvme_ns_ids_equal(&head->ids, &info->ids)) {
+ /*
+ * A newly created namespace can reuse an NSID that was
+ * previously deleted. If the head has no active paths,
+ * it is pending delayed removal and still occupying
+ * this NSID in the subsystem list. Flush the removal
+ * work to clear the stale head and retry.
+ */
+ if (!retried && multipath && list_empty(&head->list)) {
+ mutex_unlock(&ctrl->subsys->lock);
+ nvme_mpath_flush_remove_work(head);
+ nvme_put_ns_head(head);
+ retried = true;
+ goto again;
+ }
+
+ WARN_ON_ONCE(list_empty(&head->list));
dev_err(ctrl->device,
"IDs don't match for shared namespace %d\n",
info->nsid);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index e73cc2e67ac51..44801801fc289 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -1042,6 +1042,11 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head);
void nvme_mpath_start_request(struct request *rq);
void nvme_mpath_end_request(struct request *rq);
+static inline void nvme_mpath_flush_remove_work(struct nvme_ns_head *head)
+{
+ flush_delayed_work(&head->remove_work);
+}
+
static inline void nvme_trace_bio_complete(struct request *req)
{
struct nvme_ns *ns = req->q->queuedata;
@@ -1110,6 +1115,9 @@ static inline void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
static inline void nvme_mpath_remove_disk(struct nvme_ns_head *head)
{
}
+static inline void nvme_mpath_flush_remove_work(struct nvme_ns_head *head)
+{
+}
static inline void nvme_trace_bio_complete(struct request *req)
{
}
--
2.47.3
More information about the Linux-nvme
mailing list