1 /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
3 * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
6 #include <rdma/ib_verbs.h>
7 #include <rdma/restrack.h>
8 #include <linux/mutex.h>
9 #include <linux/sched/task.h>
10 #include <linux/uaccess.h>
11 #include <linux/pid_namespace.h>
13 void rdma_restrack_init(struct rdma_restrack_root
*res
)
15 init_rwsem(&res
->rwsem
);
18 void rdma_restrack_clean(struct rdma_restrack_root
*res
)
20 WARN_ON_ONCE(!hash_empty(res
->hash
));
23 int rdma_restrack_count(struct rdma_restrack_root
*res
,
24 enum rdma_restrack_type type
,
25 struct pid_namespace
*ns
)
27 struct rdma_restrack_entry
*e
;
30 down_read(&res
->rwsem
);
31 hash_for_each_possible(res
->hash
, e
, node
, type
) {
32 if (ns
== &init_pid_ns
||
33 (!rdma_is_kernel_res(e
) &&
34 ns
== task_active_pid_ns(e
->task
)))
40 EXPORT_SYMBOL(rdma_restrack_count
);
42 static void set_kern_name(struct rdma_restrack_entry
*res
)
44 enum rdma_restrack_type type
= res
->type
;
47 if (type
!= RDMA_RESTRACK_QP
)
48 /* PD and CQ types already have this name embedded in */
51 qp
= container_of(res
, struct ib_qp
, res
);
53 WARN_ONCE(true, "XRC QPs are not supported\n");
54 /* Survive, despite the programmer's error */
59 res
->kern_name
= qp
->pd
->res
.kern_name
;
62 static struct ib_device
*res_to_dev(struct rdma_restrack_entry
*res
)
64 enum rdma_restrack_type type
= res
->type
;
65 struct ib_device
*dev
;
72 case RDMA_RESTRACK_PD
:
73 pd
= container_of(res
, struct ib_pd
, res
);
76 case RDMA_RESTRACK_CQ
:
77 cq
= container_of(res
, struct ib_cq
, res
);
80 case RDMA_RESTRACK_QP
:
81 qp
= container_of(res
, struct ib_qp
, res
);
84 case RDMA_RESTRACK_XRCD
:
85 xrcd
= container_of(res
, struct ib_xrcd
, res
);
89 WARN_ONCE(true, "Wrong resource tracking type %u\n", type
);
96 void rdma_restrack_add(struct rdma_restrack_entry
*res
)
98 struct ib_device
*dev
= res_to_dev(res
);
103 if (!uaccess_kernel()) {
104 get_task_struct(current
);
106 res
->kern_name
= NULL
;
112 kref_init(&res
->kref
);
113 init_completion(&res
->comp
);
116 down_write(&dev
->res
.rwsem
);
117 hash_add(dev
->res
.hash
, &res
->node
, res
->type
);
118 up_write(&dev
->res
.rwsem
);
120 EXPORT_SYMBOL(rdma_restrack_add
);
122 int __must_check
rdma_restrack_get(struct rdma_restrack_entry
*res
)
124 return kref_get_unless_zero(&res
->kref
);
126 EXPORT_SYMBOL(rdma_restrack_get
);
128 static void restrack_release(struct kref
*kref
)
130 struct rdma_restrack_entry
*res
;
132 res
= container_of(kref
, struct rdma_restrack_entry
, kref
);
133 complete(&res
->comp
);
136 int rdma_restrack_put(struct rdma_restrack_entry
*res
)
138 return kref_put(&res
->kref
, restrack_release
);
140 EXPORT_SYMBOL(rdma_restrack_put
);
142 void rdma_restrack_del(struct rdma_restrack_entry
*res
)
144 struct ib_device
*dev
;
149 dev
= res_to_dev(res
);
153 rdma_restrack_put(res
);
155 wait_for_completion(&res
->comp
);
157 down_write(&dev
->res
.rwsem
);
158 hash_del(&res
->node
);
161 put_task_struct(res
->task
);
162 up_write(&dev
->res
.rwsem
);
164 EXPORT_SYMBOL(rdma_restrack_del
);