restrack.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2. /*
  3. * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
  4. */
  5. #include <rdma/rdma_cm.h>
  6. #include <rdma/ib_verbs.h>
  7. #include <rdma/restrack.h>
  8. #include <rdma/rdma_counter.h>
  9. #include <linux/mutex.h>
  10. #include <linux/sched/task.h>
  11. #include <linux/pid_namespace.h>
  12. #include "cma_priv.h"
  13. #include "restrack.h"
  14. /**
  15. * rdma_restrack_init() - initialize and allocate resource tracking
  16. * @dev: IB device
  17. *
  18. * Return: 0 on success
  19. */
  20. int rdma_restrack_init(struct ib_device *dev)
  21. {
  22. struct rdma_restrack_root *rt;
  23. int i;
  24. dev->res = kzalloc_objs(*rt, RDMA_RESTRACK_MAX);
  25. if (!dev->res)
  26. return -ENOMEM;
  27. rt = dev->res;
  28. for (i = 0; i < RDMA_RESTRACK_MAX; i++)
  29. xa_init_flags(&rt[i].xa, XA_FLAGS_ALLOC);
  30. return 0;
  31. }
  32. /**
  33. * rdma_restrack_clean() - clean resource tracking
  34. * @dev: IB device
  35. */
  36. void rdma_restrack_clean(struct ib_device *dev)
  37. {
  38. struct rdma_restrack_root *rt = dev->res;
  39. int i;
  40. for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
  41. struct xarray *xa = &dev->res[i].xa;
  42. WARN_ON(!xa_empty(xa));
  43. xa_destroy(xa);
  44. }
  45. kfree(rt);
  46. }
  47. /**
  48. * rdma_restrack_count() - the current usage of specific object
  49. * @dev: IB device
  50. * @type: actual type of object to operate
  51. * @show_details: count driver specific objects
  52. */
  53. int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
  54. bool show_details)
  55. {
  56. struct rdma_restrack_root *rt = &dev->res[type];
  57. struct rdma_restrack_entry *e;
  58. XA_STATE(xas, &rt->xa, 0);
  59. u32 cnt = 0;
  60. xa_lock(&rt->xa);
  61. xas_for_each(&xas, e, U32_MAX) {
  62. if (xa_get_mark(&rt->xa, e->id, RESTRACK_DD) && !show_details)
  63. continue;
  64. cnt++;
  65. }
  66. xa_unlock(&rt->xa);
  67. return cnt;
  68. }
  69. EXPORT_SYMBOL(rdma_restrack_count);
  70. static struct ib_device *res_to_dev(struct rdma_restrack_entry *res)
  71. {
  72. switch (res->type) {
  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,
  81. res)->id.device;
  82. case RDMA_RESTRACK_MR:
  83. return container_of(res, struct ib_mr, res)->device;
  84. case RDMA_RESTRACK_CTX:
  85. return container_of(res, struct ib_ucontext, res)->device;
  86. case RDMA_RESTRACK_COUNTER:
  87. return container_of(res, struct rdma_counter, res)->device;
  88. case RDMA_RESTRACK_SRQ:
  89. return container_of(res, struct ib_srq, res)->device;
  90. case RDMA_RESTRACK_DMAH:
  91. return container_of(res, struct ib_dmah, res)->device;
  92. default:
  93. WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
  94. return NULL;
  95. }
  96. }
  97. /**
  98. * rdma_restrack_attach_task() - attach the task onto this resource,
  99. * valid for user space restrack entries.
  100. * @res: resource entry
  101. * @task: the task to attach
  102. */
  103. static void rdma_restrack_attach_task(struct rdma_restrack_entry *res,
  104. struct task_struct *task)
  105. {
  106. if (WARN_ON_ONCE(!task))
  107. return;
  108. if (res->task)
  109. put_task_struct(res->task);
  110. get_task_struct(task);
  111. res->task = task;
  112. res->user = true;
  113. }
  114. /**
  115. * rdma_restrack_set_name() - set the task for this resource
  116. * @res: resource entry
  117. * @caller: kernel name, the current task will be used if the caller is NULL.
  118. */
  119. void rdma_restrack_set_name(struct rdma_restrack_entry *res, const char *caller)
  120. {
  121. if (caller) {
  122. res->kern_name = caller;
  123. return;
  124. }
  125. rdma_restrack_attach_task(res, current);
  126. }
  127. EXPORT_SYMBOL(rdma_restrack_set_name);
  128. /**
  129. * rdma_restrack_parent_name() - set the restrack name properties based
  130. * on parent restrack
  131. * @dst: destination resource entry
  132. * @parent: parent resource entry
  133. */
  134. void rdma_restrack_parent_name(struct rdma_restrack_entry *dst,
  135. const struct rdma_restrack_entry *parent)
  136. {
  137. if (rdma_is_kernel_res(parent))
  138. dst->kern_name = parent->kern_name;
  139. else
  140. rdma_restrack_attach_task(dst, parent->task);
  141. }
  142. EXPORT_SYMBOL(rdma_restrack_parent_name);
  143. /**
  144. * rdma_restrack_new() - Initializes new restrack entry to allow _put() interface
  145. * to release memory in fully automatic way.
  146. * @res: Entry to initialize
  147. * @type: REstrack type
  148. */
  149. void rdma_restrack_new(struct rdma_restrack_entry *res,
  150. enum rdma_restrack_type type)
  151. {
  152. kref_init(&res->kref);
  153. init_completion(&res->comp);
  154. res->type = type;
  155. }
  156. EXPORT_SYMBOL(rdma_restrack_new);
  157. /**
  158. * rdma_restrack_add() - add object to the resource tracking database
  159. * @res: resource entry
  160. */
  161. void rdma_restrack_add(struct rdma_restrack_entry *res)
  162. {
  163. struct ib_device *dev = res_to_dev(res);
  164. struct rdma_restrack_root *rt;
  165. int ret = 0;
  166. if (!dev)
  167. return;
  168. if (res->no_track)
  169. goto out;
  170. rt = &dev->res[res->type];
  171. if (res->type == RDMA_RESTRACK_QP) {
  172. /* Special case to ensure that LQPN points to right QP */
  173. struct ib_qp *qp = container_of(res, struct ib_qp, res);
  174. WARN_ONCE(qp->qp_num >> 24 || qp->port >> 8,
  175. "QP number 0x%0X and port 0x%0X", qp->qp_num,
  176. qp->port);
  177. res->id = qp->qp_num;
  178. if (qp->qp_type == IB_QPT_SMI || qp->qp_type == IB_QPT_GSI)
  179. res->id |= qp->port << 24;
  180. ret = xa_insert(&rt->xa, res->id, res, GFP_KERNEL);
  181. if (ret)
  182. res->id = 0;
  183. if (qp->qp_type >= IB_QPT_DRIVER)
  184. xa_set_mark(&rt->xa, res->id, RESTRACK_DD);
  185. } else if (res->type == RDMA_RESTRACK_COUNTER) {
  186. /* Special case to ensure that cntn points to right counter */
  187. struct rdma_counter *counter;
  188. counter = container_of(res, struct rdma_counter, res);
  189. ret = xa_insert(&rt->xa, counter->id, res, GFP_KERNEL);
  190. res->id = ret ? 0 : counter->id;
  191. } else {
  192. ret = xa_alloc_cyclic(&rt->xa, &res->id, res, xa_limit_32b,
  193. &rt->next_id, GFP_KERNEL);
  194. ret = (ret < 0) ? ret : 0;
  195. }
  196. out:
  197. if (!ret)
  198. res->valid = true;
  199. }
  200. EXPORT_SYMBOL(rdma_restrack_add);
  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. * rdma_restrack_get_byid() - translate from ID to restrack object
  208. * @dev: IB device
  209. * @type: resource track type
  210. * @id: ID to take a look
  211. *
  212. * Return: Pointer to restrack entry or -ENOENT in case of error.
  213. */
  214. struct rdma_restrack_entry *
  215. rdma_restrack_get_byid(struct ib_device *dev,
  216. enum rdma_restrack_type type, u32 id)
  217. {
  218. struct rdma_restrack_root *rt = &dev->res[type];
  219. struct rdma_restrack_entry *res;
  220. xa_lock(&rt->xa);
  221. res = xa_load(&rt->xa, id);
  222. if (!res || !rdma_restrack_get(res))
  223. res = ERR_PTR(-ENOENT);
  224. xa_unlock(&rt->xa);
  225. return res;
  226. }
  227. EXPORT_SYMBOL(rdma_restrack_get_byid);
  228. static void restrack_release(struct kref *kref)
  229. {
  230. struct rdma_restrack_entry *res;
  231. res = container_of(kref, struct rdma_restrack_entry, kref);
  232. if (res->task) {
  233. put_task_struct(res->task);
  234. res->task = NULL;
  235. }
  236. complete(&res->comp);
  237. }
  238. int rdma_restrack_put(struct rdma_restrack_entry *res)
  239. {
  240. return kref_put(&res->kref, restrack_release);
  241. }
  242. EXPORT_SYMBOL(rdma_restrack_put);
  243. /**
  244. * rdma_restrack_del() - delete object from the resource tracking database
  245. * @res: resource entry
  246. */
  247. void rdma_restrack_del(struct rdma_restrack_entry *res)
  248. {
  249. struct rdma_restrack_entry *old;
  250. struct rdma_restrack_root *rt;
  251. struct ib_device *dev;
  252. if (!res->valid) {
  253. if (res->task) {
  254. put_task_struct(res->task);
  255. res->task = NULL;
  256. }
  257. return;
  258. }
  259. if (res->no_track)
  260. goto out;
  261. dev = res_to_dev(res);
  262. if (WARN_ON(!dev))
  263. return;
  264. rt = &dev->res[res->type];
  265. old = xa_erase(&rt->xa, res->id);
  266. WARN_ON(old != res);
  267. out:
  268. res->valid = false;
  269. rdma_restrack_put(res);
  270. wait_for_completion(&res->comp);
  271. }
  272. EXPORT_SYMBOL(rdma_restrack_del);