mm: Convert page-writeback to XArray
[linux-2.6-block.git] / lib / test_xarray.c
CommitLineData
ad3d6c72
MW
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * test_xarray.c: Test the XArray API
4 * Copyright (c) 2017-2018 Microsoft Corporation
5 * Author: Matthew Wilcox <willy@infradead.org>
6 */
7
8#include <linux/xarray.h>
9#include <linux/module.h>
10
11static unsigned int tests_run;
12static unsigned int tests_passed;
13
14#ifndef XA_DEBUG
15# ifdef __KERNEL__
16void xa_dump(const struct xarray *xa) { }
17# endif
18#undef XA_BUG_ON
19#define XA_BUG_ON(xa, x) do { \
20 tests_run++; \
21 if (x) { \
22 printk("BUG at %s:%d\n", __func__, __LINE__); \
23 xa_dump(xa); \
24 dump_stack(); \
25 } else { \
26 tests_passed++; \
27 } \
28} while (0)
29#endif
30
31static void *xa_store_index(struct xarray *xa, unsigned long index, gfp_t gfp)
32{
58d6ea30 33 return xa_store(xa, index, xa_mk_value(index & LONG_MAX), gfp);
ad3d6c72
MW
34}
35
371c752d
MW
36static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp)
37{
38 u32 id = 0;
39
40 XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_value(index & LONG_MAX),
41 gfp) != 0);
42 XA_BUG_ON(xa, id != index);
43}
44
ad3d6c72
MW
45static void xa_erase_index(struct xarray *xa, unsigned long index)
46{
58d6ea30
MW
47 XA_BUG_ON(xa, xa_erase(xa, index) != xa_mk_value(index & LONG_MAX));
48 XA_BUG_ON(xa, xa_load(xa, index) != NULL);
49}
50
51/*
52 * If anyone needs this, please move it to xarray.c. We have no current
53 * users outside the test suite because all current multislot users want
54 * to use the advanced API.
55 */
56static void *xa_store_order(struct xarray *xa, unsigned long index,
57 unsigned order, void *entry, gfp_t gfp)
58{
59 XA_STATE_ORDER(xas, xa, index, order);
60 void *curr;
61
62 do {
63 xas_lock(&xas);
64 curr = xas_store(&xas, entry);
65 xas_unlock(&xas);
66 } while (xas_nomem(&xas, gfp));
67
68 return curr;
69}
70
71static noinline void check_xa_err(struct xarray *xa)
72{
73 XA_BUG_ON(xa, xa_err(xa_store_index(xa, 0, GFP_NOWAIT)) != 0);
74 XA_BUG_ON(xa, xa_err(xa_erase(xa, 0)) != 0);
75#ifndef __KERNEL__
76 /* The kernel does not fail GFP_NOWAIT allocations */
77 XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_NOWAIT)) != -ENOMEM);
78 XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_NOWAIT)) != -ENOMEM);
79#endif
80 XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_KERNEL)) != 0);
81 XA_BUG_ON(xa, xa_err(xa_store(xa, 1, xa_mk_value(0), GFP_KERNEL)) != 0);
82 XA_BUG_ON(xa, xa_err(xa_erase(xa, 1)) != 0);
83// kills the test-suite :-(
84// XA_BUG_ON(xa, xa_err(xa_store(xa, 0, xa_mk_internal(0), 0)) != -EINVAL);
ad3d6c72
MW
85}
86
b803b428
MW
87static noinline void check_xas_retry(struct xarray *xa)
88{
89 XA_STATE(xas, xa, 0);
90 void *entry;
91
92 xa_store_index(xa, 0, GFP_KERNEL);
93 xa_store_index(xa, 1, GFP_KERNEL);
94
95 rcu_read_lock();
96 XA_BUG_ON(xa, xas_find(&xas, ULONG_MAX) != xa_mk_value(0));
97 xa_erase_index(xa, 1);
98 XA_BUG_ON(xa, !xa_is_retry(xas_reload(&xas)));
99 XA_BUG_ON(xa, xas_retry(&xas, NULL));
100 XA_BUG_ON(xa, xas_retry(&xas, xa_mk_value(0)));
101 xas_reset(&xas);
102 XA_BUG_ON(xa, xas.xa_node != XAS_RESTART);
103 XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
104 XA_BUG_ON(xa, xas.xa_node != NULL);
105
106 XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL);
107 XA_BUG_ON(xa, !xa_is_internal(xas_reload(&xas)));
108 xas.xa_node = XAS_RESTART;
109 XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
110 rcu_read_unlock();
111
112 /* Make sure we can iterate through retry entries */
113 xas_lock(&xas);
114 xas_set(&xas, 0);
115 xas_store(&xas, XA_RETRY_ENTRY);
116 xas_set(&xas, 1);
117 xas_store(&xas, XA_RETRY_ENTRY);
118
119 xas_set(&xas, 0);
120 xas_for_each(&xas, entry, ULONG_MAX) {
121 xas_store(&xas, xa_mk_value(xas.xa_index));
122 }
123 xas_unlock(&xas);
124
125 xa_erase_index(xa, 0);
126 xa_erase_index(xa, 1);
127}
128
ad3d6c72
MW
129static noinline void check_xa_load(struct xarray *xa)
130{
131 unsigned long i, j;
132
133 for (i = 0; i < 1024; i++) {
134 for (j = 0; j < 1024; j++) {
135 void *entry = xa_load(xa, j);
136 if (j < i)
137 XA_BUG_ON(xa, xa_to_value(entry) != j);
138 else
139 XA_BUG_ON(xa, entry);
140 }
141 XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
142 }
143
144 for (i = 0; i < 1024; i++) {
145 for (j = 0; j < 1024; j++) {
146 void *entry = xa_load(xa, j);
147 if (j >= i)
148 XA_BUG_ON(xa, xa_to_value(entry) != j);
149 else
150 XA_BUG_ON(xa, entry);
151 }
152 xa_erase_index(xa, i);
153 }
154 XA_BUG_ON(xa, !xa_empty(xa));
155}
156
9b89a035
MW
157static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
158{
58d6ea30
MW
159 unsigned int order;
160 unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 8 : 1;
161
9b89a035
MW
162 /* NULL elements have no marks set */
163 XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
164 xa_set_mark(xa, index, XA_MARK_0);
165 XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
166
167 /* Storing a pointer will not make a mark appear */
168 XA_BUG_ON(xa, xa_store_index(xa, index, GFP_KERNEL) != NULL);
169 XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
170 xa_set_mark(xa, index, XA_MARK_0);
171 XA_BUG_ON(xa, !xa_get_mark(xa, index, XA_MARK_0));
172
173 /* Setting one mark will not set another mark */
174 XA_BUG_ON(xa, xa_get_mark(xa, index + 1, XA_MARK_0));
175 XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_1));
176
177 /* Storing NULL clears marks, and they can't be set again */
178 xa_erase_index(xa, index);
179 XA_BUG_ON(xa, !xa_empty(xa));
180 XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
181 xa_set_mark(xa, index, XA_MARK_0);
182 XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
58d6ea30
MW
183
184 /*
185 * Storing a multi-index entry over entries with marks gives the
186 * entire entry the union of the marks
187 */
188 BUG_ON((index % 4) != 0);
189 for (order = 2; order < max_order; order++) {
190 unsigned long base = round_down(index, 1UL << order);
191 unsigned long next = base + (1UL << order);
192 unsigned long i;
193
194 XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL));
195 xa_set_mark(xa, index + 1, XA_MARK_0);
196 XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL));
197 xa_set_mark(xa, index + 2, XA_MARK_1);
198 XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL));
199 xa_store_order(xa, index, order, xa_mk_value(index),
200 GFP_KERNEL);
201 for (i = base; i < next; i++) {
202 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));
204 XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2));
205 }
206 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));
208 XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_2));
209 xa_erase_index(xa, index);
210 xa_erase_index(xa, next);
211 XA_BUG_ON(xa, !xa_empty(xa));
212 }
213 XA_BUG_ON(xa, !xa_empty(xa));
9b89a035
MW
214}
215
216static noinline void check_xa_mark(struct xarray *xa)
217{
218 unsigned long index;
219
220 for (index = 0; index < 16384; index += 4)
221 check_xa_mark_1(xa, index);
222}
223
58d6ea30
MW
224static noinline void check_xa_shrink(struct xarray *xa)
225{
226 XA_STATE(xas, xa, 1);
227 struct xa_node *node;
228
229 XA_BUG_ON(xa, !xa_empty(xa));
230 XA_BUG_ON(xa, xa_store_index(xa, 0, GFP_KERNEL) != NULL);
231 XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL);
232
233 /*
234 * Check that erasing the entry at 1 shrinks the tree and properly
235 * marks the node as being deleted.
236 */
237 xas_lock(&xas);
238 XA_BUG_ON(xa, xas_load(&xas) != xa_mk_value(1));
239 node = xas.xa_node;
240 XA_BUG_ON(xa, xa_entry_locked(xa, node, 0) != xa_mk_value(0));
241 XA_BUG_ON(xa, xas_store(&xas, NULL) != xa_mk_value(1));
242 XA_BUG_ON(xa, xa_load(xa, 1) != NULL);
243 XA_BUG_ON(xa, xas.xa_node != XAS_BOUNDS);
244 XA_BUG_ON(xa, xa_entry_locked(xa, node, 0) != XA_RETRY_ENTRY);
245 XA_BUG_ON(xa, xas_load(&xas) != NULL);
246 xas_unlock(&xas);
247 XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
248 xa_erase_index(xa, 0);
249 XA_BUG_ON(xa, !xa_empty(xa));
250}
251
41aec91f
MW
252static noinline void check_cmpxchg(struct xarray *xa)
253{
254 void *FIVE = xa_mk_value(5);
255 void *SIX = xa_mk_value(6);
256 void *LOTS = xa_mk_value(12345678);
257
258 XA_BUG_ON(xa, !xa_empty(xa));
259 XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_KERNEL) != NULL);
260 XA_BUG_ON(xa, xa_insert(xa, 12345678, xa, GFP_KERNEL) != -EEXIST);
261 XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, SIX, FIVE, GFP_KERNEL) != LOTS);
262 XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, LOTS, FIVE, GFP_KERNEL) != LOTS);
263 XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, FIVE, LOTS, GFP_KERNEL) != FIVE);
264 XA_BUG_ON(xa, xa_cmpxchg(xa, 5, FIVE, NULL, GFP_KERNEL) != NULL);
265 XA_BUG_ON(xa, xa_cmpxchg(xa, 5, NULL, FIVE, GFP_KERNEL) != NULL);
266 xa_erase_index(xa, 12345678);
267 xa_erase_index(xa, 5);
268 XA_BUG_ON(xa, !xa_empty(xa));
269}
270
9f14d4f1
MW
271static noinline void check_reserve(struct xarray *xa)
272{
273 void *entry;
274 unsigned long index = 0;
275
276 /* An array with a reserved entry is not empty */
277 XA_BUG_ON(xa, !xa_empty(xa));
278 xa_reserve(xa, 12345678, GFP_KERNEL);
279 XA_BUG_ON(xa, xa_empty(xa));
280 XA_BUG_ON(xa, xa_load(xa, 12345678));
281 xa_release(xa, 12345678);
282 XA_BUG_ON(xa, !xa_empty(xa));
283
284 /* Releasing a used entry does nothing */
285 xa_reserve(xa, 12345678, GFP_KERNEL);
286 XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_NOWAIT) != NULL);
287 xa_release(xa, 12345678);
288 xa_erase_index(xa, 12345678);
289 XA_BUG_ON(xa, !xa_empty(xa));
290
291 /* cmpxchg sees a reserved entry as NULL */
292 xa_reserve(xa, 12345678, GFP_KERNEL);
293 XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, NULL, xa_mk_value(12345678),
294 GFP_NOWAIT) != NULL);
295 xa_release(xa, 12345678);
296 xa_erase_index(xa, 12345678);
297 XA_BUG_ON(xa, !xa_empty(xa));
298
299 /* Can iterate through a reserved entry */
300 xa_store_index(xa, 5, GFP_KERNEL);
301 xa_reserve(xa, 6, GFP_KERNEL);
302 xa_store_index(xa, 7, GFP_KERNEL);
303
304 xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
305 XA_BUG_ON(xa, index != 5 && index != 7);
306 }
307 xa_destroy(xa);
308}
309
b803b428
MW
310static noinline void check_xas_erase(struct xarray *xa)
311{
312 XA_STATE(xas, xa, 0);
313 void *entry;
314 unsigned long i, j;
315
316 for (i = 0; i < 200; i++) {
317 for (j = i; j < 2 * i + 17; j++) {
318 xas_set(&xas, j);
319 do {
320 xas_lock(&xas);
321 xas_store(&xas, xa_mk_value(j));
322 xas_unlock(&xas);
323 } while (xas_nomem(&xas, GFP_KERNEL));
324 }
325
326 xas_set(&xas, ULONG_MAX);
327 do {
328 xas_lock(&xas);
329 xas_store(&xas, xa_mk_value(0));
330 xas_unlock(&xas);
331 } while (xas_nomem(&xas, GFP_KERNEL));
332
333 xas_lock(&xas);
334 xas_store(&xas, NULL);
335
336 xas_set(&xas, 0);
337 j = i;
338 xas_for_each(&xas, entry, ULONG_MAX) {
339 XA_BUG_ON(xa, entry != xa_mk_value(j));
340 xas_store(&xas, NULL);
341 j++;
342 }
343 xas_unlock(&xas);
344 XA_BUG_ON(xa, !xa_empty(xa));
345 }
346}
347
58d6ea30
MW
348static noinline void check_multi_store(struct xarray *xa)
349{
350#ifdef CONFIG_XARRAY_MULTI
351 unsigned long i, j, k;
352 unsigned int max_order = (sizeof(long) == 4) ? 30 : 60;
353
354 /* Loading from any position returns the same value */
355 xa_store_order(xa, 0, 1, xa_mk_value(0), GFP_KERNEL);
356 XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
357 XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(0));
358 XA_BUG_ON(xa, xa_load(xa, 2) != NULL);
359 rcu_read_lock();
360 XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 2);
361 XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 2);
362 rcu_read_unlock();
363
364 /* Storing adjacent to the value does not alter the value */
365 xa_store(xa, 3, xa, GFP_KERNEL);
366 XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
367 XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(0));
368 XA_BUG_ON(xa, xa_load(xa, 2) != NULL);
369 rcu_read_lock();
370 XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 3);
371 XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 2);
372 rcu_read_unlock();
373
374 /* Overwriting multiple indexes works */
375 xa_store_order(xa, 0, 2, xa_mk_value(1), GFP_KERNEL);
376 XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(1));
377 XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(1));
378 XA_BUG_ON(xa, xa_load(xa, 2) != xa_mk_value(1));
379 XA_BUG_ON(xa, xa_load(xa, 3) != xa_mk_value(1));
380 XA_BUG_ON(xa, xa_load(xa, 4) != NULL);
381 rcu_read_lock();
382 XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 4);
383 XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 4);
384 rcu_read_unlock();
385
386 /* We can erase multiple values with a single store */
387 xa_store_order(xa, 0, 63, NULL, GFP_KERNEL);
388 XA_BUG_ON(xa, !xa_empty(xa));
389
390 /* Even when the first slot is empty but the others aren't */
391 xa_store_index(xa, 1, GFP_KERNEL);
392 xa_store_index(xa, 2, GFP_KERNEL);
393 xa_store_order(xa, 0, 2, NULL, GFP_KERNEL);
394 XA_BUG_ON(xa, !xa_empty(xa));
395
396 for (i = 0; i < max_order; i++) {
397 for (j = 0; j < max_order; j++) {
398 xa_store_order(xa, 0, i, xa_mk_value(i), GFP_KERNEL);
399 xa_store_order(xa, 0, j, xa_mk_value(j), GFP_KERNEL);
400
401 for (k = 0; k < max_order; k++) {
402 void *entry = xa_load(xa, (1UL << k) - 1);
403 if ((i < k) && (j < k))
404 XA_BUG_ON(xa, entry != NULL);
405 else
406 XA_BUG_ON(xa, entry != xa_mk_value(j));
407 }
408
409 xa_erase(xa, 0);
410 XA_BUG_ON(xa, !xa_empty(xa));
411 }
412 }
413#endif
414}
415
371c752d
MW
416static DEFINE_XARRAY_ALLOC(xa0);
417
418static noinline void check_xa_alloc(void)
419{
420 int i;
421 u32 id;
422
423 /* An empty array should assign 0 to the first alloc */
424 xa_alloc_index(&xa0, 0, GFP_KERNEL);
425
426 /* Erasing it should make the array empty again */
427 xa_erase_index(&xa0, 0);
428 XA_BUG_ON(&xa0, !xa_empty(&xa0));
429
430 /* And it should assign 0 again */
431 xa_alloc_index(&xa0, 0, GFP_KERNEL);
432
433 /* The next assigned ID should be 1 */
434 xa_alloc_index(&xa0, 1, GFP_KERNEL);
435 xa_erase_index(&xa0, 1);
436
437 /* Storing a value should mark it used */
438 xa_store_index(&xa0, 1, GFP_KERNEL);
439 xa_alloc_index(&xa0, 2, GFP_KERNEL);
440
441 /* If we then erase 0, it should be free */
442 xa_erase_index(&xa0, 0);
443 xa_alloc_index(&xa0, 0, GFP_KERNEL);
444
445 xa_erase_index(&xa0, 1);
446 xa_erase_index(&xa0, 2);
447
448 for (i = 1; i < 5000; i++) {
449 xa_alloc_index(&xa0, i, GFP_KERNEL);
450 }
451
452 xa_destroy(&xa0);
453
454 id = 0xfffffffeU;
455 XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
456 GFP_KERNEL) != 0);
457 XA_BUG_ON(&xa0, id != 0xfffffffeU);
458 XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
459 GFP_KERNEL) != 0);
460 XA_BUG_ON(&xa0, id != 0xffffffffU);
461 XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
462 GFP_KERNEL) != -ENOSPC);
463 XA_BUG_ON(&xa0, id != 0xffffffffU);
464 xa_destroy(&xa0);
465}
466
4e99d4e9
MW
467static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
468 unsigned int order, unsigned int present)
469{
470 XA_STATE_ORDER(xas, xa, start, order);
471 void *entry;
472 unsigned int count = 0;
473
474retry:
475 xas_lock(&xas);
476 xas_for_each_conflict(&xas, entry) {
477 XA_BUG_ON(xa, !xa_is_value(entry));
478 XA_BUG_ON(xa, entry < xa_mk_value(start));
479 XA_BUG_ON(xa, entry > xa_mk_value(start + (1UL << order) - 1));
480 count++;
481 }
482 xas_store(&xas, xa_mk_value(start));
483 xas_unlock(&xas);
484 if (xas_nomem(&xas, GFP_KERNEL)) {
485 count = 0;
486 goto retry;
487 }
488 XA_BUG_ON(xa, xas_error(&xas));
489 XA_BUG_ON(xa, count != present);
490 XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_value(start));
491 XA_BUG_ON(xa, xa_load(xa, start + (1UL << order) - 1) !=
492 xa_mk_value(start));
493 xa_erase_index(xa, start);
494}
495
496static noinline void check_store_iter(struct xarray *xa)
497{
498 unsigned int i, j;
499 unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 20 : 1;
500
501 for (i = 0; i < max_order; i++) {
502 unsigned int min = 1 << i;
503 unsigned int max = (2 << i) - 1;
504 __check_store_iter(xa, 0, i, 0);
505 XA_BUG_ON(xa, !xa_empty(xa));
506 __check_store_iter(xa, min, i, 0);
507 XA_BUG_ON(xa, !xa_empty(xa));
508
509 xa_store_index(xa, min, GFP_KERNEL);
510 __check_store_iter(xa, min, i, 1);
511 XA_BUG_ON(xa, !xa_empty(xa));
512 xa_store_index(xa, max, GFP_KERNEL);
513 __check_store_iter(xa, min, i, 1);
514 XA_BUG_ON(xa, !xa_empty(xa));
515
516 for (j = 0; j < min; j++)
517 xa_store_index(xa, j, GFP_KERNEL);
518 __check_store_iter(xa, 0, i, min);
519 XA_BUG_ON(xa, !xa_empty(xa));
520 for (j = 0; j < min; j++)
521 xa_store_index(xa, min + j, GFP_KERNEL);
522 __check_store_iter(xa, min, i, min);
523 XA_BUG_ON(xa, !xa_empty(xa));
524 }
525#ifdef CONFIG_XARRAY_MULTI
526 xa_store_index(xa, 63, GFP_KERNEL);
527 xa_store_index(xa, 65, GFP_KERNEL);
528 __check_store_iter(xa, 64, 2, 1);
529 xa_erase_index(xa, 63);
530#endif
531 XA_BUG_ON(xa, !xa_empty(xa));
532}
533
b803b428
MW
534static noinline void check_multi_find(struct xarray *xa)
535{
536#ifdef CONFIG_XARRAY_MULTI
537 unsigned long index;
538
539 xa_store_order(xa, 12, 2, xa_mk_value(12), GFP_KERNEL);
540 XA_BUG_ON(xa, xa_store_index(xa, 16, GFP_KERNEL) != NULL);
541
542 index = 0;
543 XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
544 xa_mk_value(12));
545 XA_BUG_ON(xa, index != 12);
546 index = 13;
547 XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
548 xa_mk_value(12));
549 XA_BUG_ON(xa, (index < 12) || (index >= 16));
550 XA_BUG_ON(xa, xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT) !=
551 xa_mk_value(16));
552 XA_BUG_ON(xa, index != 16);
553
554 xa_erase_index(xa, 12);
555 xa_erase_index(xa, 16);
556 XA_BUG_ON(xa, !xa_empty(xa));
557#endif
558}
559
560static noinline void check_multi_find_2(struct xarray *xa)
561{
562 unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 10 : 1;
563 unsigned int i, j;
564 void *entry;
565
566 for (i = 0; i < max_order; i++) {
567 unsigned long index = 1UL << i;
568 for (j = 0; j < index; j++) {
569 XA_STATE(xas, xa, j + index);
570 xa_store_index(xa, index - 1, GFP_KERNEL);
571 xa_store_order(xa, index, i, xa_mk_value(index),
572 GFP_KERNEL);
573 rcu_read_lock();
574 xas_for_each(&xas, entry, ULONG_MAX) {
575 xa_erase_index(xa, index);
576 }
577 rcu_read_unlock();
578 xa_erase_index(xa, index - 1);
579 XA_BUG_ON(xa, !xa_empty(xa));
580 }
581 }
582}
583
584static noinline void check_find(struct xarray *xa)
585{
586 unsigned long i, j, k;
587
588 XA_BUG_ON(xa, !xa_empty(xa));
589
590 /*
591 * Check xa_find with all pairs between 0 and 99 inclusive,
592 * starting at every index between 0 and 99
593 */
594 for (i = 0; i < 100; i++) {
595 XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
596 xa_set_mark(xa, i, XA_MARK_0);
597 for (j = 0; j < i; j++) {
598 XA_BUG_ON(xa, xa_store_index(xa, j, GFP_KERNEL) !=
599 NULL);
600 xa_set_mark(xa, j, XA_MARK_0);
601 for (k = 0; k < 100; k++) {
602 unsigned long index = k;
603 void *entry = xa_find(xa, &index, ULONG_MAX,
604 XA_PRESENT);
605 if (k <= j)
606 XA_BUG_ON(xa, index != j);
607 else if (k <= i)
608 XA_BUG_ON(xa, index != i);
609 else
610 XA_BUG_ON(xa, entry != NULL);
611
612 index = k;
613 entry = xa_find(xa, &index, ULONG_MAX,
614 XA_MARK_0);
615 if (k <= j)
616 XA_BUG_ON(xa, index != j);
617 else if (k <= i)
618 XA_BUG_ON(xa, index != i);
619 else
620 XA_BUG_ON(xa, entry != NULL);
621 }
622 xa_erase_index(xa, j);
623 XA_BUG_ON(xa, xa_get_mark(xa, j, XA_MARK_0));
624 XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
625 }
626 xa_erase_index(xa, i);
627 XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_0));
628 }
629 XA_BUG_ON(xa, !xa_empty(xa));
630 check_multi_find(xa);
631 check_multi_find_2(xa);
632}
633
64d3e9a9
MW
634static noinline void check_move_small(struct xarray *xa, unsigned long idx)
635{
636 XA_STATE(xas, xa, 0);
637 unsigned long i;
638
639 xa_store_index(xa, 0, GFP_KERNEL);
640 xa_store_index(xa, idx, GFP_KERNEL);
641
642 rcu_read_lock();
643 for (i = 0; i < idx * 4; i++) {
644 void *entry = xas_next(&xas);
645 if (i <= idx)
646 XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
647 XA_BUG_ON(xa, xas.xa_index != i);
648 if (i == 0 || i == idx)
649 XA_BUG_ON(xa, entry != xa_mk_value(i));
650 else
651 XA_BUG_ON(xa, entry != NULL);
652 }
653 xas_next(&xas);
654 XA_BUG_ON(xa, xas.xa_index != i);
655
656 do {
657 void *entry = xas_prev(&xas);
658 i--;
659 if (i <= idx)
660 XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
661 XA_BUG_ON(xa, xas.xa_index != i);
662 if (i == 0 || i == idx)
663 XA_BUG_ON(xa, entry != xa_mk_value(i));
664 else
665 XA_BUG_ON(xa, entry != NULL);
666 } while (i > 0);
667
668 xas_set(&xas, ULONG_MAX);
669 XA_BUG_ON(xa, xas_next(&xas) != NULL);
670 XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
671 XA_BUG_ON(xa, xas_next(&xas) != xa_mk_value(0));
672 XA_BUG_ON(xa, xas.xa_index != 0);
673 XA_BUG_ON(xa, xas_prev(&xas) != NULL);
674 XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
675 rcu_read_unlock();
676
677 xa_erase_index(xa, 0);
678 xa_erase_index(xa, idx);
679 XA_BUG_ON(xa, !xa_empty(xa));
680}
681
682static noinline void check_move(struct xarray *xa)
683{
684 XA_STATE(xas, xa, (1 << 16) - 1);
685 unsigned long i;
686
687 for (i = 0; i < (1 << 16); i++)
688 XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
689
690 rcu_read_lock();
691 do {
692 void *entry = xas_prev(&xas);
693 i--;
694 XA_BUG_ON(xa, entry != xa_mk_value(i));
695 XA_BUG_ON(xa, i != xas.xa_index);
696 } while (i != 0);
697
698 XA_BUG_ON(xa, xas_prev(&xas) != NULL);
699 XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
700
701 do {
702 void *entry = xas_next(&xas);
703 XA_BUG_ON(xa, entry != xa_mk_value(i));
704 XA_BUG_ON(xa, i != xas.xa_index);
705 i++;
706 } while (i < (1 << 16));
707 rcu_read_unlock();
708
709 for (i = (1 << 8); i < (1 << 15); i++)
710 xa_erase_index(xa, i);
711
712 i = xas.xa_index;
713
714 rcu_read_lock();
715 do {
716 void *entry = xas_prev(&xas);
717 i--;
718 if ((i < (1 << 8)) || (i >= (1 << 15)))
719 XA_BUG_ON(xa, entry != xa_mk_value(i));
720 else
721 XA_BUG_ON(xa, entry != NULL);
722 XA_BUG_ON(xa, i != xas.xa_index);
723 } while (i != 0);
724
725 XA_BUG_ON(xa, xas_prev(&xas) != NULL);
726 XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
727
728 do {
729 void *entry = xas_next(&xas);
730 if ((i < (1 << 8)) || (i >= (1 << 15)))
731 XA_BUG_ON(xa, entry != xa_mk_value(i));
732 else
733 XA_BUG_ON(xa, entry != NULL);
734 XA_BUG_ON(xa, i != xas.xa_index);
735 i++;
736 } while (i < (1 << 16));
737 rcu_read_unlock();
738
739 xa_destroy(xa);
740
741 for (i = 0; i < 16; i++)
742 check_move_small(xa, 1UL << i);
743
744 for (i = 2; i < 16; i++)
745 check_move_small(xa, (1UL << i) - 1);
746}
747
2264f513
MW
748static noinline void xa_store_many_order(struct xarray *xa,
749 unsigned long index, unsigned order)
750{
751 XA_STATE_ORDER(xas, xa, index, order);
752 unsigned int i = 0;
753
754 do {
755 xas_lock(&xas);
756 XA_BUG_ON(xa, xas_find_conflict(&xas));
757 xas_create_range(&xas);
758 if (xas_error(&xas))
759 goto unlock;
760 for (i = 0; i < (1U << order); i++) {
761 XA_BUG_ON(xa, xas_store(&xas, xa_mk_value(index + i)));
762 xas_next(&xas);
763 }
764unlock:
765 xas_unlock(&xas);
766 } while (xas_nomem(&xas, GFP_KERNEL));
767
768 XA_BUG_ON(xa, xas_error(&xas));
769}
770
771static noinline void check_create_range_1(struct xarray *xa,
772 unsigned long index, unsigned order)
773{
774 unsigned long i;
775
776 xa_store_many_order(xa, index, order);
777 for (i = index; i < index + (1UL << order); i++)
778 xa_erase_index(xa, i);
779 XA_BUG_ON(xa, !xa_empty(xa));
780}
781
782static noinline void check_create_range_2(struct xarray *xa, unsigned order)
783{
784 unsigned long i;
785 unsigned long nr = 1UL << order;
786
787 for (i = 0; i < nr * nr; i += nr)
788 xa_store_many_order(xa, i, order);
789 for (i = 0; i < nr * nr; i++)
790 xa_erase_index(xa, i);
791 XA_BUG_ON(xa, !xa_empty(xa));
792}
793
794static noinline void check_create_range_3(void)
795{
796 XA_STATE(xas, NULL, 0);
797 xas_set_err(&xas, -EEXIST);
798 xas_create_range(&xas);
799 XA_BUG_ON(NULL, xas_error(&xas) != -EEXIST);
800}
801
802static noinline void check_create_range_4(struct xarray *xa,
803 unsigned long index, unsigned order)
804{
805 XA_STATE_ORDER(xas, xa, index, order);
806 unsigned long base = xas.xa_index;
807 unsigned long i = 0;
808
809 xa_store_index(xa, index, GFP_KERNEL);
810 do {
811 xas_lock(&xas);
812 xas_create_range(&xas);
813 if (xas_error(&xas))
814 goto unlock;
815 for (i = 0; i < (1UL << order); i++) {
816 void *old = xas_store(&xas, xa_mk_value(base + i));
817 if (xas.xa_index == index)
818 XA_BUG_ON(xa, old != xa_mk_value(base + i));
819 else
820 XA_BUG_ON(xa, old != NULL);
821 xas_next(&xas);
822 }
823unlock:
824 xas_unlock(&xas);
825 } while (xas_nomem(&xas, GFP_KERNEL));
826
827 XA_BUG_ON(xa, xas_error(&xas));
828
829 for (i = base; i < base + (1UL << order); i++)
830 xa_erase_index(xa, i);
831 XA_BUG_ON(xa, !xa_empty(xa));
832}
833
834static noinline void check_create_range(struct xarray *xa)
835{
836 unsigned int order;
837 unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 12 : 1;
838
839 for (order = 0; order < max_order; order++) {
840 check_create_range_1(xa, 0, order);
841 check_create_range_1(xa, 1U << order, order);
842 check_create_range_1(xa, 2U << order, order);
843 check_create_range_1(xa, 3U << order, order);
844 check_create_range_1(xa, 1U << 24, order);
845 if (order < 10)
846 check_create_range_2(xa, order);
847
848 check_create_range_4(xa, 0, order);
849 check_create_range_4(xa, 1U << order, order);
850 check_create_range_4(xa, 2U << order, order);
851 check_create_range_4(xa, 3U << order, order);
852 check_create_range_4(xa, 1U << 24, order);
853
854 check_create_range_4(xa, 1, order);
855 check_create_range_4(xa, (1U << order) + 1, order);
856 check_create_range_4(xa, (2U << order) + 1, order);
857 check_create_range_4(xa, (2U << order) - 1, order);
858 check_create_range_4(xa, (3U << order) + 1, order);
859 check_create_range_4(xa, (3U << order) - 1, order);
860 check_create_range_4(xa, (1U << 24) + 1, order);
861 }
862
863 check_create_range_3();
864}
865
687149fc
MW
866static noinline void check_destroy(struct xarray *xa)
867{
868 unsigned long index;
869
870 XA_BUG_ON(xa, !xa_empty(xa));
871
872 /* Destroying an empty array is a no-op */
873 xa_destroy(xa);
874 XA_BUG_ON(xa, !xa_empty(xa));
875
876 /* Destroying an array with a single entry */
877 for (index = 0; index < 1000; index++) {
878 xa_store_index(xa, index, GFP_KERNEL);
879 XA_BUG_ON(xa, xa_empty(xa));
880 xa_destroy(xa);
881 XA_BUG_ON(xa, !xa_empty(xa));
882 }
883
884 /* Destroying an array with a single entry at ULONG_MAX */
885 xa_store(xa, ULONG_MAX, xa, GFP_KERNEL);
886 XA_BUG_ON(xa, xa_empty(xa));
887 xa_destroy(xa);
888 XA_BUG_ON(xa, !xa_empty(xa));
889
890#ifdef CONFIG_XARRAY_MULTI
891 /* Destroying an array with a multi-index entry */
892 xa_store_order(xa, 1 << 11, 11, xa, GFP_KERNEL);
893 XA_BUG_ON(xa, xa_empty(xa));
894 xa_destroy(xa);
895 XA_BUG_ON(xa, !xa_empty(xa));
896#endif
897}
898
58d6ea30 899static DEFINE_XARRAY(array);
ad3d6c72
MW
900
901static int xarray_checks(void)
902{
58d6ea30 903 check_xa_err(&array);
b803b428 904 check_xas_retry(&array);
ad3d6c72 905 check_xa_load(&array);
9b89a035 906 check_xa_mark(&array);
58d6ea30 907 check_xa_shrink(&array);
b803b428 908 check_xas_erase(&array);
41aec91f 909 check_cmpxchg(&array);
9f14d4f1 910 check_reserve(&array);
58d6ea30 911 check_multi_store(&array);
371c752d 912 check_xa_alloc();
b803b428 913 check_find(&array);
687149fc 914 check_destroy(&array);
64d3e9a9 915 check_move(&array);
2264f513 916 check_create_range(&array);
4e99d4e9 917 check_store_iter(&array);
ad3d6c72
MW
918
919 printk("XArray: %u of %u tests passed\n", tests_passed, tests_run);
920 return (tests_run == tests_passed) ? 0 : -EINVAL;
921}
922
923static void xarray_exit(void)
924{
925}
926
927module_init(xarray_checks);
928module_exit(xarray_exit);
929MODULE_AUTHOR("Matthew Wilcox <willy@infradead.org>");
930MODULE_LICENSE("GPL");