nvme: fix the deadlock in nvme_update_formats

"Linux Kernel Mailing List" <[email protected]> Sat, 17 Feb 2018 19:17:15 +0000 (UTC)
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/3fd176b754e992e1cdf1693ea8184626d1ed7671
Commit:     3fd176b754e992e1cdf1693ea8184626d1ed7671
Parent:     0a34e4668c508cbbc2d5ef2d9710b145e4c0b27d
Refname:    refs/heads/master
Author:     Jianchao Wang <[email protected]>
AuthorDate: Mon Feb 12 20:54:45 2018 +0800
Committer:  Keith Busch <[email protected]>
CommitDate: Tue Feb 13 17:09:50 2018 -0700

    nvme: fix the deadlock in nvme_update_formats
    
    nvme_update_formats will invoke nvme_ns_remove under namespaces_mutext.
    The will cause deadlock because nvme_ns_remove will also require
    the namespaces_mutext. Fix it by getting the ns entries which should
    be removed under namespaces_mutext and invoke nvme_ns_remove out of
    namespaces_mutext.
    
    Signed-off-by: Jianchao Wang <[email protected]>
    Reviewed-by: Christoph Hellwig <[email protected]>
    Reviewed-by: Keith Busch <[email protected]>
    Signed-off-by: Sagi Grimberg <[email protected]>
---
 drivers/nvme/host/core.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 6d0490b477c9..52b3626fb64e 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1117,14 +1117,19 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 
 static void nvme_update_formats(struct nvme_ctrl *ctrl)
 {
-	struct nvme_ns *ns;
+	struct nvme_ns *ns, *next;
+	LIST_HEAD(rm_list);
 
 	mutex_lock(&ctrl->namespaces_mutex);
 	list_for_each_entry(ns, &ctrl->namespaces, list) {
-		if (ns->disk && nvme_revalidate_disk(ns->disk))
-			nvme_ns_remove(ns);
+		if (ns->disk && nvme_revalidate_disk(ns->disk)) {
+			list_move_tail(&ns->list, &rm_list);
+		}
 	}
 	mutex_unlock(&ctrl->namespaces_mutex);
+
+	list_for_each_entry_safe(ns, next, &rm_list, list)
+		nvme_ns_remove(ns);
 }
 
 static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html