--- /dev/null
+From ac262508daa88fb12c5dc53cf30bde163f9f26c9 Mon Sep 17 00:00:00 2001
+From: Keith Busch <kbusch@kernel.org>
+Date: Thu, 9 Apr 2020 09:09:00 -0700
+Subject: nvme: release namespace head reference on error
+
+From: Keith Busch <kbusch@kernel.org>
+
+commit ac262508daa88fb12c5dc53cf30bde163f9f26c9 upstream.
+
+If a namespace identification does not match the subsystem's head for
+that NSID, release the reference that was taken when the matching head
+was initially found.
+
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -3467,6 +3467,7 @@ static int nvme_init_ns_head(struct nvme
+ "IDs don't match for shared namespace %d\n",
+ nsid);
+ ret = -EINVAL;
++ nvme_put_ns_head(head);
+ goto out_unlock;
+ }
+ }
--- /dev/null
+From d567572906d986dedb78b37f111c44eba033f3ef Mon Sep 17 00:00:00 2001
+From: Keith Busch <kbusch@kernel.org>
+Date: Thu, 9 Apr 2020 09:08:59 -0700
+Subject: nvme: unlink head after removing last namespace
+
+From: Keith Busch <kbusch@kernel.org>
+
+commit d567572906d986dedb78b37f111c44eba033f3ef upstream.
+
+The driver had been unlinking the namespace head from the subsystem's
+list only after the last reference was released, and outside of the
+list's subsys->lock protection.
+
+There is no reason to track an empty head, so unlink the entry from the
+subsystem's list when the last namespace using that head is removed and
+with the mutex lock protecting the list update. The next namespace to
+attach reusing the previous NSID will allocate a new head rather than
+find the old head with mismatched identifiers.
+
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/core.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -455,7 +455,6 @@ static void nvme_free_ns_head(struct kre
+
+ nvme_mpath_remove_disk(head);
+ ida_simple_remove(&head->subsys->ns_ida, head->instance);
+- list_del_init(&head->entry);
+ cleanup_srcu_struct(&head->srcu);
+ nvme_put_subsystem(head->subsys);
+ kfree(head);
+@@ -3374,7 +3373,6 @@ static int __nvme_check_ids(struct nvme_
+
+ list_for_each_entry(h, &subsys->nsheads, entry) {
+ if (nvme_ns_ids_valid(&new->ids) &&
+- !list_empty(&h->list) &&
+ nvme_ns_ids_equal(&new->ids, &h->ids))
+ return -EINVAL;
+ }
+@@ -3629,6 +3627,8 @@ static int nvme_alloc_ns(struct nvme_ctr
+ 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_id:
+@@ -3651,7 +3651,10 @@ static void nvme_ns_remove(struct nvme_n
+
+ 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 */
+ nvme_mpath_clear_current_path(ns);
+ synchronize_srcu(&ns->head->srcu); /* wait for concurrent submissions */