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 <linux/mutex.h>
10 #include <linux/sched/task.h>
11 #include <linux/pid_namespace.h>
15 static int fill_res_noop(struct sk_buff
*msg
,
16 struct rdma_restrack_entry
*entry
)
21 void rdma_restrack_init(struct rdma_restrack_root
*res
)
23 init_rwsem(&res
->rwsem
);
24 res
->fill_res_entry
= fill_res_noop
;
27 static const char *type2str(enum rdma_restrack_type type
)
29 static const char * const names
[RDMA_RESTRACK_MAX
] = {
30 [RDMA_RESTRACK_PD
] = "PD",
31 [RDMA_RESTRACK_CQ
] = "CQ",
32 [RDMA_RESTRACK_QP
] = "QP",
33 [RDMA_RESTRACK_CM_ID
] = "CM_ID",
34 [RDMA_RESTRACK_MR
] = "MR",
40 void rdma_restrack_clean(struct rdma_restrack_root
*res
)
42 struct rdma_restrack_entry
*e
;
43 char buf
[TASK_COMM_LEN
];
44 struct ib_device
*dev
;
48 if (hash_empty(res
->hash
))
51 dev
= container_of(res
, struct ib_device
, res
);
52 pr_err("restrack: %s", CUT_HERE
);
53 pr_err("restrack: BUG: RESTRACK detected leak of resources on %s\n",
55 hash_for_each(res
->hash
, bkt
, e
, node
) {
56 if (rdma_is_kernel_res(e
)) {
60 * There is no need to call get_task_struct here,
61 * because we can be here only if there are more
62 * get_task_struct() call than put_task_struct().
64 get_task_comm(buf
, e
->task
);
68 pr_err("restrack: %s %s object allocated by %s is not freed\n",
69 rdma_is_kernel_res(e
) ? "Kernel" : "User",
70 type2str(e
->type
), owner
);
72 pr_err("restrack: %s", CUT_HERE
);
75 int rdma_restrack_count(struct rdma_restrack_root
*res
,
76 enum rdma_restrack_type type
,
77 struct pid_namespace
*ns
)
79 struct rdma_restrack_entry
*e
;
82 down_read(&res
->rwsem
);
83 hash_for_each_possible(res
->hash
, e
, node
, type
) {
84 if (ns
== &init_pid_ns
||
85 (!rdma_is_kernel_res(e
) &&
86 ns
== task_active_pid_ns(e
->task
)))
92 EXPORT_SYMBOL(rdma_restrack_count
);
94 static void set_kern_name(struct rdma_restrack_entry
*res
)
99 case RDMA_RESTRACK_QP
:
100 pd
= container_of(res
, struct ib_qp
, res
)->pd
;
102 WARN_ONCE(true, "XRC QPs are not supported\n");
103 /* Survive, despite the programmer's error */
104 res
->kern_name
= " ";
107 case RDMA_RESTRACK_MR
:
108 pd
= container_of(res
, struct ib_mr
, res
)->pd
;
111 /* Other types set kern_name directly */
117 res
->kern_name
= pd
->res
.kern_name
;
120 static struct ib_device
*res_to_dev(struct rdma_restrack_entry
*res
)
123 case RDMA_RESTRACK_PD
:
124 return container_of(res
, struct ib_pd
, res
)->device
;
125 case RDMA_RESTRACK_CQ
:
126 return container_of(res
, struct ib_cq
, res
)->device
;
127 case RDMA_RESTRACK_QP
:
128 return container_of(res
, struct ib_qp
, res
)->device
;
129 case RDMA_RESTRACK_CM_ID
:
130 return container_of(res
, struct rdma_id_private
,
132 case RDMA_RESTRACK_MR
:
133 return container_of(res
, struct ib_mr
, res
)->device
;
135 WARN_ONCE(true, "Wrong resource tracking type %u\n", res
->type
);
140 static bool res_is_user(struct rdma_restrack_entry
*res
)
143 case RDMA_RESTRACK_PD
:
144 return container_of(res
, struct ib_pd
, res
)->uobject
;
145 case RDMA_RESTRACK_CQ
:
146 return container_of(res
, struct ib_cq
, res
)->uobject
;
147 case RDMA_RESTRACK_QP
:
148 return container_of(res
, struct ib_qp
, res
)->uobject
;
149 case RDMA_RESTRACK_CM_ID
:
150 return !res
->kern_name
;
151 case RDMA_RESTRACK_MR
:
152 return container_of(res
, struct ib_mr
, res
)->pd
->uobject
;
154 WARN_ONCE(true, "Wrong resource tracking type %u\n", res
->type
);
159 void rdma_restrack_add(struct rdma_restrack_entry
*res
)
161 struct ib_device
*dev
= res_to_dev(res
);
166 if (res
->type
!= RDMA_RESTRACK_CM_ID
|| !res_is_user(res
))
169 if (res_is_user(res
)) {
171 rdma_restrack_set_task(res
, current
);
172 res
->kern_name
= NULL
;
177 kref_init(&res
->kref
);
178 init_completion(&res
->comp
);
181 down_write(&dev
->res
.rwsem
);
182 hash_add(dev
->res
.hash
, &res
->node
, res
->type
);
183 up_write(&dev
->res
.rwsem
);
185 EXPORT_SYMBOL(rdma_restrack_add
);
187 int __must_check
rdma_restrack_get(struct rdma_restrack_entry
*res
)
189 return kref_get_unless_zero(&res
->kref
);
191 EXPORT_SYMBOL(rdma_restrack_get
);
193 static void restrack_release(struct kref
*kref
)
195 struct rdma_restrack_entry
*res
;
197 res
= container_of(kref
, struct rdma_restrack_entry
, kref
);
198 complete(&res
->comp
);
201 int rdma_restrack_put(struct rdma_restrack_entry
*res
)
203 return kref_put(&res
->kref
, restrack_release
);
205 EXPORT_SYMBOL(rdma_restrack_put
);
207 void rdma_restrack_del(struct rdma_restrack_entry
*res
)
209 struct ib_device
*dev
;
214 dev
= res_to_dev(res
);
218 rdma_restrack_put(res
);
220 wait_for_completion(&res
->comp
);
222 down_write(&dev
->res
.rwsem
);
223 hash_del(&res
->node
);
225 up_write(&dev
->res
.rwsem
);
229 put_task_struct(res
->task
);
233 EXPORT_SYMBOL(rdma_restrack_del
);