Commit 47b0e50a authored by Sunad Bhandary's avatar Sunad Bhandary Committed by Jens Axboe

NVMe: Fix removal in case of active namespace list scanning method

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: default avatarSunad Bhandary S <sunad.s@samsung.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent bd0fc288
...@@ -1528,6 +1528,17 @@ static void nvme_validate_ns(struct nvme_ctrl *ctrl, unsigned nsid) ...@@ -1528,6 +1528,17 @@ static void nvme_validate_ns(struct nvme_ctrl *ctrl, unsigned nsid)
nvme_alloc_ns(ctrl, 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) static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn)
{ {
struct nvme_ns *ns; struct nvme_ns *ns;
...@@ -1542,7 +1553,7 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn) ...@@ -1542,7 +1553,7 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn)
for (i = 0; i < num_lists; i++) { for (i = 0; i < num_lists; i++) {
ret = nvme_identify_ns_list(ctrl, prev, ns_list); ret = nvme_identify_ns_list(ctrl, prev, ns_list);
if (ret) if (ret)
goto out; goto free;
for (j = 0; j < min(nn, 1024U); j++) { for (j = 0; j < min(nn, 1024U); j++) {
nsid = le32_to_cpu(ns_list[j]); nsid = le32_to_cpu(ns_list[j]);
...@@ -1560,13 +1571,14 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn) ...@@ -1560,13 +1571,14 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn)
nn -= j; nn -= j;
} }
out: out:
nvme_remove_invalid_namespaces(ctrl, prev);
free:
kfree(ns_list); kfree(ns_list);
return ret; return ret;
} }
static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn) static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
{ {
struct nvme_ns *ns, *next;
unsigned i; unsigned i;
lockdep_assert_held(&ctrl->namespaces_mutex); lockdep_assert_held(&ctrl->namespaces_mutex);
...@@ -1574,10 +1586,7 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn) ...@@ -1574,10 +1586,7 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
for (i = 1; i <= nn; i++) for (i = 1; i <= nn; i++)
nvme_validate_ns(ctrl, i); nvme_validate_ns(ctrl, i);
list_for_each_entry_safe(ns, next, &ctrl->namespaces, list) { nvme_remove_invalid_namespaces(ctrl, nn);
if (ns->ns_id > nn)
nvme_ns_remove(ns);
}
} }
static void nvme_scan_work(struct work_struct *work) static void nvme_scan_work(struct work_struct *work)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment