1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
6 #include <rdma/rdma_cm.h>
7 #include <rdma/ib_verbs.h>
8 #include <rdma/restrack.h>
9 #include <rdma/rdma_counter.h>
10 #include <linux/mutex.h>
11 #include <linux/sched/task.h>
12 #include <linux/pid_namespace.h>
18 * rdma_restrack_init() - initialize and allocate resource tracking
21 * Return: 0 on success
23 int rdma_restrack_init(struct ib_device
*dev
)
25 struct rdma_restrack_root
*rt
;
28 dev
->res
= kcalloc(RDMA_RESTRACK_MAX
, sizeof(*rt
), GFP_KERNEL
);
34 for (i
= 0; i
< RDMA_RESTRACK_MAX
; i
++)
35 xa_init_flags(&rt
[i
].xa
, XA_FLAGS_ALLOC
);
40 static const char *type2str(enum rdma_restrack_type type
)
42 static const char * const names
[RDMA_RESTRACK_MAX
] = {
43 [RDMA_RESTRACK_PD
] = "PD",
44 [RDMA_RESTRACK_CQ
] = "CQ",
45 [RDMA_RESTRACK_QP
] = "QP",
46 [RDMA_RESTRACK_CM_ID
] = "CM_ID",
47 [RDMA_RESTRACK_MR
] = "MR",
48 [RDMA_RESTRACK_CTX
] = "CTX",
49 [RDMA_RESTRACK_COUNTER
] = "COUNTER",
56 * rdma_restrack_clean() - clean resource tracking
59 void rdma_restrack_clean(struct ib_device
*dev
)
61 struct rdma_restrack_root
*rt
= dev
->res
;
62 struct rdma_restrack_entry
*e
;
63 char buf
[TASK_COMM_LEN
];
68 for (i
= 0 ; i
< RDMA_RESTRACK_MAX
; i
++) {
69 struct xarray
*xa
= &dev
->res
[i
].xa
;
75 pr_err("restrack: %s", CUT_HERE
);
76 dev_err(&dev
->dev
, "BUG: RESTRACK detected leak of resources\n");
78 xa_for_each(xa
, index
, e
) {
79 if (rdma_is_kernel_res(e
)) {
83 * There is no need to call get_task_struct here,
84 * because we can be here only if there are more
85 * get_task_struct() call than put_task_struct().
87 get_task_comm(buf
, e
->task
);
91 pr_err("restrack: %s %s object allocated by %s is not freed\n",
92 rdma_is_kernel_res(e
) ? "Kernel" :
94 type2str(e
->type
), owner
);
101 pr_err("restrack: %s", CUT_HERE
);
107 * rdma_restrack_count() - the current usage of specific object
109 * @type: actual type of object to operate
111 int rdma_restrack_count(struct ib_device
*dev
, enum rdma_restrack_type type
)
113 struct rdma_restrack_root
*rt
= &dev
->res
[type
];
114 struct rdma_restrack_entry
*e
;
115 XA_STATE(xas
, &rt
->xa
, 0);
119 xas_for_each(&xas
, e
, U32_MAX
)
124 EXPORT_SYMBOL(rdma_restrack_count
);
126 static void set_kern_name(struct rdma_restrack_entry
*res
)
131 case RDMA_RESTRACK_QP
:
132 pd
= container_of(res
, struct ib_qp
, res
)->pd
;
134 WARN_ONCE(true, "XRC QPs are not supported\n");
135 /* Survive, despite the programmer's error */
136 res
->kern_name
= " ";
139 case RDMA_RESTRACK_MR
:
140 pd
= container_of(res
, struct ib_mr
, res
)->pd
;
143 /* Other types set kern_name directly */
149 res
->kern_name
= pd
->res
.kern_name
;
152 static struct ib_device
*res_to_dev(struct rdma_restrack_entry
*res
)
155 case RDMA_RESTRACK_PD
:
156 return container_of(res
, struct ib_pd
, res
)->device
;
157 case RDMA_RESTRACK_CQ
:
158 return container_of(res
, struct ib_cq
, res
)->device
;
159 case RDMA_RESTRACK_QP
:
160 return container_of(res
, struct ib_qp
, res
)->device
;
161 case RDMA_RESTRACK_CM_ID
:
162 return container_of(res
, struct rdma_id_private
,
164 case RDMA_RESTRACK_MR
:
165 return container_of(res
, struct ib_mr
, res
)->device
;
166 case RDMA_RESTRACK_CTX
:
167 return container_of(res
, struct ib_ucontext
, res
)->device
;
168 case RDMA_RESTRACK_COUNTER
:
169 return container_of(res
, struct rdma_counter
, res
)->device
;
171 WARN_ONCE(true, "Wrong resource tracking type %u\n", res
->type
);
176 void rdma_restrack_set_task(struct rdma_restrack_entry
*res
,
180 res
->kern_name
= caller
;
185 put_task_struct(res
->task
);
186 get_task_struct(current
);
189 EXPORT_SYMBOL(rdma_restrack_set_task
);
192 * rdma_restrack_attach_task() - attach the task onto this resource
193 * @res: resource entry
194 * @task: the task to attach, the current task will be used if it is NULL.
196 void rdma_restrack_attach_task(struct rdma_restrack_entry
*res
,
197 struct task_struct
*task
)
200 put_task_struct(res
->task
);
201 get_task_struct(task
);
205 static void rdma_restrack_add(struct rdma_restrack_entry
*res
)
207 struct ib_device
*dev
= res_to_dev(res
);
208 struct rdma_restrack_root
*rt
;
214 rt
= &dev
->res
[res
->type
];
216 kref_init(&res
->kref
);
217 init_completion(&res
->comp
);
218 if (res
->type
== RDMA_RESTRACK_QP
) {
219 /* Special case to ensure that LQPN points to right QP */
220 struct ib_qp
*qp
= container_of(res
, struct ib_qp
, res
);
222 ret
= xa_insert(&rt
->xa
, qp
->qp_num
, res
, GFP_KERNEL
);
223 res
->id
= ret
? 0 : qp
->qp_num
;
224 } else if (res
->type
== RDMA_RESTRACK_COUNTER
) {
225 /* Special case to ensure that cntn points to right counter */
226 struct rdma_counter
*counter
;
228 counter
= container_of(res
, struct rdma_counter
, res
);
229 ret
= xa_insert(&rt
->xa
, counter
->id
, res
, GFP_KERNEL
);
230 res
->id
= ret
? 0 : counter
->id
;
232 ret
= xa_alloc_cyclic(&rt
->xa
, &res
->id
, res
, xa_limit_32b
,
233 &rt
->next_id
, GFP_KERNEL
);
241 * rdma_restrack_kadd() - add kernel object to the reource tracking database
242 * @res: resource entry
244 void rdma_restrack_kadd(struct rdma_restrack_entry
*res
)
249 rdma_restrack_add(res
);
251 EXPORT_SYMBOL(rdma_restrack_kadd
);
254 * rdma_restrack_uadd() - add user object to the reource tracking database
255 * @res: resource entry
257 void rdma_restrack_uadd(struct rdma_restrack_entry
*res
)
259 if ((res
->type
!= RDMA_RESTRACK_CM_ID
) &&
260 (res
->type
!= RDMA_RESTRACK_COUNTER
))
264 rdma_restrack_set_task(res
, NULL
);
265 res
->kern_name
= NULL
;
268 rdma_restrack_add(res
);
270 EXPORT_SYMBOL(rdma_restrack_uadd
);
272 int __must_check
rdma_restrack_get(struct rdma_restrack_entry
*res
)
274 return kref_get_unless_zero(&res
->kref
);
276 EXPORT_SYMBOL(rdma_restrack_get
);
279 * rdma_restrack_get_byid() - translate from ID to restrack object
281 * @type: resource track type
282 * @id: ID to take a look
284 * Return: Pointer to restrack entry or -ENOENT in case of error.
286 struct rdma_restrack_entry
*
287 rdma_restrack_get_byid(struct ib_device
*dev
,
288 enum rdma_restrack_type type
, u32 id
)
290 struct rdma_restrack_root
*rt
= &dev
->res
[type
];
291 struct rdma_restrack_entry
*res
;
294 res
= xa_load(&rt
->xa
, id
);
295 if (!res
|| !rdma_restrack_get(res
))
296 res
= ERR_PTR(-ENOENT
);
301 EXPORT_SYMBOL(rdma_restrack_get_byid
);
303 static void restrack_release(struct kref
*kref
)
305 struct rdma_restrack_entry
*res
;
307 res
= container_of(kref
, struct rdma_restrack_entry
, kref
);
308 complete(&res
->comp
);
311 int rdma_restrack_put(struct rdma_restrack_entry
*res
)
313 return kref_put(&res
->kref
, restrack_release
);
315 EXPORT_SYMBOL(rdma_restrack_put
);
317 void rdma_restrack_del(struct rdma_restrack_entry
*res
)
319 struct rdma_restrack_entry
*old
;
320 struct rdma_restrack_root
*rt
;
321 struct ib_device
*dev
;
326 dev
= res_to_dev(res
);
330 rt
= &dev
->res
[res
->type
];
332 old
= xa_erase(&rt
->xa
, res
->id
);
336 rdma_restrack_put(res
);
337 wait_for_completion(&res
->comp
);
341 put_task_struct(res
->task
);
345 EXPORT_SYMBOL(rdma_restrack_del
);