[PATCH rdma-next v3 11/19] RDMA/restrack: Hide restrack DB from IB/core

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

 



From: Leon Romanovsky <leonro@xxxxxxxxxxxx>

There is no need to expose internals of restrack DB to IB/core.

Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
---
 drivers/infiniband/core/device.c   |   5 +-
 drivers/infiniband/core/nldev.c    |  16 ++--
 drivers/infiniband/core/restrack.c | 144 ++++++++++++++++++++++++-----
 include/rdma/ib_verbs.h            |   7 +-
 include/rdma/restrack.h            |  32 +------
 5 files changed, 140 insertions(+), 64 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index fa8d79548ee7..d13491b416dc 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -288,7 +288,10 @@ struct ib_device *ib_alloc_device(size_t size)
 	if (!device)
 		return NULL;
 
-	rdma_restrack_init(device);
+	if (rdma_restrack_init(device)) {
+		kfree(device);
+		return NULL;
+	}
 
 	device->dev.class = &ib_class;
 	device_initialize(&device->dev);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 57ce5dde6679..fed891e60686 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1029,6 +1029,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
 	unsigned long id = 0;
 	u32 index, port = 0;
 	bool filled = false;
+	struct xarray *xa;
 
 	err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
 			  nldev_policy, NULL);
@@ -1076,8 +1077,9 @@ static int res_get_common_dumpit(struct sk_buff *skb,
 
 	has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN);
 
