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/pid_namespace.h>
12 void rdma_restrack_init(struct rdma_restrack_root
*res
)
14 init_rwsem(&res
->rwsem
);
17 void rdma_restrack_clean(struct rdma_restrack_root
*res
)
19 WARN_ON_ONCE(!hash_empty(res
->hash
));
22 int rdma_restrack_count(struct rdma_restrack_root
*res
,
23 enum rdma_restrack_type type
,
24 struct pid_namespace
*ns
)
26 struct rdma_restrack_entry
*e
;
29 down_read(&res
->rwsem
);
30 hash_for_each_possible(res
->hash
, e
, node
, type
) {
31 if (ns
== &init_pid_ns
||
32 (!rdma_is_kernel_res(e
) &&
33 ns
== task_active_pid_ns(e
->task
)))
39 EXPORT_SYMBOL(rdma_restrack_count
);
41 static void set_kern_name(struct rdma_restrack_entry
*res
)
43 enum rdma_restrack_type type
= res
->type
;
46 if (type
!= RDMA_RESTRACK_QP
)
47 /* PD and CQ types already have this name embedded in */
50 qp
= container_of(res
, struct ib_qp
, res
);
52 WARN_ONCE(true, "XRC QPs are not supported\n");
53 /* Survive, despite the programmer's error */
58 res
->kern_name
= qp
->pd
->res
.kern_name
;
61 static struct ib_device
*res_to_dev(struct rdma_restrack_entry
*res
)
63 enum rdma_restrack_type type
= res
->type
;
64 struct ib_device
*dev
;
70 case RDMA_RESTRACK_PD
:
71 pd
= container_of(res
, struct ib_pd
, res
);
74 case RDMA_RESTRACK_CQ
:
75 cq
= container_of(res
, struct ib_cq
, res
);
78 case RDMA_RESTRACK_QP
:
79 qp
= container_of(res
, struct ib_qp
, res
);
83 WARN_ONCE(true, "Wrong resource tracking type %u\n", 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
;
100 WARN_ONCE(true, "Wrong resource tracking type %u\n", res
->type
);
105 void rdma_restrack_add(struct rdma_restrack_entry
*res
)
107 struct ib_device
*dev
= res_to_dev(res
);
112 if (res_is_user(res
)) {
113 get_task_struct(current
);
115 res
->kern_name
= NULL
;
121 kref_init(&res
->kref
);
122 init_completion(&res
->comp
);
125 down_write(&dev
->res
.rwsem
);
126 hash_add(dev
->res
.hash
, &res
->node
, res
->type
);
127 up_write(&dev
->res
.rwsem
);
129 EXPORT_SYMBOL(rdma_restrack_add
);
131 int __must_check
rdma_restrack_get(struct rdma_restrack_entry
*res
)
133 return kref_get_unless_zero(&res
->kref
);
135 EXPORT_SYMBOL(rdma_restrack_get
);
137 static void restrack_release(struct kref
*kref
)
139 struct rdma_restrack_entry
*res
;
141 res
= container_of(kref
, struct rdma_restrack_entry
, kref
);
142 complete(&res
->comp
);
145 int rdma_restrack_put(struct rdma_restrack_entry
*res
)
147 return kref_put(&res
->kref
, restrack_release
);
149 EXPORT_SYMBOL(rdma_restrack_put
);
151 void rdma_restrack_del(struct rdma_restrack_entry
*res
)
153 struct ib_device
*dev
;
158 dev
= res_to_dev(res
);
162 rdma_restrack_put(res
);
164 wait_for_completion(&res
->comp
);
166 down_write(&dev
->res
.rwsem
);
167 hash_del(&res
->node
);
170 put_task_struct(res
->task
);
171 up_write(&dev
->res
.rwsem
);
173 EXPORT_SYMBOL(rdma_restrack_del
);