1 /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
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 void rdma_restrack_init(struct rdma_restrack_root *res)
17 init_rwsem(&res->rwsem);
20 void rdma_restrack_clean(struct rdma_restrack_root *res)
22 WARN_ON_ONCE(!hash_empty(res->hash));
25 int rdma_restrack_count(struct rdma_restrack_root *res,
26 enum rdma_restrack_type type,
27 struct pid_namespace *ns)
29 struct rdma_restrack_entry *e;
32 down_read(&res->rwsem);
33 hash_for_each_possible(res->hash, e, node, type) {
34 if (ns == &init_pid_ns ||
35 (!rdma_is_kernel_res(e) &&
36 ns == task_active_pid_ns(e->task)))
42 EXPORT_SYMBOL(rdma_restrack_count);
44 static void set_kern_name(struct rdma_restrack_entry *res)
49 case RDMA_RESTRACK_QP:
50 pd = container_of(res, struct ib_qp, res)->pd;
52 WARN_ONCE(true, "XRC QPs are not supported\n");
53 /* Survive, despite the programmer's error */
57 case RDMA_RESTRACK_MR:
58 pd = container_of(res, struct ib_mr, res)->pd;
61 /* Other types set kern_name directly */
67 res->kern_name = pd->res.kern_name;
70 static struct ib_device *res_to_dev(struct rdma_restrack_entry *res)
73 case RDMA_RESTRACK_PD:
74 return container_of(res, struct ib_pd, res)->device;
75 case RDMA_RESTRACK_CQ:
76 return container_of(res, struct ib_cq, res)->device;
77 case RDMA_RESTRACK_QP:
78 return container_of(res, struct ib_qp, res)->device;
79 case RDMA_RESTRACK_CM_ID:
80 return container_of(res, struct rdma_id_private,
82 case RDMA_RESTRACK_MR:
83 return container_of(res, struct ib_mr, res)->device;
85 WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
90 static bool res_is_user(struct rdma_restrack_entry *res)
93 case RDMA_RESTRACK_PD:
94 return container_of(res, struct ib_pd, res)->uobject;
95 case RDMA_RESTRACK_CQ:
96 return container_of(res, struct ib_cq, res)->uobject;
97 case RDMA_RESTRACK_QP:
98 return container_of(res, struct ib_qp, res)->uobject;
99 case RDMA_RESTRACK_CM_ID:
100 return !res->kern_name;
101 case RDMA_RESTRACK_MR:
102 return container_of(res, struct ib_mr, res)->pd->uobject;
104 WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
109 void rdma_restrack_add(struct rdma_restrack_entry *res)
111 struct ib_device *dev = res_to_dev(res);
116 if (res_is_user(res)) {
118 rdma_restrack_set_task(res, current);
119 res->kern_name = NULL;
125 kref_init(&res->kref);
126 init_completion(&res->comp);
129 down_write(&dev->res.rwsem);
130 hash_add(dev->res.hash, &res->node, res->type);
131 up_write(&dev->res.rwsem);
133 EXPORT_SYMBOL(rdma_restrack_add);
135 int __must_check rdma_restrack_get(struct rdma_restrack_entry *res)
137 return kref_get_unless_zero(&res->kref);
139 EXPORT_SYMBOL(rdma_restrack_get);
141 static void restrack_release(struct kref *kref)
143 struct rdma_restrack_entry *res;
145 res = container_of(kref, struct rdma_restrack_entry, kref);
146 complete(&res->comp);
149 int rdma_restrack_put(struct rdma_restrack_entry *res)
151 return kref_put(&res->kref, restrack_release);
153 EXPORT_SYMBOL(rdma_restrack_put);
155 void rdma_restrack_del(struct rdma_restrack_entry *res)
157 struct ib_device *dev;
162 dev = res_to_dev(res);
166 rdma_restrack_put(res);
168 wait_for_completion(&res->comp);
170 down_write(&dev->res.rwsem);
171 hash_del(&res->node);
174 put_task_struct(res->task);
175 up_write(&dev->res.rwsem);
177 EXPORT_SYMBOL(rdma_restrack_del);