[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