[PATCHv2] nvme: allow to re-attach namespaces after all paths are down
From: Hannes Reinecke <hare@suse.de>
Date: 2021-05-11 10:42:15
Subsystem:
nvm express driver, the rest · Maintainers:
Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg, Linus Torvalds
We should only remove the ns head from the list of heads per subsystem if the reference count drops to zero. Removing it at the start of nvme_ns_remove() will prevent us from reattaching the namespace to the correct ns head once a path becomes available again. Changes to v1: - Always check NSIDs after reattach Signed-off-by: Hannes Reinecke <hare@suse.de> --- drivers/nvme/host/core.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 522c9b229f80..aa19a7e80a47 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c@@ -546,6 +546,9 @@ static void nvme_free_ns_head(struct kref *ref) struct nvme_ns_head *head = container_of(ref, struct nvme_ns_head, ref); + mutex_lock(&head->subsys->lock); + list_del_init(&head->entry); + mutex_unlock(&head->subsys->lock); nvme_mpath_remove_disk(head); ida_simple_remove(&head->subsys->ns_ida, head->instance); cleanup_srcu_struct(&head->srcu);
@@ -3549,7 +3552,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl, goto out_ida_remove; head->subsys = ctrl->subsys; head->ns_id = nsid; - head->ids = *ids; + memcpy(&head->ids, ids, sizeof(sturct nvme_ns_ids)); kref_init(&head->ref); ret = __nvme_check_ids(ctrl->subsys, head);
@@ -3605,15 +3608,23 @@ static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid, head->shared = is_shared; } else { ret = -EINVAL; + /* + * If multipath is enabled we might hit an ns head with no + * paths, but that doesn't indicate it's a shared namespace. + */ + if (nvme_ns_head_multipath(head) && + list_empty(&head->list)) + goto check_ids; if (!is_shared || !head->shared) { dev_err(ctrl->device, "Duplicate unshared namespace %d\n", nsid); goto out_put_ns_head; } +check_ids: if (!nvme_ns_ids_equal(&head->ids, ids)) { dev_err(ctrl->device, "IDs don't match for shared namespace %d\n", - nsid); + nsid); goto out_put_ns_head; } }
@@ -3764,8 +3775,6 @@ static void nvme_ns_remove(struct nvme_ns *ns) mutex_lock(&ns->ctrl->subsys->lock); list_del_rcu(&ns->siblings); - if (list_empty(&ns->head->list)) - list_del_init(&ns->head->entry); mutex_unlock(&ns->ctrl->subsys->lock); synchronize_rcu(); /* guarantee not available in head->list */
--
2.29.2
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme