Skip to content

Commit 13ef553

Browse files
Leon Romanovskyjgunthorpe
authored andcommitted
RDMA/restrack: Count references to the verbs objects
Refactor the restrack code to make sure the kref inside the restrack entry properly kref's the object in which it is embedded. This slight change is needed for future conversions of MR and QP which are refcounted before the release and kfree. The ideal flow from ib_core perspective as follows: * Allocate ib_* structure with rdma_zalloc_*. * Set everything that is known to ib_core to that newly created object. * Initialize kref with restrack help * Call to driver specific allocation functions. * Insert into restrack DB .... * Return and release restrack with restrack_put. Largely this means a rdma_restrack_new() should be called near allocating the containing structure. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent d7ecab1 commit 13ef553

File tree

10 files changed

+70
-38
lines changed

10 files changed

+70
-38
lines changed

drivers/infiniband/core/cma.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -833,8 +833,6 @@ struct rdma_cm_id *__rdma_create_id(struct net *net,
833833
if (!id_priv)
834834
return ERR_PTR(-ENOMEM);
835835

836-
rdma_restrack_set_task(&id_priv->res, caller);
837-
id_priv->res.type = RDMA_RESTRACK_CM_ID;
838836
id_priv->state = RDMA_CM_IDLE;
839837
id_priv->id.context = context;
840838
id_priv->id.event_handler = event_handler;
@@ -854,6 +852,9 @@ struct rdma_cm_id *__rdma_create_id(struct net *net,
854852
id_priv->id.route.addr.dev_addr.net = get_net(net);
855853
id_priv->seq_num &= 0x00ffffff;
856854

855+
rdma_restrack_new(&id_priv->res, RDMA_RESTRACK_CM_ID);
856+
rdma_restrack_set_task(&id_priv->res, caller);
857+
857858
return &id_priv->id;
858859
}
859860
EXPORT_SYMBOL(__rdma_create_id);

drivers/infiniband/core/core_priv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <rdma/ib_mad.h>
4545
#include <rdma/restrack.h>
4646
#include "mad_priv.h"
47+
#include "restrack.h"
4748

4849
/* Total number of ports combined across all struct ib_devices's */
4950
#define RDMA_MAX_PORTS 8192
@@ -352,14 +353,14 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
352353
INIT_LIST_HEAD(&qp->rdma_mrs);
353354
INIT_LIST_HEAD(&qp->sig_mrs);
354355

356+
rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
355357
/*
356358
* We don't track XRC QPs for now, because they don't have PD
357359
* and more importantly they are created internaly by driver,
358360
* see mlx5 create_dev_resources() as an example.
359361
*/
360362
is_xrc = qp_type == IB_QPT_XRC_INI || qp_type == IB_QPT_XRC_TGT;
361363
if ((qp_type < IB_QPT_MAX && !is_xrc) || qp_type == IB_QPT_DRIVER) {
362-
qp->res.type = RDMA_RESTRACK_QP;
363364
if (uobj)
364365
rdma_restrack_uadd(&qp->res);
365366
else

drivers/infiniband/core/counters.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,
8080

8181
counter->device = dev;
8282
counter->port = port;
83-
counter->res.type = RDMA_RESTRACK_COUNTER;
84-
counter->stats = dev->ops.counter_alloc_stats(counter);
83+
84+
rdma_restrack_new(&counter->res, RDMA_RESTRACK_COUNTER);
85+
counter->stats = dev->ops.counter_alloc_stats(counter);
8586
if (!counter->stats)
8687
goto err_stats;
8788

@@ -107,6 +108,7 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,
107108
mutex_unlock(&port_counter->lock);
108109
kfree(counter->stats);
109110
err_stats:
111+
rdma_restrack_put(&counter->res);
110112
kfree(counter);
111113
return NULL;
112114
}

drivers/infiniband/core/cq.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,13 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe,
235235
if (!cq->wc)
236236
goto out_free_cq;
237237

238-
cq->res.type = RDMA_RESTRACK_CQ;
238+
rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
239239
rdma_restrack_set_task(&cq->res, caller);
240240

241241
ret = dev->ops.create_cq(cq, &cq_attr, NULL);
242242
if (ret)
243243
goto out_free_wc;
244244

245-
rdma_restrack_kadd(&cq->res);
246-
247245
rdma_dim_init(cq);
248246

249247
switch (cq->poll_ctx) {
@@ -269,14 +267,15 @@ struct ib_cq *__ib_alloc_cq(struct ib_device *dev, void *private, int nr_cqe,
269267
goto out_destroy_cq;
270268
}
271269

270+
rdma_restrack_kadd(&cq->res);
272271
trace_cq_alloc(cq, nr_cqe, comp_vector, poll_ctx);
273272
return cq;
274273

275274
out_destroy_cq:
276275
rdma_dim_destroy(cq);
277-
rdma_restrack_del(&cq->res);
278276
cq->device->ops.destroy_cq(cq, NULL);
279277
out_free_wc:
278+
rdma_restrack_put(&cq->res);
280279
kfree(cq->wc);
281280
out_free_cq:
282281
kfree(cq);

drivers/infiniband/core/restrack.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,21 @@ void rdma_restrack_attach_task(struct rdma_restrack_entry *res,
202202
res->task = task;
203203
}
204204

205+
/**
206+
* rdma_restrack_new() - Initializes new restrack entry to allow _put() interface
207+
* to release memory in fully automatic way.
208+
* @res - Entry to initialize
209+
* @type - REstrack type
210+
*/
211+
void rdma_restrack_new(struct rdma_restrack_entry *res,
212+
enum rdma_restrack_type type)
213+
{
214+
kref_init(&res->kref);
215+
init_completion(&res->comp);
216+
res->type = type;
217+
}
218+
EXPORT_SYMBOL(rdma_restrack_new);
219+
205220
static void rdma_restrack_add(struct rdma_restrack_entry *res)
206221
{
207222
struct ib_device *dev = res_to_dev(res);
@@ -213,8 +228,6 @@ static void rdma_restrack_add(struct rdma_restrack_entry *res)
213228

214229
rt = &dev->res[res->type];
215230

216-
kref_init(&res->kref);
217-
init_completion(&res->comp);
218231
if (res->type == RDMA_RESTRACK_QP) {
219232
/* Special case to ensure that LQPN points to right QP */
220233
struct ib_qp *qp = container_of(res, struct ib_qp, res);
@@ -305,6 +318,10 @@ static void restrack_release(struct kref *kref)
305318
struct rdma_restrack_entry *res;
306319

307320
res = container_of(kref, struct rdma_restrack_entry, kref);
321+
if (res->task) {
322+
put_task_struct(res->task);
323+
res->task = NULL;
324+
}
308325
complete(&res->comp);
309326
}
310327

@@ -314,14 +331,23 @@ int rdma_restrack_put(struct rdma_restrack_entry *res)
314331
}
315332
EXPORT_SYMBOL(rdma_restrack_put);
316333

334+
/**
335+
* rdma_restrack_del() - delete object from the reource tracking database
336+
* @res: resource entry
337+
*/
317338
void rdma_restrack_del(struct rdma_restrack_entry *res)
318339
{
319340
struct rdma_restrack_entry *old;
320341
struct rdma_restrack_root *rt;
321342
struct ib_device *dev;
322343

323-
if (!res->valid)
324-
goto out;
344+
if (!res->valid) {
345+
if (res->task) {
346+
put_task_struct(res->task);
347+
res->task = NULL;
348+
}
349+
return;
350+
}
325351

326352
dev = res_to_dev(res);
327353
if (WARN_ON(!dev))
@@ -330,16 +356,12 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)
330356
rt = &dev->res[res->type];
331357

332358
old = xa_erase(&rt->xa, res->id);
359+
if (res->type == RDMA_RESTRACK_MR || res->type == RDMA_RESTRACK_QP)
360+
return;
333361
WARN_ON(old != res);
334362
res->valid = false;
335363

336364
rdma_restrack_put(res);
337365
wait_for_completion(&res->comp);
338-
339-
out:
340-
if (res->task) {
341-
put_task_struct(res->task);
342-
res->task = NULL;
343-
}
344366
}
345367
EXPORT_SYMBOL(rdma_restrack_del);

drivers/infiniband/core/restrack.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ struct rdma_restrack_root {
2525

2626
int rdma_restrack_init(struct ib_device *dev);
2727
void rdma_restrack_clean(struct ib_device *dev);
28+
void rdma_restrack_del(struct rdma_restrack_entry *res);
29+
void rdma_restrack_new(struct rdma_restrack_entry *res,
30+
enum rdma_restrack_type type);
2831
void rdma_restrack_attach_task(struct rdma_restrack_entry *res,
2932
struct task_struct *task);
3033
#endif /* _RDMA_CORE_RESTRACK_H_ */

drivers/infiniband/core/uverbs_cmd.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,11 @@ int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs)
218218
if (!ucontext)
219219
return -ENOMEM;
220220

221-
ucontext->res.type = RDMA_RESTRACK_CTX;
222221
ucontext->device = ib_dev;
223222
ucontext->ufile = ufile;
224223
xa_init_flags(&ucontext->mmap_xa, XA_FLAGS_ALLOC);
224+
225+
rdma_restrack_new(&ucontext->res, RDMA_RESTRACK_CTX);
225226
attrs->context = ucontext;
226227
return 0;
227228
}
@@ -313,6 +314,7 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs)
313314
err_uobj:
314315
rdma_alloc_abort_uobject(uobj, attrs, false);
315316
err_ucontext:
317+
rdma_restrack_put(&attrs->context->res);
316318
kfree(attrs->context);
317319
attrs->context = NULL;
318320
return ret;
@@ -439,8 +441,8 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)
439441
pd->device = ib_dev;
440442
pd->uobject = uobj;
441443
atomic_set(&pd->usecnt, 0);
442-
pd->res.type = RDMA_RESTRACK_PD;
443444

445+
rdma_restrack_new(&pd->res, RDMA_RESTRACK_PD);
444446
ret = ib_dev->ops.alloc_pd(pd, &attrs->driver_udata);
445447
if (ret)
446448
goto err_alloc;
@@ -453,6 +455,7 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)
453455
return uverbs_response(attrs, &resp, sizeof(resp));
454456

455457
err_alloc:
458+
rdma_restrack_put(&pd->res);
456459
kfree(pd);
457460
err:
458461
uobj_alloc_abort(uobj, attrs);
@@ -742,8 +745,9 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
742745
mr->sig_attrs = NULL;
743746
mr->uobject = uobj;
744747
atomic_inc(&pd->usecnt);
745-
mr->res.type = RDMA_RESTRACK_MR;
746748
mr->iova = cmd.hca_va;
749+
750+
rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
747751
rdma_restrack_uadd(&mr->res);
748752

749753
uobj->object = mr;
@@ -1002,8 +1006,8 @@ static int create_cq(struct uverbs_attr_bundle *attrs,
10021006
cq->event_handler = ib_uverbs_cq_event_handler;
10031007
cq->cq_context = ev_file ? &ev_file->ev_queue : NULL;
10041008
atomic_set(&cq->usecnt, 0);
1005-
cq->res.type = RDMA_RESTRACK_CQ;
10061009

1010+
rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
10071011
ret = ib_dev->ops.create_cq(cq, &attr, &attrs->driver_udata);
10081012
if (ret)
10091013
goto err_free;
@@ -1021,6 +1025,7 @@ static int create_cq(struct uverbs_attr_bundle *attrs,
10211025
return uverbs_response(attrs, &resp, sizeof(resp));
10221026

10231027
err_free:
1028+
rdma_restrack_put(&cq->res);
10241029
kfree(cq);
10251030
err_file:
10261031
if (ev_file)

drivers/infiniband/core/uverbs_std_types_cq.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <rdma/uverbs_std_types.h>
3434
#include "rdma_core.h"
3535
#include "uverbs.h"
36+
#include "restrack.h"
3637

3738
static int uverbs_free_cq(struct ib_uobject *uobject,
3839
enum rdma_remove_reason why,
@@ -123,8 +124,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
123124
cq->event_handler = ib_uverbs_cq_event_handler;
124125
cq->cq_context = ev_file ? &ev_file->ev_queue : NULL;
125126
atomic_set(&cq->usecnt, 0);
126-
cq->res.type = RDMA_RESTRACK_CQ;
127127

128+
rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
128129
ret = ib_dev->ops.create_cq(cq, &attr, &attrs->driver_udata);
129130
if (ret)
130131
goto err_free;
@@ -139,6 +140,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
139140
return ret;
140141

141142
err_free:
143+
rdma_restrack_put(&cq->res);
142144
kfree(cq);
143145
err_event_file:
144146
if (obj->uevent.event_file)

drivers/infiniband/core/verbs.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,12 @@ struct ib_pd *__ib_alloc_pd(struct ib_device *device, unsigned int flags,
272272
atomic_set(&pd->usecnt, 0);
273273
pd->flags = flags;
274274

275-
pd->res.type = RDMA_RESTRACK_PD;
275+
rdma_restrack_new(&pd->res, RDMA_RESTRACK_PD);
276276
rdma_restrack_set_task(&pd->res, caller);
277277

278278
ret = device->ops.alloc_pd(pd, NULL);
279279
if (ret) {
280+
rdma_restrack_put(&pd->res);
280281
kfree(pd);
281282
return ERR_PTR(ret);
282283
}
@@ -1996,11 +1997,13 @@ struct ib_cq *__ib_create_cq(struct ib_device *device,
19961997
cq->event_handler = event_handler;
19971998
cq->cq_context = cq_context;
19981999
atomic_set(&cq->usecnt, 0);
1999-
cq->res.type = RDMA_RESTRACK_CQ;
2000+
2001+
rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
20002002
rdma_restrack_set_task(&cq->res, caller);
20012003

20022004
ret = device->ops.create_cq(cq, cq_attr, NULL);
20032005
if (ret) {
2006+
rdma_restrack_put(&cq->res);
20042007
kfree(cq);
20052008
return ERR_PTR(ret);
20062009
}
@@ -2076,7 +2079,8 @@ struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
20762079
mr->pd = pd;
20772080
mr->dm = NULL;
20782081
atomic_inc(&pd->usecnt);
2079-
mr->res.type = RDMA_RESTRACK_MR;
2082+
2083+
rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
20802084
rdma_restrack_kadd(&mr->res);
20812085

20822086
return mr;
@@ -2156,11 +2160,11 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
21562160
mr->uobject = NULL;
21572161
atomic_inc(&pd->usecnt);
21582162
mr->need_inval = false;
2159-
mr->res.type = RDMA_RESTRACK_MR;
2160-
rdma_restrack_kadd(&mr->res);
21612163
mr->type = mr_type;
21622164
mr->sig_attrs = NULL;
21632165

2166+
rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
2167+
rdma_restrack_kadd(&mr->res);
21642168
out:
21652169
trace_mr_alloc(pd, mr_type, max_num_sg, mr);
21662170
return mr;
@@ -2216,11 +2220,11 @@ struct ib_mr *ib_alloc_mr_integrity(struct ib_pd *pd,
22162220
mr->uobject = NULL;
22172221
atomic_inc(&pd->usecnt);
22182222
mr->need_inval = false;
2219-
mr->res.type = RDMA_RESTRACK_MR;
2220-
rdma_restrack_kadd(&mr->res);
22212223
mr->type = IB_MR_TYPE_INTEGRITY;
22222224
mr->sig_attrs = sig_attrs;
22232225

2226+
rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
2227+
rdma_restrack_kadd(&mr->res);
22242228
out:
22252229
trace_mr_integ_alloc(pd, max_num_data_sg, max_num_meta_sg, mr);
22262230
return mr;

include/rdma/restrack.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,6 @@ int rdma_restrack_count(struct ib_device *dev,
110110
void rdma_restrack_kadd(struct rdma_restrack_entry *res);
111111
void rdma_restrack_uadd(struct rdma_restrack_entry *res);
112112

113-
/**
114-
* rdma_restrack_del() - delete object from the reource tracking database
115-
* @res: resource entry
116-
* @type: actual type of object to operate
117-
*/
118-
void rdma_restrack_del(struct rdma_restrack_entry *res);
119-
120113
/**
121114
* rdma_is_kernel_res() - check the owner of resource
122115
* @res: resource entry

0 commit comments

Comments
 (0)