drivers/infiniband/core/netlink.c | 29 +++
drivers/infiniband/core/nldev.c | 316 ++++++++++++++++++++++++
drivers/infiniband/core/rdma_core.c | 131 +++++++++-
- drivers/infiniband/core/restrack.c | 4 +
+ drivers/infiniband/core/restrack.c | 63 +++++
drivers/infiniband/core/restrack.h | 15 ++
drivers/infiniband/core/roce_gid_mgmt.c | 58 +++++
drivers/infiniband/core/rw.c | 6 +
include/rdma/restrack.h | 9 +
include/rdma/uverbs_ioctl.h | 3 +
include/trace/events/ib_mad.h | 7 +
- 32 files changed, 1557 insertions(+), 7 deletions(-)
+ 32 files changed, 1616 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index xxxxxxx..xxxxxxx 100644
/**
* rdma_restrack_init() - initialize and allocate resource tracking
* @dev: IB device
+@@ -58,11 +62,18 @@ static const char *type2str(enum rdma_restrack_type type)
+ */
+ void rdma_restrack_clean(struct ib_device *dev)
+ {
++#ifdef HAVE_XARRAY
+ struct rdma_restrack_root *rt = dev->res;
++#else
++ struct rdma_restrack_root *res = dev->res;
++#endif
+ struct rdma_restrack_entry *e;
+ char buf[TASK_COMM_LEN];
++#ifdef HAVE_XARRAY
+ bool found = false;
++#endif
+ const char *owner;
++#ifdef HAVE_XARRAY
+ int i;
+
+ for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
+@@ -101,6 +112,37 @@ void rdma_restrack_clean(struct ib_device *dev)
+ pr_err("restrack: %s", CUT_HERE);
+
+ kfree(rt);
++#else
++
++ int bkt;
++
++ if (hash_empty(res->hash)) {
++ kfree(res);
++ return;
++ }
++
++ pr_err("restrack: %s", CUT_HERE);
++ dev_err(&dev->dev, "BUG: RESTRACK detected leak of resources\n");
++ compat_hash_for_each(res->hash, bkt, e, node) {
++ if (rdma_is_kernel_res(e)) {
++ owner = e->kern_name;
++ } else {
++ /*
++ * There is no need to call get_task_struct here,
++ * because we can be here only if there are more
++ * get_task_struct() call than put_task_struct().
++ */
++ get_task_comm(buf, e->task);
++ owner = buf;
++ }
++
++ pr_err("restrack: %s %s object allocated by %s is not freed\n",
++ rdma_is_kernel_res(e) ? "Kernel" : "User",
++ type2str(e->type), owner);
++ }
++ pr_err("restrack: %s", CUT_HERE);
++ kfree(res);
++#endif /* HAVE_XARRAY */
+ }
+
+ /**
+@@ -112,6 +154,7 @@ 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)
+ {
++#ifdef HAVE_XARRAY
+ struct rdma_restrack_root *rt = &dev->res[type];
+ struct rdma_restrack_entry *e;
+ XA_STATE(xas, &rt->xa, 0);
+@@ -126,6 +169,26 @@ int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
+ }
+ xa_unlock(&rt->xa);
+ return cnt;
++#else
++ struct rdma_restrack_root *res = &dev->res[type];
++ struct rdma_restrack_entry *e;
++ u32 cnt = 0;
++ COMPAT_HL_NODE
++
++ down_read(&res->rwsem);
++#ifdef HAVE_HLIST_FOR_EACH_ENTRY_3_PARAMS
++ hash_for_each_possible(res->hash, e, node, type) {
++#else
++ hash_for_each_possible(res->hash, e, hlnode, node, type) {
++#endif
++ if (ns == &init_pid_ns ||
++ (!rdma_is_kernel_res(e) &&
++ ns == task_active_pid_ns(e->task)))
++ cnt++;
++ }
++ up_read(&res->rwsem);
++ return cnt;
++#endif /* HAVE_XARRAY */
+ }
+ EXPORT_SYMBOL(rdma_restrack_count);
+
diff --git a/drivers/infiniband/core/restrack.h b/drivers/infiniband/core/restrack.h
index xxxxxxx..xxxxxxx 100644
--- a/drivers/infiniband/core/restrack.h