Skip to content

Commit 02d8883

Browse files
Leon Romanovskyjgunthorpe
authored andcommitted
RDMA/restrack: Add general infrastructure to track RDMA resources
The RDMA subsystem has very strict set of objects to work with, but it completely lacks tracking facilities and has no visibility of resource utilization. The following patch adds such infrastructure to keep track of RDMA resources to help with debugging of user space applications. The primary user of this infrastructure is RDMA nldev netlink (following patches), to be exposed to userspace via rdmatool, but it is not limited too that. At this stage, the main three objects (PD, CQ and QP) are added, and more will be added later. Reviewed-by: Mark Bloch <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Reviewed-by: Steve Wise <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent f66c8ba commit 02d8883

File tree

6 files changed

+346
-1
lines changed

6 files changed

+346
-1
lines changed

drivers/infiniband/core/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ ib_core-y := packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \
1212
device.o fmr_pool.o cache.o netlink.o \
1313
roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
1414
multicast.o mad.o smi.o agent.o mad_rmpp.o \
15-
security.o nldev.o
15+
security.o nldev.o restrack.o
1616

1717
ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
1818
ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o

drivers/infiniband/core/core_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <rdma/ib_verbs.h>
4141
#include <rdma/opa_addr.h>
4242
#include <rdma/ib_mad.h>
43+
#include <rdma/restrack.h>
4344
#include "mad_priv.h"
4445

4546
/* Total number of ports combined across all struct ib_devices's */

drivers/infiniband/core/device.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ struct ib_device *ib_alloc_device(size_t size)
263263
if (!device)
264264
return NULL;
265265

266+
rdma_restrack_init(&device->res);
267+
266268
device->dev.class = &ib_class;
267269
device_initialize(&device->dev);
268270

@@ -596,6 +598,8 @@ void ib_unregister_device(struct ib_device *device)
596598
}
597599
up_read(&lists_rwsem);
598600

601+
rdma_restrack_clean(&device->res);
602+
599603
ib_device_unregister_rdmacg(device);
600604
ib_device_unregister_sysfs(device);
601605

drivers/infiniband/core/restrack.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
2+
/*
3+
* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
4+
*/
5+
6+
#include <rdma/ib_verbs.h>
7+
#include <rdma/restrack.h>
8+
#include <linux/mutex.h>
9+
#include <linux/sched/task.h>
10+
#include <linux/uaccess.h>
11+
#include <linux/pid_namespace.h>
12+
13+
void rdma_restrack_init(struct rdma_restrack_root *res)
14+
{
15+
init_rwsem(&res->rwsem);
16+
}
17+
18+
void rdma_restrack_clean(struct rdma_restrack_root *res)
19+
{
20+
WARN_ON_ONCE(!hash_empty(res->hash));
21+
}
22+
23+
int rdma_restrack_count(struct rdma_restrack_root *res,
24+
enum rdma_restrack_type type,
25+
struct pid_namespace *ns)
26+
{
27+
struct rdma_restrack_entry *e;
28+
u32 cnt = 0;
29+
30+
down_read(&res->rwsem);
31+
hash_for_each_possible(res->hash, e, node, type) {
32+
if (ns == &init_pid_ns ||
33+
(!rdma_is_kernel_res(e) &&
34+
ns == task_active_pid_ns(e->task)))
35+
cnt++;
36+
}
37+
up_read(&res->rwsem);
38+
return cnt;
39+
}
40+
EXPORT_SYMBOL(rdma_restrack_count);
41+
42+
static void set_kern_name(struct rdma_restrack_entry *res)
43+
{
44+
enum rdma_restrack_type type = res->type;
45+
struct ib_qp *qp;
46+
47+
if (type != RDMA_RESTRACK_QP)
48+
/* PD and CQ types already have this name embedded in */
49+
return;
50+
51+
qp = container_of(res, struct ib_qp, res);
52+
if (!qp->pd) {
53+
WARN_ONCE(true, "XRC QPs are not supported\n");
54+
/* Survive, despite the programmer's error */
55+
res->kern_name = " ";
56+
return;
57+
}
58+
59+
res->kern_name = qp->pd->res.kern_name;
60+
}
61+
62+
static struct ib_device *res_to_dev(struct rdma_restrack_entry *res)
63+
{
64+
enum rdma_restrack_type type = res->type;
65+
struct ib_device *dev;
66+
struct ib_xrcd *xrcd;
67+
struct ib_pd *pd;
68+
struct ib_cq *cq;
69+
struct ib_qp *qp;
70+
71+
switch (type) {
72+
case RDMA_RESTRACK_PD:
73+
pd = container_of(res, struct ib_pd, res);
74+
dev = pd->device;
75+
break;
76+
case RDMA_RESTRACK_CQ:
77+
cq = container_of(res, struct ib_cq, res);
78+
dev = cq->device;
79+
break;
80+
case RDMA_RESTRACK_QP:
81+
qp = container_of(res, struct ib_qp, res);
82+
dev = qp->device;
83+
break;
84+
case RDMA_RESTRACK_XRCD:
85+
xrcd = container_of(res, struct ib_xrcd, res);
86+
dev = xrcd->device;
87+
break;
88+
default:
89+
WARN_ONCE(true, "Wrong resource tracking type %u\n", type);
90+
return NULL;
91+
}
92+
93+
return dev;
94+
}
95+
96+
void rdma_restrack_add(struct rdma_restrack_entry *res)
97+
{
98+
struct ib_device *dev = res_to_dev(res);
99+
100+
if (!dev)
101+
return;
102+
103+
if (!uaccess_kernel()) {
104+
get_task_struct(current);
105+
res->task = current;
106+
res->kern_name = NULL;
107+
} else {
108+
set_kern_name(res);
109+
res->task = NULL;
110+
}
111+
112+
kref_init(&res->kref);
113+
init_completion(&res->comp);
114+
res->valid = true;
115+
116+
down_write(&dev->res.rwsem);
117+
hash_add(dev->res.hash, &res->node, res->type);
118+
up_write(&dev->res.rwsem);
119+
}
120+
EXPORT_SYMBOL(rdma_restrack_add);
121+
122+
int __must_check rdma_restrack_get(struct rdma_restrack_entry *res)
123+
{
124+
return kref_get_unless_zero(&res->kref);
125+
}
126+
EXPORT_SYMBOL(rdma_restrack_get);
127+
128+
static void restrack_release(struct kref *kref)
129+
{
130+
struct rdma_restrack_entry *res;
131+
132+
res = container_of(kref, struct rdma_restrack_entry, kref);
133+
complete(&res->comp);
134+
}
135+
136+
int rdma_restrack_put(struct rdma_restrack_entry *res)
137+
{
138+
return kref_put(&res->kref, restrack_release);
139+
}
140+
EXPORT_SYMBOL(rdma_restrack_put);
141+
142+
void rdma_restrack_del(struct rdma_restrack_entry *res)
143+
{
144+
struct ib_device *dev;
145+
146+
if (!res->valid)
147+
return;
148+
149+
dev = res_to_dev(res);
150+
if (!dev)
151+
return;
152+
153+
rdma_restrack_put(res);
154+
155+
wait_for_completion(&res->comp);
156+
157+
down_write(&dev->res.rwsem);
158+
hash_del(&res->node);
159+
res->valid = false;
160+
if (res->task)
161+
put_task_struct(res->task);
162+
up_write(&dev->res.rwsem);
163+
}
164+
EXPORT_SYMBOL(rdma_restrack_del);

