1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3  * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
4  */
5 
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>
12 
13 #include "cma_priv.h"
14 
15 static int fill_res_noop(struct sk_buff *msg,
16 			 struct rdma_restrack_entry *entry)
17 {
18 	return 0;
19 }
20 
21 void rdma_restrack_init(struct rdma_restrack_root *res)
22 {
23 	init_rwsem(&res->rwsem);
24 	res->fill_res_entry = fill_res_noop;
25 }
26 
27 static const char *type2str(enum rdma_restrack_type type)
28 {
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",
35 	};
36 
37 	return names[type];
38 };
39 
40 void rdma_restrack_clean(struct rdma_restrack_root *res)
41 {
42 	struct rdma_restrack_entry *e;
43 	char buf[TASK_COMM_LEN];
44 	struct ib_device *dev;
45 	const char *owner;
46 	int bkt;
47 
48 	if (hash_empty(res->hash))
49 		return;
50 
51 	dev = container_of(res, struct ib_device, res);
52 	pr_err("restrack: %s", CUT_HERE);
53 	dev_err(&dev->dev, "BUG: RESTRACK detected leak of resources\n");
54 	hash_for_each(res->hash, bkt, e, node) {
55 		if (rdma_is_kernel_res(e)) {
56 			owner = e->kern_name;
57 		} else {
58 			/*
59 			 * There is no need to call get_task_struct here,
60 			 * because we can be here only if there are more
61 			 * get_task_struct() call than put_task_struct().
62 			 */
63 			get_task_comm(buf, e->task);
64 			owner = buf;
65 		}
66 
67 		pr_err("restrack: %s %s object allocated by %s is not freed\n",
68 		       rdma_is_kernel_res(e) ? "Kernel" : "User",
69 		       type2str(e->type), owner);
70 	}
71 	pr_err("restrack: %s", CUT_HERE);
72 }
73 
74 int rdma_restrack_count(struct rdma_restrack_root *res,
75 			enum rdma_restrack_type type,
76 			struct pid_namespace *ns)
77 {
78 	struct rdma_restrack_entry *e;
79 	u32 cnt = 0;
80 
81 	down_read(&res->rwsem);
82 	hash_for_each_possible(res->hash, e, node, type) {
83 		if (ns == &init_pid_ns ||
84 		    (!rdma_is_kernel_res(e) &&
85 		     ns == task_active_pid_ns(e->task)))
86 			cnt++;
87 	}
88 	up_read(&res->rwsem);
89 	return cnt;
90 }
91 EXPORT_SYMBOL(rdma_restrack_count);
92 
93 static void set_kern_name(struct rdma_restrack_entry *res)
94 {
95 	struct ib_pd *pd;
96 
97 	switch (res->type) {
98 	case RDMA_RESTRACK_QP:
99 		pd = container_of(res, struct ib_qp, res)->pd;
100 		if (!pd) {
101 			WARN_ONCE(true, "XRC QPs are not supported\n");
102 			/* Survive, despite the programmer's error */
103 			res->kern_name = " ";
104 		}
105 		break;
106 	case RDMA_RESTRACK_MR:
107 		pd = container_of(res, struct ib_mr, res)->pd;
108 		break;
109 	default:
110 		/* Other types set kern_name directly */
111 		pd = NULL;
112 		break;
113 	}
114 
115 	if (pd)
116 		res->kern_name = pd->res.kern_name;
117 }
118 
119 static struct ib_device *res_to_dev(struct rdma_restrack_entry *res)
120 {
121 	switch (res->type) {
122 	case RDMA_RESTRACK_PD:
123 		return container_of(res, struct ib_pd, res)->device;
124 	case RDMA_RESTRACK_CQ:
125 		return container_of(res, struct ib_cq, res)->device;
126 	case RDMA_RESTRACK_QP:
127 		return container_of(res, struct ib_qp, res)->device;
128 	case RDMA_RESTRACK_CM_ID:
129 		return container_of(res, struct rdma_id_private,
130 				    res)->id.device;
131 	case RDMA_RESTRACK_MR:
132 		return container_of(res, struct ib_mr, res)->device;
133 	default:
134 		WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
135 		return NULL;
136 	}
137 }
138 
139 static bool res_is_user(struct rdma_restrack_entry *res)
140 {
141 	switch (res->type) {
142 	case RDMA_RESTRACK_PD:
143 		return container_of(res, struct ib_pd, res)->uobject;
144 	case RDMA_RESTRACK_CQ:
145 		return container_of(res, struct ib_cq, res)->uobject;
146 	case RDMA_RESTRACK_QP:
147 		return container_of(res, struct ib_qp, res)->uobject;
148 	case RDMA_RESTRACK_CM_ID:
149 		return !res->kern_name;
150 	case RDMA_RESTRACK_MR:
151 		return container_of(res, struct ib_mr, res)->pd->uobject;
152 	default:
153 		WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
154 		return false;
155 	}
156 }
157 
158 void rdma_restrack_set_task(struct rdma_restrack_entry *res,
159 			    const char *caller)
160 {
161 	if (caller) {
162 		res->kern_name = caller;
163 		return;
164 	}
165 
166 	if (res->task)
167 		put_task_struct(res->task);
168 	get_task_struct(current);
169 	res->task = current;
170 }
171 EXPORT_SYMBOL(rdma_restrack_set_task);
172 
173 void rdma_restrack_add(struct rdma_restrack_entry *res)
174 {
175 	struct ib_device *dev = res_to_dev(res);
176 
177 	if (!dev)
178 		return;
179 
180 	if (res->type != RDMA_RESTRACK_CM_ID || !res_is_user(res))
181 		res->task = NULL;
182 
183 	if (res_is_user(res)) {
184 		if (!res->task)
185 			rdma_restrack_set_task(res, NULL);
186 		res->kern_name = NULL;
187 	} else {
188 		set_kern_name(res);
189 	}
190 
191 	kref_init(&res->kref);
192 	init_completion(&res->comp);
193 	res->valid = true;
194 
195 	down_write(&dev->res.rwsem);
196 	hash_add(dev->res.hash, &res->node, res->type);
197 	up_write(&dev->res.rwsem);
198 }
199 EXPORT_SYMBOL(rdma_restrack_add);
200 
201 int __must_check rdma_restrack_get(struct rdma_restrack_entry *res)
202 {
203 	return kref_get_unless_zero(&res->kref);
204 }
205 EXPORT_SYMBOL(rdma_restrack_get);
206 
207 static void restrack_release(struct kref *kref)
208 {
209 	struct rdma_restrack_entry *res;
210 
211 	res = container_of(kref, struct rdma_restrack_entry, kref);
212 	complete(&res->comp);
213 }
214 
215 int rdma_restrack_put(struct rdma_restrack_entry *res)
216 {
217 	return kref_put(&res->kref, restrack_release);
218 }
219 EXPORT_SYMBOL(rdma_restrack_put);
220 
221 void rdma_restrack_del(struct rdma_restrack_entry *res)
222 {
223 	struct ib_device *dev;
224 
225 	if (!res->valid)
226 		goto out;
227 
228 	dev = res_to_dev(res);
229 	if (!dev)
230 		return;
231 
232 	rdma_restrack_put(res);
233 
234 	wait_for_completion(&res->comp);
235 
236 	down_write(&dev->res.rwsem);
237 	hash_del(&res->node);
238 	res->valid = false;
239 	up_write(&dev->res.rwsem);
240 
241 out:
242 	if (res->task) {
243 		put_task_struct(res->task);
244 		res->task = NULL;
245 	}
246 }
247 EXPORT_SYMBOL(rdma_restrack_del);
248