[PATCH 2/2] nvme-loop: use xarray for loop port tracking
Chaitanya Kulkarni
chaitanya.kulkarni at wdc.com
Thu Sep 24 19:51:30 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 | 35 +++++++++++++++--------------------
1 file changed, 15 insertions(+), 20 deletions(-)
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index 1d8e5c4fd293..81c40011255f 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);
@@ -539,19 +537,18 @@ 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;
+ struct nvmet_port *p;
+ 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))
- continue;
- found = p;
- break;
+ if (!((ctrl->opts->mask & NVMF_OPT_TRADDR) &&
+ strcmp(ctrl->opts->traddr, p->disc_addr.traddr)))
+ break;
}
- mutex_unlock(&nvme_loop_ports_mutex);
- return found;
+ rcu_read_unlock();
+ return p;
}
static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
@@ -639,18 +636,14 @@ 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
* deleted are in fact deleted before we return
@@ -688,6 +681,7 @@ static int __init nvme_loop_init_module(void)
if (ret)
nvmet_unregister_transport(&nvme_loop_ops);
+ xa_init(&nvme_loop_ports);
xa_init(&nvme_loop_ctrls);
return ret;
@@ -705,6 +699,7 @@ static void __exit nvme_loop_cleanup_module(void)
nvme_delete_ctrl(&ctrl->ctrl);
xa_destroy(&nvme_loop_ctrls);
+ xa_destroy(&nvme_loop_ports);
flush_workqueue(nvme_delete_wq);
}
--
2.22.1
More information about the Linux-nvme
mailing list