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 | 14 +++-- drivers/infiniband/core/restrack.c | 93 +++++++++++++++++++++++------- include/rdma/ib_verbs.h | 7 +-- include/rdma/restrack.h | 51 ++++++++-------- 5 files changed, 115 insertions(+), 55 deletions(-) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index b4ff83ef4667..ed17e4f5b622 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -291,7 +291,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 51cc003e0223..7fa64bd43c40 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -1071,6 +1071,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); @@ -1118,8 +1119,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], res, id, ULONG_MAX, XA_PRESENT) { + 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) { if (idx < start) goto next; @@ -1136,9 +1138,9 @@ static int res_get_common_dumpit(struct sk_buff *skb, filled = true; - 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. @@ -1156,7 +1158,7 @@ static int res_get_common_dumpit(struct sk_buff *skb, goto res_err; next: idx++; } - up_read(&device->res.rwsem); + rdma_rt_read_unlock(device, res_type); nla_nest_end(skb, table_attr); nlmsg_end(skb, nlh); @@ -1174,7 +1176,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 e8e21012bec9..0e9995ac6212 100644 --- a/drivers/infiniband/core/restrack.c +++ b/drivers/infiniband/core/restrack.c @@ -9,18 +9,46 @@ #include <linux/mutex.h> #include <linux/sched/task.h> #include <linux/pid_namespace.h> +#include <linux/rwsem.h> #include "cma_priv.h" -void rdma_restrack_init(struct ib_device *dev) +/** + * 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]; +}; + +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) @@ -37,9 +65,29 @@ static const char *type2str(enum rdma_restrack_type type) return names[type]; }; +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); + +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); + +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); + 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; @@ -47,14 +95,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], e, index, ULONG_MAX, XA_PRESENT) { + xa_for_each(xa, e, index, ULONG_MAX, XA_PRESENT) { if (rdma_is_kernel_res(e)) { owner = e->kern_name; } else { @@ -74,28 +124,30 @@ 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); } 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], e, index, ULONG_MAX, XA_PRESENT) { + rdma_rt_read_lock(dev, type); + xa_for_each(xa, e, index, ULONG_MAX, XA_PRESENT) { 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); @@ -182,6 +234,7 @@ static unsigned long res_to_id(struct rdma_restrack_entry *res) static void 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); unsigned long id; int ret; @@ -204,7 +257,7 @@ static void rdma_restrack_add(struct rdma_restrack_entry *res) res->valid = true; id = res_to_id(res); - ret = xa_insert(&dev->res.xa[res->type], id, res, GFP_KERNEL); + ret = xa_insert(xa, id, res, GFP_KERNEL); WARN_ONCE(ret == -EEXIST, "Tried to add non-unique type %d entry\n", res->type); if (ret) @@ -243,10 +296,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 || xa_is_err(res) || !rdma_restrack_get(res)) return ERR_PTR(-ENOENT); return res; @@ -269,13 +322,13 @@ 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 = rdma_dev_to_xa(dev, res->type); unsigned long id; if (!res->valid) goto out; - dev = res_to_dev(res); if (!dev) return; @@ -284,10 +337,10 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) wait_for_completion(&res->comp); id = res_to_id(res); - down_write(&dev->res.rwsem); - xa_erase(&dev->res.xa[res->type], id); + down_write(&dev->res->rwsem); + xa_erase(xa, 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 34acf04292d4..0914c862c60d 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2516,6 +2516,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; @@ -2580,10 +2582,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 df1d87b25cdf..dbbce1b29b12 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,27 +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]; -}; /** * struct rdma_restrack_entry - metadata per-entry @@ -118,10 +96,12 @@ struct rdma_restrack_entry { }; /** - * rdma_restrack_init() - initialize resource tracking + * 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); /** * rdma_restrack_clean() - clean resource tracking @@ -199,4 +179,27 @@ 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); +/** + * 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); +/** + * 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); +/** + * 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); #endif /* _RDMA_RESTRACK_H_ */ -- 2.19.1