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: Sunad Bhandary S <sunad.s@samsung.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
bd0fc2884c
commit
47b0e50ac7
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user