[PATCH rdma-next 15/16] RDMA/restrack: Implement software ID interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Leon Romanovsky <leonro@xxxxxxxxxxxx>

Generate unique resource ID for SW and HW capable devices.
RES_VALID marker is introduced as a temporal measure till
all drivers are converted to use restrask IDs. After that,
it will be safe to remove RES_VISIBLE and expose all objects,
including internal ones.

Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
---
 drivers/infiniband/core/nldev.c    |  2 +-
 drivers/infiniband/core/restrack.c | 83 +++++++++++++++++++-----------
 include/rdma/restrack.h            | 19 +++++++
 3 files changed, 74 insertions(+), 30 deletions(-)

diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 7fa64bd43c40..de3e90d6fb5a 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1121,7 +1121,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
 
 	xa = rdma_dev_to_xa(device, res_type);
 	rdma_rt_read_lock(device, res_type);
-	xa_for_each(xa, res, id, ULONG_MAX, XA_PRESENT) {
+	xa_for_each(xa, res, id, ULONG_MAX, RES_VISIBLE) {
 		if (idx < start)
 			goto next;
 
diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
index a3c94fe910a2..ff1581347f66 100644
--- a/drivers/infiniband/core/restrack.c
+++ b/drivers/infiniband/core/restrack.c
@@ -51,6 +51,7 @@ int rdma_restrack_init(struct ib_device *dev)
 	for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
 		init_rwsem(&rt[i].rwsem);
 		xa_init_flags(&rt[i].xa, XA_FLAGS_ALLOC);
+		rt[i].max = U32_MAX;
 	}
 
 	return 0;
@@ -146,7 +147,7 @@ int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
 	u32 cnt = 0;
 
 	rdma_rt_read_lock(dev, type);
-	xa_for_each(xa, e, index, ULONG_MAX, XA_PRESENT) {
+	xa_for_each(xa, e, index, ULONG_MAX, RES_VISIBLE) {
 		if (ns == &init_pid_ns ||
 		    (!rdma_is_kernel_res(e) &&
 		     ns == task_active_pid_ns(e->task)))
@@ -220,40 +221,52 @@ void rdma_restrack_set_task(struct rdma_restrack_entry *res,
 }
 EXPORT_SYMBOL(rdma_restrack_set_task);
 
-static unsigned long res_to_id(struct rdma_restrack_entry *res)
-{
-	switch (res->type) {
-	case RDMA_RESTRACK_PD:
-	case RDMA_RESTRACK_MR:
-	case RDMA_RESTRACK_CM_ID:
-	case RDMA_RESTRACK_CTX:
-	case RDMA_RESTRACK_CQ:
-	case RDMA_RESTRACK_QP:
-		return (unsigned long)res;
-	default:
-		WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
-		return 0;
-	}
-}
+#define RES_USER_ENTRY	XA_MARK_1
 
-static void rdma_restrack_add(struct rdma_restrack_entry *res)
+int rdma_restrack_add(struct rdma_restrack_entry *res)
 {
 	struct ib_device *dev = res_to_dev(res);
 	struct xarray *xa = rdma_dev_to_xa(dev, res->type);
+	struct rdma_restrack_root *rt = dev->res;
 	int ret;
 
+	/*
+	 * Once all drivers are converted, we can remove this check
+	 * and remove call to rdma_restrack_add() from rdma_restrack_kadd()
+	 * and rdma_restrack_uadd()
+	 */
+	if (xa_load(xa, res->id))
+		return 0;
+
 	kref_init(&res->kref);
 	init_completion(&res->comp);
 	res->valid = true;
 
-	ret = xa_insert(xa, res_to_id(res), res, GFP_KERNEL);
-	WARN_ONCE(ret == -EEXIST, "Tried to add non-unique type %d entry\n",
-		  res->type);
+	if (rt[res->type].max) {
+		/* Not HW-capable device */
+		res->id = rt[res->type].reserved;
+		ret = xa_alloc(xa, &res->id, rt[res->type].max, res,
+			       GFP_KERNEL);
+	} else {
+		ret = xa_insert(xa, res->id, res, GFP_KERNEL);
+	}
+	/*
+	 * WARNs below indicates an error in driver code.
+	 * The check of -EEXIST is never occuried and added here
+	 * to allow simple removal of xa_load above.
+	 */
+	WARN_ONCE(ret == -EEXIST, "Tried to add non-unique %s entry %u\n",
+		  type2str(res->type), res->id);
+	WARN_ONCE(ret == -ENOSPC,
+		  "There are no more free indexes for type %s entry %u\n",
+		  type2str(res->type), res->id);
+
 	if (ret)
 		res->valid = false;
-}
 
-#define RES_USER_ENTRY	XA_MARK_1
+	return ret;
+}
+EXPORT_SYMBOL(rdma_restrack_add);
 
 /**
  * rdma_restrack_kadd() - add kernel object to the reource tracking database
@@ -261,9 +274,17 @@ static void rdma_restrack_add(struct rdma_restrack_entry *res)
  */
 void rdma_restrack_kadd(struct rdma_restrack_entry *res)
 {
+	struct ib_device *dev = res_to_dev(res);
+	struct xarray *xa = rdma_dev_to_xa(dev, res->type);
+
 	res->task = NULL;
 	set_kern_name(res);
+	/*
+	 * Temporaly, we are not intested in return value,
+	 * once conversion will be finished, it will be checked by drivers.
+	 */
 	rdma_restrack_add(res);
+	xa_set_mark(xa, res->id, RES_VISIBLE);
 }
 EXPORT_SYMBOL(rdma_restrack_kadd);
 
@@ -283,8 +304,13 @@ void rdma_restrack_uadd(struct rdma_restrack_entry *res)
 		rdma_restrack_set_task(res, NULL);
 	res->kern_name = NULL;
 
+	/*
+	 * Temporaly, we are not intested in return value,
+	 * once conversion will be finished, it will be checked by drivers.
+	 */
 	rdma_restrack_add(res);
-	xa_set_mark(xa, res_to_id(res), RES_USER_ENTRY);
+	xa_set_mark(xa, res->id, RES_USER_ENTRY);
+	xa_set_mark(xa, res->id, RES_VISIBLE);
 }
 EXPORT_SYMBOL(rdma_restrack_uadd);
 
@@ -295,7 +321,7 @@ bool rdma_is_kernel_res(struct rdma_restrack_entry *res)
 
 	xa = rdma_dev_to_xa(dev, res->type);
 
-	return !xa_get_mark(xa, res_to_id(res), RES_USER_ENTRY);
+	return !xa_get_mark(xa, res->id, RES_USER_ENTRY);
 }
 EXPORT_SYMBOL(rdma_is_kernel_res);
 
