[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