[PATCH 2/2] nvme: do not detach nshead when a namespace is removed

Hannes Reinecke hare at suse.de
Wed Mar 31 15:53:51 BST 2021


'struct nshead' and 'struct ns' have different lifetimes; the nshead
can (and occasionally will) stay around even if no namespaces are
connected, as it will only be finally removed once the last
reference is gone.
But while it is in this state we should still be able to access
it during lookup; a nshead with no controllers is perfectly valid
(at least for fabrics), and the namespace has no business with
removing the nshead from the subsystem lists.

This patch fixes the situation by only removing the nshead from the
subsystem list once it's being finally removed.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 drivers/nvme/host/core.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index ee898c8da786..05fecbd33fa7 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -542,6 +542,10 @@ 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);
+
 #ifdef CONFIG_NVME_MULTIPATH
 	if (head->disk)
 		put_disk(head->disk);
@@ -3993,8 +3997,6 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid,
  out_unlink_ns:
 	mutex_lock(&ctrl->subsys->lock);
 	list_del_rcu(&ns->siblings);
-	if (list_empty(&ns->head->list))
-		list_del_init(&ns->head->entry);
 	mutex_unlock(&ctrl->subsys->lock);
 	nvme_put_ns_head(ns->head);
  out_free_queue:
@@ -4015,8 +4017,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




More information about the Linux-nvme mailing list