include/rdma/ib_verbs.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include <linux/uaccess.h>
6464
#include <linux/cgroup_rdma.h>
6565
#include <uapi/rdma/ib_user_verbs.h>
66+
#include <rdma/restrack.h>
6667

6768
#define IB_FW_VERSION_NAME_MAX ETHTOOL_FWVERS_LEN
6869

@@ -1525,6 +1526,7 @@ struct ib_pd {
15251526
* Implementation details of the RDMA core, don't use in drivers:
15261527
*/
15271528
struct ib_mr *__internal_mr;
1529+
struct rdma_restrack_entry res;
15281530
};
15291531

15301532
struct ib_xrcd {
@@ -1534,6 +1536,10 @@ struct ib_xrcd {
15341536

15351537
struct mutex tgt_qp_mutex;
15361538
struct list_head tgt_qp_list;
1539+
/*
1540+
* Implementation details of the RDMA core, don't use in drivers:
1541+
*/
1542+
struct rdma_restrack_entry res;
15371543
};
15381544

15391545
struct ib_ah {
@@ -1565,6 +1571,10 @@ struct ib_cq {
15651571
struct irq_poll iop;
15661572
struct work_struct work;
15671573
};
1574+
/*
1575+
* Implementation details of the RDMA core, don't use in drivers:
1576+
*/
1577+
struct rdma_restrack_entry res;
15681578
};
15691579

15701580
struct ib_srq {
@@ -1741,6 +1751,11 @@ struct ib_qp {
17411751
struct ib_rwq_ind_table *rwq_ind_tbl;
17421752
struct ib_qp_security *qp_sec;
17431753
u8 port;
1754+
1755+
/*
1756+
* Implementation details of the RDMA core, don't use in drivers:
1757+
*/
1758+
struct rdma_restrack_entry res;
17441759
};
17451760

17461761
struct ib_mr {
@@ -2347,6 +2362,10 @@ struct ib_device {
23472362
#endif
23482363

23492364
u32 index;
2365+
/*
2366+
* Implementation details of the RDMA core, don't use in drivers
2367+
*/
2368+
struct rdma_restrack_root res;
23502369

23512370
/**
23522371
* The following mandatory functions are used only at device

0 commit comments

Comments
 (0)