@@ -313,7 +339,8 @@ rdma_restrack_get_byid(struct ib_device *dev,
 	struct rdma_restrack_entry *res;
 
 	res = xa_load(xa, id);
-	if (!res || xa_is_err(res) || !rdma_restrack_get(res))
+	if (!res || !rdma_restrack_get(res) ||
+	    !xa_get_mark(xa, res->id, RES_VISIBLE))
 		return ERR_PTR(-ENOENT);
 	return res;
 }
@@ -337,9 +364,8 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)
 {
 	struct ib_device *dev = res_to_dev(res);
 	struct xarray *xa = rdma_dev_to_xa(dev, res->type);
-	unsigned long id;
 
-	if (!res->valid)
+	if (!res->valid || !xa_load(xa, res->id))
 		goto out;
 
 	if (!dev)
@@ -348,10 +374,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)
 	rdma_restrack_put(res);
 
 	wait_for_completion(&res->comp);
-	id = res_to_id(res);
 
 	down_write(&dev->res[res->type].rwsem);
-	xa_erase(xa, id);
+	xa_erase(xa, res->id);
 	res->valid = false;
 	up_write(&dev->res[res->type].rwsem);
 
diff --git a/include/rdma/restrack.h b/include/rdma/restrack.h
index 4dba2e0ec90e..e70622bf3293 100644
--- a/include/rdma/restrack.h
+++ b/include/rdma/restrack.h
@@ -89,6 +89,11 @@ struct rdma_restrack_entry {
 	 * @type: various objects in restrack database
 	 */
 	enum rdma_restrack_type	type;
+	/**
+	 * @id: unique to specific type identifier, for HW-capable devices,
+	 * drivers are supposed to update it, because it is used as an index.
+	 */
+	u32 id;
 };
 
 /**
@@ -118,6 +123,20 @@ int rdma_restrack_count(struct ib_device *dev,
 void rdma_restrack_kadd(struct rdma_restrack_entry *res);
 void rdma_restrack_uadd(struct rdma_restrack_entry *res);
 
+/**
+ * Addition of entry is performed in two steps approach:
+ * 1. Driver creates ID and allocates resource entry.
+ * 2. IB/core marks such entry as user/kernel and exports to nldev.c
+ */
+#define RES_VISIBLE	XA_MARK_2
+/**
+ * rdma_restrack_add() - add new resoruce to DB and get ID in return
+ * @res: resoruce to add
+ *
+ * Return: 0 on success
+ */
+int rdma_restrack_add(struct rdma_restrack_entry *res);
+
 /**
  * rdma_restrack_del() - delete object from the reource tracking database
  * @res:  resource entry
-- 
2.19.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux