resource.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * KUnit resource API for test managed resources (allocations, etc.).
  4. *
  5. * Copyright (C) 2022, Google LLC.
  6. * Author: Daniel Latypov <[email protected]>
  7. */
  8. #ifndef _KUNIT_RESOURCE_H
  9. #define _KUNIT_RESOURCE_H
  10. #include <kunit/test.h>
  11. #include <linux/kref.h>
  12. #include <linux/list.h>
  13. #include <linux/slab.h>
  14. #include <linux/spinlock.h>
  15. struct kunit_resource;
  16. typedef int (*kunit_resource_init_t)(struct kunit_resource *, void *);
  17. typedef void (*kunit_resource_free_t)(struct kunit_resource *);
  18. /**
  19. * struct kunit_resource - represents a *test managed resource*
  20. * @data: for the user to store arbitrary data.
  21. * @name: optional name
  22. * @free: a user supplied function to free the resource.
  23. *
  24. * Represents a *test managed resource*, a resource which will automatically be
  25. * cleaned up at the end of a test case. This cleanup is performed by the 'free'
  26. * function. The struct kunit_resource itself is freed automatically with
  27. * kfree() if it was allocated by KUnit (e.g., by kunit_alloc_resource()), but
  28. * must be freed by the user otherwise.
  29. *
  30. * Resources are reference counted so if a resource is retrieved via
  31. * kunit_alloc_and_get_resource() or kunit_find_resource(), we need
  32. * to call kunit_put_resource() to reduce the resource reference count
  33. * when finished with it. Note that kunit_alloc_resource() does not require a
  34. * kunit_resource_put() because it does not retrieve the resource itself.
  35. *
  36. * Example:
  37. *
  38. * .. code-block:: c
  39. *
  40. * struct kunit_kmalloc_params {
  41. * size_t size;
  42. * gfp_t gfp;
  43. * };
  44. *
  45. * static int kunit_kmalloc_init(struct kunit_resource *res, void *context)
  46. * {
  47. * struct kunit_kmalloc_params *params = context;
  48. * res->data = kmalloc(params->size, params->gfp);
  49. *
  50. * if (!res->data)
  51. * return -ENOMEM;
  52. *
  53. * return 0;
  54. * }
  55. *
  56. * static void kunit_kmalloc_free(struct kunit_resource *res)
  57. * {
  58. * kfree(res->data);
  59. * }
  60. *
  61. * void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
  62. * {
  63. * struct kunit_kmalloc_params params;
  64. *
  65. * params.size = size;
  66. * params.gfp = gfp;
  67. *
  68. * return kunit_alloc_resource(test, kunit_kmalloc_init,
  69. * kunit_kmalloc_free, &params);
  70. * }
  71. *
  72. * Resources can also be named, with lookup/removal done on a name
  73. * basis also. kunit_add_named_resource(), kunit_find_named_resource()
  74. * and kunit_destroy_named_resource(). Resource names must be
  75. * unique within the test instance.
  76. */
  77. struct kunit_resource {
  78. void *data;
  79. const char *name;
  80. kunit_resource_free_t free;
  81. /* private: internal use only. */
  82. struct kref refcount;
  83. struct list_head node;
  84. bool should_kfree;
  85. };
  86. /**
  87. * kunit_get_resource() - Hold resource for use. Should not need to be used
  88. * by most users as we automatically get resources
  89. * retrieved by kunit_find_resource*().
  90. * @res: resource
  91. */
  92. static inline void kunit_get_resource(struct kunit_resource *res)
  93. {
  94. kref_get(&res->refcount);
  95. }
  96. /*
  97. * Called when refcount reaches zero via kunit_put_resource();
  98. * should not be called directly.
  99. */
  100. static inline void kunit_release_resource(struct kref *kref)
  101. {
  102. struct kunit_resource *res = container_of(kref, struct kunit_resource,
  103. refcount);
  104. if (res->free)
  105. res->free(res);
  106. /* 'res' is valid here, as if should_kfree is set, res->free may not free
  107. * 'res' itself, just res->data
  108. */
  109. if (res->should_kfree)
  110. kfree(res);
  111. }
  112. /**
  113. * kunit_put_resource() - When caller is done with retrieved resource,
  114. * kunit_put_resource() should be called to drop
  115. * reference count. The resource list maintains
  116. * a reference count on resources, so if no users
  117. * are utilizing a resource and it is removed from
  118. * the resource list, it will be freed via the
  119. * associated free function (if any). Only
  120. * needs to be used if we alloc_and_get() or
  121. * find() resource.
  122. * @res: resource
  123. */
  124. static inline void kunit_put_resource(struct kunit_resource *res)
  125. {
  126. kref_put(&res->refcount, kunit_release_resource);
  127. }
  128. /**
  129. * __kunit_add_resource() - Internal helper to add a resource.
  130. *
  131. * res->should_kfree is not initialised.
  132. * @test: The test context object.
  133. * @init: a user-supplied function to initialize the result (if needed). If
  134. * none is supplied, the resource data value is simply set to @data.
  135. * If an init function is supplied, @data is passed to it instead.
  136. * @free: a user-supplied function to free the resource (if needed).
  137. * @res: The resource.
  138. * @data: value to pass to init function or set in resource data field.
  139. */
  140. int __kunit_add_resource(struct kunit *test,
  141. kunit_resource_init_t init,
  142. kunit_resource_free_t free,
  143. struct kunit_resource *res,
  144. void *data);
  145. /**
  146. * kunit_add_resource() - Add a *test managed resource*.
  147. * @test: The test context object.
  148. * @init: a user-supplied function to initialize the result (if needed). If
  149. * none is supplied, the resource data value is simply set to @data.
  150. * If an init function is supplied, @data is passed to it instead.
  151. * @free: a user-supplied function to free the resource (if needed).
  152. * @res: The resource.
  153. * @data: value to pass to init function or set in resource data field.
  154. */
  155. static inline int kunit_add_resource(struct kunit *test,
  156. kunit_resource_init_t init,
  157. kunit_resource_free_t free,
  158. struct kunit_resource *res,
  159. void *data)
  160. {
  161. res->should_kfree = false;
  162. return __kunit_add_resource(test, init, free, res, data);
  163. }
  164. static inline struct kunit_resource *
  165. kunit_find_named_resource(struct kunit *test, const char *name);
  166. /**
  167. * kunit_add_named_resource() - Add a named *test managed resource*.
  168. * @test: The test context object.
  169. * @init: a user-supplied function to initialize the resource data, if needed.
  170. * @free: a user-supplied function to free the resource data, if needed.
  171. * @res: The resource.
  172. * @name: name to be set for resource.
  173. * @data: value to pass to init function or set in resource data field.
  174. */
  175. static inline int kunit_add_named_resource(struct kunit *test,
  176. kunit_resource_init_t init,
  177. kunit_resource_free_t free,
  178. struct kunit_resource *res,
  179. const char *name,
  180. void *data)
  181. {
  182. struct kunit_resource *existing;
  183. if (!name)
  184. return -EINVAL;
  185. existing = kunit_find_named_resource(test, name);
  186. if (existing) {
  187. kunit_put_resource(existing);
  188. return -EEXIST;
  189. }
  190. res->name = name;
  191. res->should_kfree = false;
  192. return __kunit_add_resource(test, init, free, res, data);
  193. }
  194. /**
  195. * kunit_alloc_and_get_resource() - Allocates and returns a *test managed resource*.
  196. * @test: The test context object.
  197. * @init: a user supplied function to initialize the resource.
  198. * @free: a user supplied function to free the resource (if needed).
  199. * @internal_gfp: gfp to use for internal allocations, if unsure, use GFP_KERNEL
  200. * @context: for the user to pass in arbitrary data to the init function.
  201. *
  202. * Allocates a *test managed resource*, a resource which will automatically be
  203. * cleaned up at the end of a test case. See &struct kunit_resource for an
  204. * example.
  205. *
  206. * This is effectively identical to kunit_alloc_resource, but returns the
  207. * struct kunit_resource pointer, not just the 'data' pointer. It therefore
  208. * also increments the resource's refcount, so kunit_put_resource() should be
  209. * called when you've finished with it.
  210. *
  211. * Note: KUnit needs to allocate memory for a kunit_resource object. You must
  212. * specify an @internal_gfp that is compatible with the use context of your
  213. * resource.
  214. */
  215. static inline struct kunit_resource *
  216. kunit_alloc_and_get_resource(struct kunit *test,
  217. kunit_resource_init_t init,
  218. kunit_resource_free_t free,
  219. gfp_t internal_gfp,
  220. void *context)
  221. {
  222. struct kunit_resource *res;
  223. int ret;
  224. res = kzalloc(sizeof(*res), internal_gfp);
  225. if (!res)
  226. return NULL;
  227. res->should_kfree = true;
  228. ret = __kunit_add_resource(test, init, free, res, context);
  229. if (!ret) {
  230. /*
  231. * bump refcount for get; kunit_resource_put() should be called
  232. * when done.
  233. */
  234. kunit_get_resource(res);
  235. return res;
  236. }
  237. return NULL;
  238. }
  239. /**
  240. * kunit_alloc_resource() - Allocates a *test managed resource*.
  241. * @test: The test context object.
  242. * @init: a user supplied function to initialize the resource.
  243. * @free: a user supplied function to free the resource (if needed).
  244. * @internal_gfp: gfp to use for internal allocations, if unsure, use GFP_KERNEL
  245. * @context: for the user to pass in arbitrary data to the init function.
  246. *
  247. * Allocates a *test managed resource*, a resource which will automatically be
  248. * cleaned up at the end of a test case. See &struct kunit_resource for an
  249. * example.
  250. *
  251. * Note: KUnit needs to allocate memory for a kunit_resource object. You must
  252. * specify an @internal_gfp that is compatible with the use context of your
  253. * resource.
  254. */
  255. static inline void *kunit_alloc_resource(struct kunit *test,
  256. kunit_resource_init_t init,
  257. kunit_resource_free_t free,
  258. gfp_t internal_gfp,
  259. void *context)
  260. {
  261. struct kunit_resource *res;
  262. res = kzalloc(sizeof(*res), internal_gfp);
  263. if (!res)
  264. return NULL;
  265. res->should_kfree = true;
  266. if (!__kunit_add_resource(test, init, free, res, context))
  267. return res->data;
  268. return NULL;
  269. }
  270. typedef bool (*kunit_resource_match_t)(struct kunit *test,
  271. struct kunit_resource *res,
  272. void *match_data);
  273. /**
  274. * kunit_resource_name_match() - Match a resource with the same name.
  275. * @test: Test case to which the resource belongs.
  276. * @res: The resource.
  277. * @match_name: The name to match against.
  278. */
  279. static inline bool kunit_resource_name_match(struct kunit *test,
  280. struct kunit_resource *res,
  281. void *match_name)
  282. {
  283. return res->name && strcmp(res->name, match_name) == 0;
  284. }
  285. /**
  286. * kunit_find_resource() - Find a resource using match function/data.
  287. * @test: Test case to which the resource belongs.
  288. * @match: match function to be applied to resources/match data.
  289. * @match_data: data to be used in matching.
  290. */
  291. static inline struct kunit_resource *
  292. kunit_find_resource(struct kunit *test,
  293. kunit_resource_match_t match,
  294. void *match_data)
  295. {
  296. struct kunit_resource *res, *found = NULL;
  297. unsigned long flags;
  298. spin_lock_irqsave(&test->lock, flags);
  299. list_for_each_entry_reverse(res, &test->resources, node) {
  300. if (match(test, res, (void *)match_data)) {
  301. found = res;
  302. kunit_get_resource(found);
  303. break;
  304. }
  305. }
  306. spin_unlock_irqrestore(&test->lock, flags);
  307. return found;
  308. }
  309. /**
  310. * kunit_find_named_resource() - Find a resource using match name.
  311. * @test: Test case to which the resource belongs.
  312. * @name: match name.
  313. */
  314. static inline struct kunit_resource *
  315. kunit_find_named_resource(struct kunit *test,
  316. const char *name)
  317. {
  318. return kunit_find_resource(test, kunit_resource_name_match,
  319. (void *)name);
  320. }
  321. /**
  322. * kunit_destroy_resource() - Find a kunit_resource and destroy it.
  323. * @test: Test case to which the resource belongs.
  324. * @match: Match function. Returns whether a given resource matches @match_data.
  325. * @match_data: Data passed into @match.
  326. *
  327. * RETURNS:
  328. * 0 if kunit_resource is found and freed, -ENOENT if not found.
  329. */
  330. int kunit_destroy_resource(struct kunit *test,
  331. kunit_resource_match_t match,
  332. void *match_data);
  333. static inline int kunit_destroy_named_resource(struct kunit *test,
  334. const char *name)
  335. {
  336. return kunit_destroy_resource(test, kunit_resource_name_match,
  337. (void *)name);
  338. }
  339. /**
  340. * kunit_remove_resource() - remove resource from resource list associated with
  341. * test.
  342. * @test: The test context object.
  343. * @res: The resource to be removed.
  344. *
  345. * Note that the resource will not be immediately freed since it is likely
  346. * the caller has a reference to it via alloc_and_get() or find();
  347. * in this case a final call to kunit_put_resource() is required.
  348. */
  349. void kunit_remove_resource(struct kunit *test, struct kunit_resource *res);
  350. #endif /* _KUNIT_RESOURCE_H */