-	down_read(&device->res.rwsem);
-	xa_for_each(&device->res.xa[res_type], id, res) {
+	xa = rdma_dev_to_xa(device, res_type);
+	rdma_rt_read_lock(device, res_type);
+	xa_for_each(xa, id, res) {
 		if (idx < start)
 			goto next;
 
@@ -1098,13 +1100,13 @@ static int res_get_common_dumpit(struct sk_buff *skb,
 		if (!entry_attr) {
 			ret = -EMSGSIZE;
 			rdma_restrack_put(res);
-			up_read(&device->res.rwsem);
+			rdma_rt_read_unlock(device, res_type);
 			break;
 		}
-		up_read(&device->res.rwsem);
 
+		rdma_rt_read_unlock(device, res_type);
 		ret = fe->fill_res_func(skb, has_cap_net_admin, res, port);
-		down_read(&device->res.rwsem);
+		rdma_rt_read_lock(device, res_type);
 		/*
 		 * Return resource back, but it won't be released till
 		 * the &device->res.rwsem will be released for write.
@@ -1125,7 +1127,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
 		nla_nest_end(skb, entry_attr);
 next:		idx++;
 	}
-	up_read(&device->res.rwsem);
+	rdma_rt_read_unlock(device, res_type);
 
 	nla_nest_end(skb, table_attr);
 	nlmsg_end(skb, nlh);
@@ -1143,7 +1145,7 @@ next:		idx++;
 
 res_err:
 	nla_nest_cancel(skb, table_attr);
-	up_read(&device->res.rwsem);
+	rdma_rt_read_unlock(device, res_type);
 
 err:
 	nlmsg_cancel(skb, nlh);
diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
index fce51c2f156a..284d087d7785 100644
--- a/drivers/infiniband/core/restrack.c
+++ b/drivers/infiniband/core/restrack.c
@@ -9,6 +9,7 @@
 #include <linux/mutex.h>
 #include <linux/sched/task.h>
 #include <linux/pid_namespace.h>
+#include <linux/rwsem.h>
 
 #include "cma_priv.h"
 
@@ -35,18 +36,51 @@ static int rt_xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry,
 }
 
 /**
- * rdma_restrack_init() - initialize resource tracking
+ * struct rdma_restrack_root - main resource tracking management
+ * entity, per-device
+ */
+struct rdma_restrack_root {
+	/*
+	 * @rwsem: Read/write lock to protect erase of entry.
+	 * Lists and insertions are protected by XArray internal lock.
+	 */
+	struct rw_semaphore	rwsem;
+	/**
+	 * @xa: Array of XArray structures to hold restrack entries.
+	 * We want to use array of XArrays because insertion is type
+	 * dependent. For types with xisiting unique ID (like QPN),
+	 * we will insert to that unique index. For other types,
+	 * we insert based on pointers and auto-allocate unique index.
+	 */
+	struct xarray xa[RDMA_RESTRACK_MAX];
+	/**
+	 * #next_id: Next ID to support cyclic allocation
+	 */
+	u32 next_id[RDMA_RESTRACK_MAX];
+};
+
+/**
+ * rdma_restrack_init() - initialize and allocate resource tracking
  * @dev:  IB device
+ *
+ * Return: 0 on success
  */
-void rdma_restrack_init(struct ib_device *dev)
+int rdma_restrack_init(struct ib_device *dev)
 {
-	struct rdma_restrack_root *res = &dev->res;
+	struct rdma_restrack_root *rt;
 	int i;
 
+	dev->res = kzalloc(sizeof(*rt), GFP_KERNEL);
+	if (!dev->res)
+		return -ENOMEM;
+
+	rt = dev->res;
+
 	for (i = 0 ; i < RDMA_RESTRACK_MAX; i++)
-		xa_init_flags(&res->xa[i], XA_FLAGS_ALLOC);
+		xa_init_flags(&rt->xa[i], XA_FLAGS_ALLOC);
+	init_rwsem(&rt->rwsem);
 
-	init_rwsem(&res->rwsem);
+	return 0;
 }
 
 static const char *type2str(enum rdma_restrack_type type)
@@ -63,13 +97,52 @@ static const char *type2str(enum rdma_restrack_type type)
 	return names[type];
 };
 
+/**
+ * rdma_dev_to_xa() - translate from device to XArray DB
+ * @dev: IB device to work
+ * @type: resource track type
+ *
+ * Return: XArray DB to use for xa_for_each() iterations
+ */
+struct xarray *rdma_dev_to_xa(struct ib_device *dev,
+			      enum rdma_restrack_type type)
+{
+	return &dev->res->xa[type];
+
+}
+EXPORT_SYMBOL(rdma_dev_to_xa);
+
+/**
+ * rdma_rt_read_lock() - Lock XArray for read, needed while iterating
+ *                       with xa_for_each()
+ * @dev: IB device to work
+ * @type: resource track type
+ */
+void rdma_rt_read_lock(struct ib_device *dev, enum rdma_restrack_type type)
+{
+	down_read(&dev->res->rwsem);
+}
+EXPORT_SYMBOL(rdma_rt_read_lock);
+
+/**
+ * rdma_rt_read_unlock() - Unlock XArray for read, needed while iterating
+ *                         with xa_for_each()
+ * @dev: IB device to work
+ * @type: resource track type
+ */
+void rdma_rt_read_unlock(struct ib_device *dev, enum rdma_restrack_type type)
+{
+	up_read(&dev->res->rwsem);
+}
+EXPORT_SYMBOL(rdma_rt_read_unlock);
+
 /**
  * rdma_restrack_clean() - clean resource tracking
  * @dev:  IB device
  */
 void rdma_restrack_clean(struct ib_device *dev)
 {
-	struct rdma_restrack_root *res = &dev->res;
+	struct rdma_restrack_root *rt = dev->res;
 	struct rdma_restrack_entry *e;
 	char buf[TASK_COMM_LEN];
 	bool found = false;
@@ -77,14 +150,16 @@ void rdma_restrack_clean(struct ib_device *dev)
 	int i;
 
 	for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
-		if (!xa_empty(&res->xa[i])) {
+		struct xarray *xa = rdma_dev_to_xa(dev, i);
+
+		if (!xa_empty(xa)) {
 			unsigned long index = 0;
 
 			if (!found) {
 				pr_err("restrack: %s", CUT_HERE);
 				dev_err(&dev->dev, "BUG: RESTRACK detected leak of resources\n");
 			}
-			xa_for_each(&res->xa[i], index, e) {
+			xa_for_each(xa, index, e) {
 				if (rdma_is_kernel_res(e)) {
 					owner = e->kern_name;
 				} else {
@@ -104,10 +179,12 @@ void rdma_restrack_clean(struct ib_device *dev)
 			}
 			found = true;
 		}
-		xa_destroy(&res->xa[i]);
+		xa_destroy(xa);
 	}
 	if (found)
 		pr_err("restrack: %s", CUT_HERE);
+
+	kfree(rt);
 }
 
 /**
@@ -119,19 +196,19 @@ void rdma_restrack_clean(struct ib_device *dev)
 int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
 			struct pid_namespace *ns)
 {
-	struct rdma_restrack_root *res = &dev->res;
+	struct xarray *xa = rdma_dev_to_xa(dev, type);
 	struct rdma_restrack_entry *e;
 	unsigned long index = 0;
 	u32 cnt = 0;
 
-	down_read(&res->rwsem);
-	xa_for_each(&res->xa[type], index, e) {
+	rdma_rt_read_lock(dev, type);
+	xa_for_each(xa, index, e) {
 		if (ns == &init_pid_ns ||
 		    (!rdma_is_kernel_res(e) &&
 		     ns == task_active_pid_ns(e->task)))
 			cnt++;
 	}
-	up_read(&res->rwsem);
+	rdma_rt_read_unlock(dev, type);
 	return cnt;
 }
 EXPORT_SYMBOL(rdma_restrack_count);
@@ -202,11 +279,16 @@ EXPORT_SYMBOL(rdma_restrack_set_task);
 static void rdma_restrack_add(struct rdma_restrack_entry *res)
 {
 	struct ib_device *dev = res_to_dev(res);
+	struct rdma_restrack_root *rt;
+	struct xarray *xa;
 	int ret;
 
 	if (!dev)
 		return;
 
+	rt = dev->res;
+	xa = rdma_dev_to_xa(dev, res->type);
+
 	if (res->type != RDMA_RESTRACK_CM_ID || rdma_is_kernel_res(res))
 		res->task = NULL;
 
@@ -220,10 +302,7 @@ static void rdma_restrack_add(struct rdma_restrack_entry *res)
 
 	kref_init(&res->kref);
 	init_completion(&res->comp);
-
-	ret = rt_xa_alloc_cyclic(&dev->res.xa[res->type], &res->id, res,
-				 &dev->res.next_id[res->type]);
-
+	ret = rt_xa_alloc_cyclic(xa, &res->id, res, &rt->next_id[res->type]);
 	if (!ret)
 		res->valid = true;
 }
@@ -268,10 +347,10 @@ struct rdma_restrack_entry *
 rdma_restrack_get_byid(struct ib_device *dev,
 		       enum rdma_restrack_type type, u32 id)
 {
-	struct rdma_restrack_root *rt = &dev->res;
+	struct xarray *xa = rdma_dev_to_xa(dev, type);
 	struct rdma_restrack_entry *res;
 
-	res = xa_load(&rt->xa[type], id);
+	res = xa_load(xa, id);
 	if (!res || !rdma_restrack_get(res))
 		return ERR_PTR(-ENOENT);
 	return res;
@@ -294,26 +373,41 @@ EXPORT_SYMBOL(rdma_restrack_put);
 
 void rdma_restrack_del(struct rdma_restrack_entry *res)
 {
-	struct ib_device *dev;
+	struct ib_device *dev = res_to_dev(res);
+	struct xarray *xa;
 
 	if (!res->valid)
 		goto out;
 
-	dev = res_to_dev(res);
+	/*
+	 * All objects except CM_ID set valid device immediately
+	 * after new object is created, it means that for not valid
+	 * objects will still have "dev".
+	 *
+	 * It is not the case for CM_ID, newly created object has
+	 * this field set to NULL and it is set in _cma_attach_to_dev()
+	 * only.
+	 *
+	 * Becasue we don't want to add any conditions on call
+	 * to rdma_restrack_del(), the check below protects from
+	 * NULL-dereference.
+	 */
 	if (!dev)
 		return;
 
-	if (!xa_load(&dev->res.xa[res->type], res->id))
+	xa = rdma_dev_to_xa(dev, res->type);
+
+	if (!xa_load(xa, res->id))
 		goto out;
 
 	rdma_restrack_put(res);
 
 	wait_for_completion(&res->comp);
 
-	down_write(&dev->res.rwsem);
-	xa_erase(&dev->res.xa[res->type], res->id);
+	down_write(&dev->res->rwsem);
+	xa_erase(xa, res->id);
 	res->valid = false;
-	up_write(&dev->res.rwsem);
+	up_write(&dev->res->rwsem);
 
 out:
 	if (res->task) {
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 9d593c89f541..d54c87640f89 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2519,6 +2519,8 @@ struct ib_device_ops {
 			      struct rdma_restrack_entry *entry);
 };
 
+struct rdma_restrack_root;
+
 struct ib_device {
 	/* Do not access @dma_device directly from ULP nor from HW drivers. */
 	struct device                *dma_device;
@@ -2583,10 +2585,7 @@ struct ib_device {
 #endif
 
 	u32                          index;
-	/*
-	 * Implementation details of the RDMA core, don't use in drivers
-	 */
-	struct rdma_restrack_root     res;
+	struct rdma_restrack_root *res;
 
 	const struct uapi_definition   *driver_def;
 	enum rdma_driver_id		driver_id;
diff --git a/include/rdma/restrack.h b/include/rdma/restrack.h
index 50c963b0046f..92d11c35221a 100644
--- a/include/rdma/restrack.h
+++ b/include/rdma/restrack.h
@@ -7,7 +7,6 @@
 #define _RDMA_RESTRACK_H_
 
 #include <linux/typecheck.h>
-#include <linux/rwsem.h>
 #include <linux/sched.h>
 #include <linux/kref.h>
 #include <linux/completion.h>
@@ -50,31 +49,6 @@ enum rdma_restrack_type {
 };
 
 struct ib_device;
-struct rdma_restrack_entry;
-
-/**
- * struct rdma_restrack_root - main resource tracking management
- * entity, per-device
- */
-struct rdma_restrack_root {
-	/*
-	 * @rwsem: Read/write lock to protect erase of entry.
-	 * Lists and insertions are protected by XArray internal lock.
-	 */
-	struct rw_semaphore	rwsem;
-	/**
-	 * @xa: Array of XArray structures to hold restrack entries.
-	 * We want to use array of XArrays because insertion is type
-	 * dependent. For types with xisiting unique ID (like QPN),
-	 * we will insert to that unique index. For other types,
-	 * we insert based on pointers and auto-allocate unique index.
-	 */
-	struct xarray xa[RDMA_RESTRACK_MAX];
-	/**
-	 * #next_id: Next ID to support cyclic allocation
-	 */
-	u32 next_id[RDMA_RESTRACK_MAX];
-};
 
 /**
  * struct rdma_restrack_entry - metadata per-entry
@@ -125,7 +99,7 @@ struct rdma_restrack_entry {
 	u32 id;
 };
 
-void rdma_restrack_init(struct ib_device *dev);
+int rdma_restrack_init(struct ib_device *dev);
 void rdma_restrack_clean(struct ib_device *dev);
 int rdma_restrack_count(struct ib_device *dev,
 			enum rdma_restrack_type type,
@@ -183,4 +157,8 @@ int rdma_nl_put_driver_u64_hex(struct sk_buff *msg, const char *name,
 struct rdma_restrack_entry *rdma_restrack_get_byid(struct ib_device *dev,
 						   enum rdma_restrack_type type,
 						   u32 id);
+struct xarray *rdma_dev_to_xa(struct ib_device *dev,
+			      enum rdma_restrack_type type);
+void rdma_rt_read_lock(struct ib_device *dev, enum rdma_restrack_type type);
+void rdma_rt_read_unlock(struct ib_device *dev, enum rdma_restrack_type type);
 #endif /* _RDMA_RESTRACK_H_ */
-- 
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