]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
NVMe: Fix removal in case of active namespace list scanning method
authorSunad Bhandary <sunad.s@samsung.com>
Fri, 27 May 2016 10:29:43 +0000 (15:59 +0530)
committerJens Axboe <axboe@fb.com>
Wed, 8 Jun 2016 14:48:47 +0000 (08:48 -0600)
In case of the active namespace list scanning method, a namespace that
is detached is not removed from the host if it was the last entry in
the list. Fix this by adding a scan to validate namespaces greater than
the value of prev.

This also handles the case of removing namespaces whose value exceed
the device's reported number of namespaces.

Signed-off-by: Sunad Bhandary S <sunad.s@samsung.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/nvme/host/core.c

index 99a95bad3ce4b28635c0aacc74ad9029790916a6..684062a9d392a07bfc7cd37a5bcf6af9f670d2ed 100644 (file)
@@ -1528,6 +1528,17 @@ static void nvme_validate_ns(struct nvme_ctrl *ctrl, unsigned nsid)
                nvme_alloc_ns(ctrl, nsid);
 }
 
+static void nvme_remove_invalid_namespaces(struct nvme_ctrl *ctrl,
+                                       unsigned nsid)
+{
+       struct nvme_ns *ns, *next;
+
+       list_for_each_entry_safe(ns, next, &ctrl->namespaces, list) {
+               if (ns->ns_id > nsid)
+                       nvme_ns_remove(ns);
+       }
+}
+
 static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn)
 {
        struct nvme_ns *ns;
@@ -1542,7 +1553,7 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn)
        for (i = 0; i < num_lists; i++) {
                ret = nvme_identify_ns_list(ctrl, prev, ns_list);
                if (ret)
-                       goto out;
+                       goto free;
 
                for (j = 0; j < min(nn, 1024U); j++) {
                        nsid = le32_to_cpu(ns_list[j]);
@@ -1560,13 +1571,14 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn)
                nn -= j;
        }
  out:
+       nvme_remove_invalid_namespaces(ctrl, prev);
+ free:
        kfree(ns_list);
        return ret;
 }
 
 static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
 {
-       struct nvme_ns *ns, *next;
        unsigned i;
 
        lockdep_assert_held(&ctrl->namespaces_mutex);
@@ -1574,10 +1586,7 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
        for (i = 1; i <= nn; i++)
                nvme_validate_ns(ctrl, i);
 
-       list_for_each_entry_safe(ns, next, &ctrl->namespaces, list) {
-               if (ns->ns_id > nn)
-                       nvme_ns_remove(ns);
-       }
+       nvme_remove_invalid_namespaces(ctrl, nn);
 }
 
 static void nvme_scan_work(struct work_struct *work)