diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-09-08 12:09:52 -0400 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 10:46:46 -0400 |
commit | 93eb07f72c8d86f8fe5e90907df1cc037f6ffbb7 (patch) | |
tree | 1770476c4ad43d7f1aeb730cf09aeba22c65d6f7 | |
parent | d6427f8179b5dd65eb468c61fc8cc24657c336c9 (diff) |
xarray: Move multiorder_shrink to kernel tests
Test this functionality inside the kernel as well as in userspace.
Also remove insert_bug() as there's no comparable thing to test
in the XArray code.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
-rw-r--r-- | lib/test_xarray.c | 37 | ||||
-rw-r--r-- | tools/testing/radix-tree/multiorder.c | 173 |
2 files changed, 37 insertions, 173 deletions
diff --git a/lib/test_xarray.c b/lib/test_xarray.c index 38cab4ccb24e..ff94b54a926d 100644 --- a/lib/test_xarray.c +++ b/lib/test_xarray.c | |||
@@ -199,9 +199,25 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index) | |||
199 | xa_store_order(xa, index, order, xa_mk_value(index), | 199 | xa_store_order(xa, index, order, xa_mk_value(index), |
200 | GFP_KERNEL); | 200 | GFP_KERNEL); |
201 | for (i = base; i < next; i++) { | 201 | for (i = base; i < next; i++) { |
202 | XA_STATE(xas, xa, i); | ||
203 | unsigned int seen = 0; | ||
204 | void *entry; | ||
205 | |||
202 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0)); | 206 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0)); |
203 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1)); | 207 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1)); |
204 | XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2)); | 208 | XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2)); |
209 | |||
210 | /* We should see two elements in the array */ | ||
211 | xas_for_each(&xas, entry, ULONG_MAX) | ||
212 | seen++; | ||
213 | XA_BUG_ON(xa, seen != 2); | ||
214 | |||
215 | /* One of which is marked */ | ||
216 | xas_set(&xas, 0); | ||
217 | seen = 0; | ||
218 | xas_for_each_marked(&xas, entry, ULONG_MAX, XA_MARK_0) | ||
219 | seen++; | ||
220 | XA_BUG_ON(xa, seen != 1); | ||
205 | } | 221 | } |
206 | XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_0)); | 222 | XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_0)); |
207 | XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_1)); | 223 | XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_1)); |
@@ -265,6 +281,8 @@ static noinline void check_xa_shrink(struct xarray *xa) | |||
265 | { | 281 | { |
266 | XA_STATE(xas, xa, 1); | 282 | XA_STATE(xas, xa, 1); |
267 | struct xa_node *node; | 283 | struct xa_node *node; |
284 | unsigned int order; | ||
285 | unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 15 : 1; | ||
268 | 286 | ||
269 | XA_BUG_ON(xa, !xa_empty(xa)); | 287 | XA_BUG_ON(xa, !xa_empty(xa)); |
270 | XA_BUG_ON(xa, xa_store_index(xa, 0, GFP_KERNEL) != NULL); | 288 | XA_BUG_ON(xa, xa_store_index(xa, 0, GFP_KERNEL) != NULL); |
@@ -287,6 +305,25 @@ static noinline void check_xa_shrink(struct xarray *xa) | |||
287 | XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0)); | 305 | XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0)); |
288 | xa_erase_index(xa, 0); | 306 | xa_erase_index(xa, 0); |
289 | XA_BUG_ON(xa, !xa_empty(xa)); | 307 | XA_BUG_ON(xa, !xa_empty(xa)); |
308 | |||
309 | for (order = 0; order < max_order; order++) { | ||
310 | unsigned long max = (1UL << order) - 1; | ||
311 | xa_store_order(xa, 0, order, xa_mk_value(0), GFP_KERNEL); | ||
312 | XA_BUG_ON(xa, xa_load(xa, max) != xa_mk_value(0)); | ||
313 | XA_BUG_ON(xa, xa_load(xa, max + 1) != NULL); | ||
314 | rcu_read_lock(); | ||
315 | node = xa_head(xa); | ||
316 | rcu_read_unlock(); | ||
317 | XA_BUG_ON(xa, xa_store_index(xa, ULONG_MAX, GFP_KERNEL) != | ||
318 | NULL); | ||
319 | rcu_read_lock(); | ||
320 | XA_BUG_ON(xa, xa_head(xa) == node); | ||
321 | rcu_read_unlock(); | ||
322 | XA_BUG_ON(xa, xa_load(xa, max + 1) != NULL); | ||
323 | xa_erase_index(xa, ULONG_MAX); | ||
324 | XA_BUG_ON(xa, xa->xa_head != node); | ||
325 | xa_erase_index(xa, 0); | ||
326 | } | ||
290 | } | 327 | } |
291 | 328 | ||
292 | static noinline void check_cmpxchg(struct xarray *xa) | 329 | static noinline void check_cmpxchg(struct xarray *xa) |
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c index dc27a3da210a..a60c03287e9c 100644 --- a/tools/testing/radix-tree/multiorder.c +++ b/tools/testing/radix-tree/multiorder.c | |||
@@ -20,127 +20,6 @@ | |||
20 | 20 | ||
21 | #include "test.h" | 21 | #include "test.h" |
22 | 22 | ||
23 | #define for_each_index(i, base, order) \ | ||
24 | for (i = base; i < base + (1 << order); i++) | ||
25 | |||
26 | static void __multiorder_tag_test(int index, int order) | ||
27 | { | ||
28 | RADIX_TREE(tree, GFP_KERNEL); | ||
29 | int base, err, i; | ||
30 | |||
31 | /* our canonical entry */ | ||
32 | base = index & ~((1 << order) - 1); | ||
33 | |||
34 | printv(2, "Multiorder tag test with index %d, canonical entry %d\n", | ||
35 | index, base); | ||
36 | |||
37 | err = item_insert_order(&tree, index, order); | ||
38 | assert(!err); | ||
39 | |||
40 | /* | ||
41 | * Verify we get collisions for covered indices. We try and fail to | ||
42 | * insert a value entry so we don't leak memory via | ||
43 | * item_insert_order(). | ||
44 | */ | ||
45 | for_each_index(i, base, order) { | ||
46 | err = __radix_tree_insert(&tree, i, order, xa_mk_value(0xA0)); | ||
47 | assert(err == -EEXIST); | ||
48 | } | ||
49 | |||
50 | for_each_index(i, base, order) { | ||
51 | assert(!radix_tree_tag_get(&tree, i, 0)); | ||
52 | assert(!radix_tree_tag_get(&tree, i, 1)); | ||
53 | } | ||
54 | |||
55 | assert(radix_tree_tag_set(&tree, index, 0)); | ||
56 | |||
57 | for_each_index(i, base, order) { | ||
58 | assert(radix_tree_tag_get(&tree, i, 0)); | ||
59 | assert(!radix_tree_tag_get(&tree, i, 1)); | ||
60 | } | ||
61 | |||
62 | assert(tag_tagged_items(&tree, 0, ~0UL, 10, XA_MARK_0, XA_MARK_1) == 1); | ||
63 | assert(radix_tree_tag_clear(&tree, index, 0)); | ||
64 | |||
65 | for_each_index(i, base, order) { | ||
66 | assert(!radix_tree_tag_get(&tree, i, 0)); | ||
67 | assert(radix_tree_tag_get(&tree, i, 1)); | ||
68 | } | ||
69 | |||
70 | assert(radix_tree_tag_clear(&tree, index, 1)); | ||
71 | |||
72 | assert(!radix_tree_tagged(&tree, 0)); | ||
73 | assert(!radix_tree_tagged(&tree, 1)); | ||
74 | |||
75 | item_kill_tree(&tree); | ||
76 | } | ||
77 | |||
78 | static void __multiorder_tag_test2(unsigned order, unsigned long index2) | ||
79 | { | ||
80 | RADIX_TREE(tree, GFP_KERNEL); | ||
81 | unsigned long index = (1 << order); | ||
82 | index2 += index; | ||
83 | |||
84 | assert(item_insert_order(&tree, 0, order) == 0); | ||
85 | assert(item_insert(&tree, index2) == 0); | ||
86 | |||
87 | assert(radix_tree_tag_set(&tree, 0, 0)); | ||
88 | assert(radix_tree_tag_set(&tree, index2, 0)); | ||
89 | |||
90 | assert(tag_tagged_items(&tree, 0, ~0UL, 10, XA_MARK_0, XA_MARK_1) == 2); | ||
91 | |||
92 | item_kill_tree(&tree); | ||
93 | } | ||
94 | |||
95 | static void multiorder_tag_tests(void) | ||
96 | { | ||
97 | int i, j; | ||
98 | |||
99 | /* test multi-order entry for indices 0-7 with no sibling pointers */ | ||
100 | __multiorder_tag_test(0, 3); | ||
101 | __multiorder_tag_test(5, 3); | ||
102 | |||
103 | /* test multi-order entry for indices 8-15 with no sibling pointers */ | ||
104 | __multiorder_tag_test(8, 3); | ||
105 | __multiorder_tag_test(15, 3); | ||
106 | |||
107 | /* | ||
108 | * Our order 5 entry covers indices 0-31 in a tree with height=2. | ||
109 | * This is broken up as follows: | ||
110 | * 0-7: canonical entry | ||
111 | * 8-15: sibling 1 | ||
112 | * 16-23: sibling 2 | ||
113 | * 24-31: sibling 3 | ||
114 | */ | ||
115 | __multiorder_tag_test(0, 5); | ||
116 | __multiorder_tag_test(29, 5); | ||
117 | |||
118 | /* same test, but with indices 32-63 */ | ||
119 | __multiorder_tag_test(32, 5); | ||
120 | __multiorder_tag_test(44, 5); | ||
121 | |||
122 | /* | ||
123 | * Our order 8 entry covers indices 0-255 in a tree with height=3. | ||
124 | * This is broken up as follows: | ||
125 | * 0-63: canonical entry | ||
126 | * 64-127: sibling 1 | ||
127 | * 128-191: sibling 2 | ||
128 | * 192-255: sibling 3 | ||
129 | */ | ||
130 | __multiorder_tag_test(0, 8); | ||
131 | __multiorder_tag_test(190, 8); | ||
132 | |||
133 | /* same test, but with indices 256-511 */ | ||
134 | __multiorder_tag_test(256, 8); | ||
135 | __multiorder_tag_test(300, 8); | ||
136 | |||
137 | __multiorder_tag_test(0x12345678UL, 8); | ||
138 | |||
139 | for (i = 1; i < 10; i++) | ||
140 | for (j = 0; j < (10 << i); j++) | ||
141 | __multiorder_tag_test2(i, j); | ||
142 | } | ||
143 | |||
144 | static void multiorder_check(unsigned long index, int order) | 23 | static void multiorder_check(unsigned long index, int order) |
145 | { | 24 | { |
146 | unsigned long i; | 25 | unsigned long i; |
@@ -181,53 +60,6 @@ static void multiorder_check(unsigned long index, int order) | |||
181 | item_check_absent(&tree, i); | 60 | item_check_absent(&tree, i); |
182 | } | 61 | } |
183 | 62 | ||
184 | static void multiorder_shrink(unsigned long index, int order) | ||
185 | { | ||
186 | unsigned long i; | ||
187 | unsigned long max = 1 << order; | ||
188 | RADIX_TREE(tree, GFP_KERNEL); | ||
189 | struct radix_tree_node *node; | ||
190 | |||
191 | printv(2, "Multiorder shrink index %ld, order %d\n", index, order); | ||
192 | |||
193 | assert(item_insert_order(&tree, 0, order) == 0); | ||
194 | |||
195 | node = tree.xa_head; | ||
196 | |||
197 | assert(item_insert(&tree, index) == 0); | ||
198 | assert(node != tree.xa_head); | ||
199 | |||
200 | assert(item_delete(&tree, index) != 0); | ||
201 | assert(node == tree.xa_head); | ||
202 | |||
203 | for (i = 0; i < max; i++) { | ||
204 | struct item *item = item_lookup(&tree, i); | ||
205 | assert(item != 0); | ||
206 | assert(item->index == 0); | ||
207 | } | ||
208 | for (i = max; i < 2*max; i++) | ||
209 | item_check_absent(&tree, i); | ||
210 | |||
211 | if (!item_delete(&tree, 0)) { | ||
212 | printv(2, "failed to delete index %ld (order %d)\n", index, order); | ||
213 | abort(); | ||
214 | } | ||
215 | |||
216 | for (i = 0; i < 2*max; i++) | ||
217 | item_check_absent(&tree, i); | ||
218 | } | ||
219 | |||
220 | static void multiorder_insert_bug(void) | ||
221 | { | ||
222 | RADIX_TREE(tree, GFP_KERNEL); | ||
223 | |||
224 | item_insert(&tree, 0); | ||
225 | radix_tree_tag_set(&tree, 0, 0); | ||
226 | item_insert_order(&tree, 3 << 6, 6); | ||
227 | |||
228 | item_kill_tree(&tree); | ||
229 | } | ||
230 | |||
231 | void multiorder_iteration(void) | 63 | void multiorder_iteration(void) |
232 | { | 64 | { |
233 | RADIX_TREE(tree, GFP_KERNEL); | 65 | RADIX_TREE(tree, GFP_KERNEL); |
@@ -427,11 +259,6 @@ void multiorder_checks(void) | |||
427 | multiorder_check((1UL << i) + 1, i); | 259 | multiorder_check((1UL << i) + 1, i); |
428 | } | 260 | } |
429 | 261 | ||
430 | for (i = 0; i < 15; i++) | ||
431 | multiorder_shrink((1UL << (i + RADIX_TREE_MAP_SHIFT)), i); | ||
432 | |||
433 | multiorder_insert_bug(); | ||
434 | multiorder_tag_tests(); | ||
435 | multiorder_iteration(); | 262 | multiorder_iteration(); |
436 | multiorder_tagged_iteration(); | 263 | multiorder_tagged_iteration(); |
437 | multiorder_iteration_race(); | 264 | multiorder_iteration_race(); |