Line data Source code
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 <dlatypov@google.com>
7 : */
8 :
9 : #include <kunit/resource.h>
10 : #include <kunit/test.h>
11 : #include <linux/kref.h>
12 :
13 : /*
14 : * Used for static resources and when a kunit_resource * has been created by
15 : * kunit_alloc_resource(). When an init function is supplied, @data is passed
16 : * into the init function; otherwise, we simply set the resource data field to
17 : * the data value passed in.
18 : */
19 271 : int kunit_add_resource(struct kunit *test,
20 : kunit_resource_init_t init,
21 : kunit_resource_free_t free,
22 : struct kunit_resource *res,
23 : void *data)
24 : {
25 271 : int ret = 0;
26 : unsigned long flags;
27 :
28 271 : res->free = free;
29 542 : kref_init(&res->refcount);
30 :
31 271 : if (init) {
32 271 : ret = init(res, data);
33 271 : if (ret)
34 : return ret;
35 : } else {
36 0 : res->data = data;
37 : }
38 :
39 271 : spin_lock_irqsave(&test->lock, flags);
40 542 : list_add_tail(&res->node, &test->resources);
41 : /* refcount for list is established by kref_init() */
42 542 : spin_unlock_irqrestore(&test->lock, flags);
43 :
44 271 : return ret;
45 : }
46 : EXPORT_SYMBOL_GPL(kunit_add_resource);
47 :
48 0 : int kunit_add_named_resource(struct kunit *test,
49 : kunit_resource_init_t init,
50 : kunit_resource_free_t free,
51 : struct kunit_resource *res,
52 : const char *name,
53 : void *data)
54 : {
55 : struct kunit_resource *existing;
56 :
57 0 : if (!name)
58 : return -EINVAL;
59 :
60 0 : existing = kunit_find_named_resource(test, name);
61 0 : if (existing) {
62 0 : kunit_put_resource(existing);
63 0 : return -EEXIST;
64 : }
65 :
66 0 : res->name = name;
67 :
68 0 : return kunit_add_resource(test, init, free, res, data);
69 : }
70 : EXPORT_SYMBOL_GPL(kunit_add_named_resource);
71 :
72 0 : struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
73 : kunit_resource_init_t init,
74 : kunit_resource_free_t free,
75 : gfp_t internal_gfp,
76 : void *data)
77 : {
78 : struct kunit_resource *res;
79 : int ret;
80 :
81 0 : res = kzalloc(sizeof(*res), internal_gfp);
82 0 : if (!res)
83 : return NULL;
84 :
85 0 : ret = kunit_add_resource(test, init, free, res, data);
86 0 : if (!ret) {
87 : /*
88 : * bump refcount for get; kunit_resource_put() should be called
89 : * when done.
90 : */
91 0 : kunit_get_resource(res);
92 0 : return res;
93 : }
94 : return NULL;
95 : }
96 : EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
97 :
98 271 : void kunit_remove_resource(struct kunit *test, struct kunit_resource *res)
99 : {
100 : unsigned long flags;
101 :
102 271 : spin_lock_irqsave(&test->lock, flags);
103 542 : list_del(&res->node);
104 542 : spin_unlock_irqrestore(&test->lock, flags);
105 271 : kunit_put_resource(res);
106 271 : }
107 : EXPORT_SYMBOL_GPL(kunit_remove_resource);
108 :
109 50 : int kunit_destroy_resource(struct kunit *test, kunit_resource_match_t match,
110 : void *match_data)
111 : {
112 50 : struct kunit_resource *res = kunit_find_resource(test, match,
113 : match_data);
114 :
115 50 : if (!res)
116 : return -ENOENT;
117 :
118 50 : kunit_remove_resource(test, res);
119 :
120 : /* We have a reference also via _find(); drop it. */
121 50 : kunit_put_resource(res);
122 :
123 50 : return 0;
124 : }
125 : EXPORT_SYMBOL_GPL(kunit_destroy_resource);
|