[PATCH V2 2/2] nvme-loop: use xarray for loop port tracking
Chaitanya Kulkarni
chaitanya.kulkarni at wdc.com
Wed Sep 30 00:55:57 EDT 2020
For nvme-loop ports are tracked with nvme_loop_ports_list. This requires
an extra locking just for list operations.
The Xarray data structure provides a clear API which handles locking
implicitly so we can get rid of the locking and the list loop(s) if any.
Replace nvme loop ports list and its lock nvme_loop_ports_mutex with
nvme_loop_ports XArray.
Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni at wdc.com>
---
drivers/nvme/target/loop.c | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index 2f2e16fb9f29..873afe0654e9 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -54,9 +54,7 @@ struct nvme_loop_queue {
unsigned long flags;
};
-static LIST_HEAD(nvme_loop_ports);
-static DEFINE_MUTEX(nvme_loop_ports_mutex);
-
+static DEFINE_XARRAY(nvme_loop_ports);
static DEFINE_XARRAY(nvme_loop_ctrls);
static void nvme_loop_queue_response(struct nvmet_req *nvme_req);
@@ -540,9 +538,10 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
static struct nvmet_port *nvme_loop_find_port(struct nvme_ctrl *ctrl)
{
struct nvmet_port *p, *found = NULL;
+ unsigned long idx;
- mutex_lock(&nvme_loop_ports_mutex);
- list_for_each_entry(p, &nvme_loop_ports, entry) {
+ rcu_read_lock();
+ xa_for_each(&nvme_loop_ports, idx, p) {
/* if no transport address is specified use the first port */
if ((ctrl->opts->mask & NVMF_OPT_TRADDR) &&
strcmp(ctrl->opts->traddr, p->disc_addr.traddr))
@@ -550,7 +549,7 @@ static struct nvmet_port *nvme_loop_find_port(struct nvme_ctrl *ctrl)
found = p;
break;
}
- mutex_unlock(&nvme_loop_ports_mutex);
+ rcu_read_unlock();
return found;
}
@@ -639,17 +638,13 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
static int nvme_loop_add_port(struct nvmet_port *port)
{
- mutex_lock(&nvme_loop_ports_mutex);
- list_add_tail(&port->entry, &nvme_loop_ports);
- mutex_unlock(&nvme_loop_ports_mutex);
- return 0;
+ return xa_insert(&nvme_loop_ports, port->disc_addr.portid,
+ port, GFP_KERNEL);
}
static void nvme_loop_remove_port(struct nvmet_port *port)
{
- mutex_lock(&nvme_loop_ports_mutex);
- list_del_init(&port->entry);
- mutex_unlock(&nvme_loop_ports_mutex);
+ xa_erase(&nvme_loop_ports, port->disc_addr.portid);
/*
* Ensure any ctrls that are in the process of being
@@ -689,6 +684,7 @@ static int __init nvme_loop_init_module(void)
nvmet_unregister_transport(&nvme_loop_ops);
xa_init(&nvme_loop_ctrls);
+ xa_init(&nvme_loop_ports);
return ret;
}
@@ -704,6 +700,7 @@ static void __exit nvme_loop_cleanup_module(void)
xa_for_each(&nvme_loop_ctrls, idx, ctrl)
nvme_delete_ctrl(&ctrl->ctrl);
+ xa_destroy(&nvme_loop_ports);
xa_destroy(&nvme_loop_ctrls);
flush_workqueue(nvme_delete_wq);
--
2.22.1
More information about the Linux-nvme
mailing list