xref: /linux-6.15/lib/test_xarray.c (revision 371c752d)
1ad3d6c72SMatthew Wilcox // SPDX-License-Identifier: GPL-2.0+
2ad3d6c72SMatthew Wilcox /*
3ad3d6c72SMatthew Wilcox  * test_xarray.c: Test the XArray API
4ad3d6c72SMatthew Wilcox  * Copyright (c) 2017-2018 Microsoft Corporation
5ad3d6c72SMatthew Wilcox  * Author: Matthew Wilcox <[email protected]>
6ad3d6c72SMatthew Wilcox  */
7ad3d6c72SMatthew Wilcox 
8ad3d6c72SMatthew Wilcox #include <linux/xarray.h>
9ad3d6c72SMatthew Wilcox #include <linux/module.h>
10ad3d6c72SMatthew Wilcox 
11ad3d6c72SMatthew Wilcox static unsigned int tests_run;
12ad3d6c72SMatthew Wilcox static unsigned int tests_passed;
13ad3d6c72SMatthew Wilcox 
14ad3d6c72SMatthew Wilcox #ifndef XA_DEBUG
15ad3d6c72SMatthew Wilcox # ifdef __KERNEL__
16ad3d6c72SMatthew Wilcox void xa_dump(const struct xarray *xa) { }
17ad3d6c72SMatthew Wilcox # endif
18ad3d6c72SMatthew Wilcox #undef XA_BUG_ON
19ad3d6c72SMatthew Wilcox #define XA_BUG_ON(xa, x) do {					\
20ad3d6c72SMatthew Wilcox 	tests_run++;						\
21ad3d6c72SMatthew Wilcox 	if (x) {						\
22ad3d6c72SMatthew Wilcox 		printk("BUG at %s:%d\n", __func__, __LINE__);	\
23ad3d6c72SMatthew Wilcox 		xa_dump(xa);					\
24ad3d6c72SMatthew Wilcox 		dump_stack();					\
25ad3d6c72SMatthew Wilcox 	} else {						\
26ad3d6c72SMatthew Wilcox 		tests_passed++;					\
27ad3d6c72SMatthew Wilcox 	}							\
28ad3d6c72SMatthew Wilcox } while (0)
29ad3d6c72SMatthew Wilcox #endif
30ad3d6c72SMatthew Wilcox 
31ad3d6c72SMatthew Wilcox static void *xa_store_index(struct xarray *xa, unsigned long index, gfp_t gfp)
32ad3d6c72SMatthew Wilcox {
3358d6ea30SMatthew Wilcox 	return xa_store(xa, index, xa_mk_value(index & LONG_MAX), gfp);
34ad3d6c72SMatthew Wilcox }
35ad3d6c72SMatthew Wilcox 
36*371c752dSMatthew Wilcox static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp)
37*371c752dSMatthew Wilcox {
38*371c752dSMatthew Wilcox 	u32 id = 0;
39*371c752dSMatthew Wilcox 
40*371c752dSMatthew Wilcox 	XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_value(index & LONG_MAX),
41*371c752dSMatthew Wilcox 				gfp) != 0);
42*371c752dSMatthew Wilcox 	XA_BUG_ON(xa, id != index);
43*371c752dSMatthew Wilcox }
44*371c752dSMatthew Wilcox 
45ad3d6c72SMatthew Wilcox static void xa_erase_index(struct xarray *xa, unsigned long index)
46ad3d6c72SMatthew Wilcox {
4758d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_erase(xa, index) != xa_mk_value(index & LONG_MAX));
4858d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, index) != NULL);
4958d6ea30SMatthew Wilcox }
5058d6ea30SMatthew Wilcox 
5158d6ea30SMatthew Wilcox /*
5258d6ea30SMatthew Wilcox  * If anyone needs this, please move it to xarray.c.  We have no current
5358d6ea30SMatthew Wilcox  * users outside the test suite because all current multislot users want
5458d6ea30SMatthew Wilcox  * to use the advanced API.
5558d6ea30SMatthew Wilcox  */
5658d6ea30SMatthew Wilcox static void *xa_store_order(struct xarray *xa, unsigned long index,
5758d6ea30SMatthew Wilcox 		unsigned order, void *entry, gfp_t gfp)
5858d6ea30SMatthew Wilcox {
5958d6ea30SMatthew Wilcox 	XA_STATE_ORDER(xas, xa, index, order);
6058d6ea30SMatthew Wilcox 	void *curr;
6158d6ea30SMatthew Wilcox 
6258d6ea30SMatthew Wilcox 	do {
6358d6ea30SMatthew Wilcox 		xas_lock(&xas);
6458d6ea30SMatthew Wilcox 		curr = xas_store(&xas, entry);
6558d6ea30SMatthew Wilcox 		xas_unlock(&xas);
6658d6ea30SMatthew Wilcox 	} while (xas_nomem(&xas, gfp));
6758d6ea30SMatthew Wilcox 
6858d6ea30SMatthew Wilcox 	return curr;
6958d6ea30SMatthew Wilcox }
7058d6ea30SMatthew Wilcox 
7158d6ea30SMatthew Wilcox static noinline void check_xa_err(struct xarray *xa)
7258d6ea30SMatthew Wilcox {
7358d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_err(xa_store_index(xa, 0, GFP_NOWAIT)) != 0);
7458d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_err(xa_erase(xa, 0)) != 0);
7558d6ea30SMatthew Wilcox #ifndef __KERNEL__
7658d6ea30SMatthew Wilcox 	/* The kernel does not fail GFP_NOWAIT allocations */
7758d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_NOWAIT)) != -ENOMEM);
7858d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_NOWAIT)) != -ENOMEM);
7958d6ea30SMatthew Wilcox #endif
8058d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_KERNEL)) != 0);
8158d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_err(xa_store(xa, 1, xa_mk_value(0), GFP_KERNEL)) != 0);
8258d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_err(xa_erase(xa, 1)) != 0);
8358d6ea30SMatthew Wilcox // kills the test-suite :-(
8458d6ea30SMatthew Wilcox //	XA_BUG_ON(xa, xa_err(xa_store(xa, 0, xa_mk_internal(0), 0)) != -EINVAL);
85ad3d6c72SMatthew Wilcox }
86ad3d6c72SMatthew Wilcox 
87b803b428SMatthew Wilcox static noinline void check_xas_retry(struct xarray *xa)
88b803b428SMatthew Wilcox {
89b803b428SMatthew Wilcox 	XA_STATE(xas, xa, 0);
90b803b428SMatthew Wilcox 	void *entry;
91b803b428SMatthew Wilcox 
92b803b428SMatthew Wilcox 	xa_store_index(xa, 0, GFP_KERNEL);
93b803b428SMatthew Wilcox 	xa_store_index(xa, 1, GFP_KERNEL);
94b803b428SMatthew Wilcox 
95b803b428SMatthew Wilcox 	rcu_read_lock();
96b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xas_find(&xas, ULONG_MAX) != xa_mk_value(0));
97b803b428SMatthew Wilcox 	xa_erase_index(xa, 1);
98b803b428SMatthew Wilcox 	XA_BUG_ON(xa, !xa_is_retry(xas_reload(&xas)));
99b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xas_retry(&xas, NULL));
100b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xas_retry(&xas, xa_mk_value(0)));
101b803b428SMatthew Wilcox 	xas_reset(&xas);
102b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_node != XAS_RESTART);
103b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
104b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_node != NULL);
105b803b428SMatthew Wilcox 
106b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL);
107b803b428SMatthew Wilcox 	XA_BUG_ON(xa, !xa_is_internal(xas_reload(&xas)));
108b803b428SMatthew Wilcox 	xas.xa_node = XAS_RESTART;
109b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
110b803b428SMatthew Wilcox 	rcu_read_unlock();
111b803b428SMatthew Wilcox 
112b803b428SMatthew Wilcox 	/* Make sure we can iterate through retry entries */
113b803b428SMatthew Wilcox 	xas_lock(&xas);
114b803b428SMatthew Wilcox 	xas_set(&xas, 0);
115b803b428SMatthew Wilcox 	xas_store(&xas, XA_RETRY_ENTRY);
116b803b428SMatthew Wilcox 	xas_set(&xas, 1);
117b803b428SMatthew Wilcox 	xas_store(&xas, XA_RETRY_ENTRY);
118b803b428SMatthew Wilcox 
119b803b428SMatthew Wilcox 	xas_set(&xas, 0);
120b803b428SMatthew Wilcox 	xas_for_each(&xas, entry, ULONG_MAX) {
121b803b428SMatthew Wilcox 		xas_store(&xas, xa_mk_value(xas.xa_index));
122b803b428SMatthew Wilcox 	}
123b803b428SMatthew Wilcox 	xas_unlock(&xas);
124b803b428SMatthew Wilcox 
125b803b428SMatthew Wilcox 	xa_erase_index(xa, 0);
126b803b428SMatthew Wilcox 	xa_erase_index(xa, 1);
127b803b428SMatthew Wilcox }
128b803b428SMatthew Wilcox 
129ad3d6c72SMatthew Wilcox static noinline void check_xa_load(struct xarray *xa)
130ad3d6c72SMatthew Wilcox {
131ad3d6c72SMatthew Wilcox 	unsigned long i, j;
132ad3d6c72SMatthew Wilcox 
133ad3d6c72SMatthew Wilcox 	for (i = 0; i < 1024; i++) {
134ad3d6c72SMatthew Wilcox 		for (j = 0; j < 1024; j++) {
135ad3d6c72SMatthew Wilcox 			void *entry = xa_load(xa, j);
136ad3d6c72SMatthew Wilcox 			if (j < i)
137ad3d6c72SMatthew Wilcox 				XA_BUG_ON(xa, xa_to_value(entry) != j);
138ad3d6c72SMatthew Wilcox 			else
139ad3d6c72SMatthew Wilcox 				XA_BUG_ON(xa, entry);
140ad3d6c72SMatthew Wilcox 		}
141ad3d6c72SMatthew Wilcox 		XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
142ad3d6c72SMatthew Wilcox 	}
143ad3d6c72SMatthew Wilcox 
144ad3d6c72SMatthew Wilcox 	for (i = 0; i < 1024; i++) {
145ad3d6c72SMatthew Wilcox 		for (j = 0; j < 1024; j++) {
146ad3d6c72SMatthew Wilcox 			void *entry = xa_load(xa, j);
147ad3d6c72SMatthew Wilcox 			if (j >= i)
148ad3d6c72SMatthew Wilcox 				XA_BUG_ON(xa, xa_to_value(entry) != j);
149ad3d6c72SMatthew Wilcox 			else
150ad3d6c72SMatthew Wilcox 				XA_BUG_ON(xa, entry);
151ad3d6c72SMatthew Wilcox 		}
152ad3d6c72SMatthew Wilcox 		xa_erase_index(xa, i);
153ad3d6c72SMatthew Wilcox 	}
154ad3d6c72SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
155ad3d6c72SMatthew Wilcox }
156ad3d6c72SMatthew Wilcox 
1579b89a035SMatthew Wilcox static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
1589b89a035SMatthew Wilcox {
15958d6ea30SMatthew Wilcox 	unsigned int order;
16058d6ea30SMatthew Wilcox 	unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 8 : 1;
16158d6ea30SMatthew Wilcox 
1629b89a035SMatthew Wilcox 	/* NULL elements have no marks set */
1639b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
1649b89a035SMatthew Wilcox 	xa_set_mark(xa, index, XA_MARK_0);
1659b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
1669b89a035SMatthew Wilcox 
1679b89a035SMatthew Wilcox 	/* Storing a pointer will not make a mark appear */
1689b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_store_index(xa, index, GFP_KERNEL) != NULL);
1699b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
1709b89a035SMatthew Wilcox 	xa_set_mark(xa, index, XA_MARK_0);
1719b89a035SMatthew Wilcox 	XA_BUG_ON(xa, !xa_get_mark(xa, index, XA_MARK_0));
1729b89a035SMatthew Wilcox 
1739b89a035SMatthew Wilcox 	/* Setting one mark will not set another mark */
1749b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_get_mark(xa, index + 1, XA_MARK_0));
1759b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_1));
1769b89a035SMatthew Wilcox 
1779b89a035SMatthew Wilcox 	/* Storing NULL clears marks, and they can't be set again */
1789b89a035SMatthew Wilcox 	xa_erase_index(xa, index);
1799b89a035SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
1809b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
1819b89a035SMatthew Wilcox 	xa_set_mark(xa, index, XA_MARK_0);
1829b89a035SMatthew Wilcox 	XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
18358d6ea30SMatthew Wilcox 
18458d6ea30SMatthew Wilcox 	/*
18558d6ea30SMatthew Wilcox 	 * Storing a multi-index entry over entries with marks gives the
18658d6ea30SMatthew Wilcox 	 * entire entry the union of the marks
18758d6ea30SMatthew Wilcox 	 */
18858d6ea30SMatthew Wilcox 	BUG_ON((index % 4) != 0);
18958d6ea30SMatthew Wilcox 	for (order = 2; order < max_order; order++) {
19058d6ea30SMatthew Wilcox 		unsigned long base = round_down(index, 1UL << order);
19158d6ea30SMatthew Wilcox 		unsigned long next = base + (1UL << order);
19258d6ea30SMatthew Wilcox 		unsigned long i;
19358d6ea30SMatthew Wilcox 
19458d6ea30SMatthew Wilcox 		XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL));
19558d6ea30SMatthew Wilcox 		xa_set_mark(xa, index + 1, XA_MARK_0);
19658d6ea30SMatthew Wilcox 		XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL));
19758d6ea30SMatthew Wilcox 		xa_set_mark(xa, index + 2, XA_MARK_1);
19858d6ea30SMatthew Wilcox 		XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL));
19958d6ea30SMatthew Wilcox 		xa_store_order(xa, index, order, xa_mk_value(index),
20058d6ea30SMatthew Wilcox 				GFP_KERNEL);
20158d6ea30SMatthew Wilcox 		for (i = base; i < next; i++) {
20258d6ea30SMatthew Wilcox 			XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
20358d6ea30SMatthew Wilcox 			XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1));
20458d6ea30SMatthew Wilcox 			XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2));
20558d6ea30SMatthew Wilcox 		}
20658d6ea30SMatthew Wilcox 		XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_0));
20758d6ea30SMatthew Wilcox 		XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_1));
20858d6ea30SMatthew Wilcox 		XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_2));
20958d6ea30SMatthew Wilcox 		xa_erase_index(xa, index);
21058d6ea30SMatthew Wilcox 		xa_erase_index(xa, next);
21158d6ea30SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
21258d6ea30SMatthew Wilcox 	}
21358d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
2149b89a035SMatthew Wilcox }
2159b89a035SMatthew Wilcox 
2169b89a035SMatthew Wilcox static noinline void check_xa_mark(struct xarray *xa)
2179b89a035SMatthew Wilcox {
2189b89a035SMatthew Wilcox 	unsigned long index;
2199b89a035SMatthew Wilcox 
2209b89a035SMatthew Wilcox 	for (index = 0; index < 16384; index += 4)
2219b89a035SMatthew Wilcox 		check_xa_mark_1(xa, index);
2229b89a035SMatthew Wilcox }
2239b89a035SMatthew Wilcox 
22458d6ea30SMatthew Wilcox static noinline void check_xa_shrink(struct xarray *xa)
22558d6ea30SMatthew Wilcox {
22658d6ea30SMatthew Wilcox 	XA_STATE(xas, xa, 1);
22758d6ea30SMatthew Wilcox 	struct xa_node *node;
22858d6ea30SMatthew Wilcox 
22958d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
23058d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_store_index(xa, 0, GFP_KERNEL) != NULL);
23158d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL);
23258d6ea30SMatthew Wilcox 
23358d6ea30SMatthew Wilcox 	/*
23458d6ea30SMatthew Wilcox 	 * Check that erasing the entry at 1 shrinks the tree and properly
23558d6ea30SMatthew Wilcox 	 * marks the node as being deleted.
23658d6ea30SMatthew Wilcox 	 */
23758d6ea30SMatthew Wilcox 	xas_lock(&xas);
23858d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xas_load(&xas) != xa_mk_value(1));
23958d6ea30SMatthew Wilcox 	node = xas.xa_node;
24058d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_entry_locked(xa, node, 0) != xa_mk_value(0));
24158d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xas_store(&xas, NULL) != xa_mk_value(1));
24258d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 1) != NULL);
24358d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_node != XAS_BOUNDS);
24458d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_entry_locked(xa, node, 0) != XA_RETRY_ENTRY);
24558d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xas_load(&xas) != NULL);
24658d6ea30SMatthew Wilcox 	xas_unlock(&xas);
24758d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
24858d6ea30SMatthew Wilcox 	xa_erase_index(xa, 0);
24958d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
25058d6ea30SMatthew Wilcox }
25158d6ea30SMatthew Wilcox 
25241aec91fSMatthew Wilcox static noinline void check_cmpxchg(struct xarray *xa)
25341aec91fSMatthew Wilcox {
25441aec91fSMatthew Wilcox 	void *FIVE = xa_mk_value(5);
25541aec91fSMatthew Wilcox 	void *SIX = xa_mk_value(6);
25641aec91fSMatthew Wilcox 	void *LOTS = xa_mk_value(12345678);
25741aec91fSMatthew Wilcox 
25841aec91fSMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
25941aec91fSMatthew Wilcox 	XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_KERNEL) != NULL);
26041aec91fSMatthew Wilcox 	XA_BUG_ON(xa, xa_insert(xa, 12345678, xa, GFP_KERNEL) != -EEXIST);
26141aec91fSMatthew Wilcox 	XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, SIX, FIVE, GFP_KERNEL) != LOTS);
26241aec91fSMatthew Wilcox 	XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, LOTS, FIVE, GFP_KERNEL) != LOTS);
26341aec91fSMatthew Wilcox 	XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, FIVE, LOTS, GFP_KERNEL) != FIVE);
26441aec91fSMatthew Wilcox 	XA_BUG_ON(xa, xa_cmpxchg(xa, 5, FIVE, NULL, GFP_KERNEL) != NULL);
26541aec91fSMatthew Wilcox 	XA_BUG_ON(xa, xa_cmpxchg(xa, 5, NULL, FIVE, GFP_KERNEL) != NULL);
26641aec91fSMatthew Wilcox 	xa_erase_index(xa, 12345678);
26741aec91fSMatthew Wilcox 	xa_erase_index(xa, 5);
26841aec91fSMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
26941aec91fSMatthew Wilcox }
27041aec91fSMatthew Wilcox 
2719f14d4f1SMatthew Wilcox static noinline void check_reserve(struct xarray *xa)
2729f14d4f1SMatthew Wilcox {
2739f14d4f1SMatthew Wilcox 	void *entry;
2749f14d4f1SMatthew Wilcox 	unsigned long index = 0;
2759f14d4f1SMatthew Wilcox 
2769f14d4f1SMatthew Wilcox 	/* An array with a reserved entry is not empty */
2779f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
2789f14d4f1SMatthew Wilcox 	xa_reserve(xa, 12345678, GFP_KERNEL);
2799f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, xa_empty(xa));
2809f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 12345678));
2819f14d4f1SMatthew Wilcox 	xa_release(xa, 12345678);
2829f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
2839f14d4f1SMatthew Wilcox 
2849f14d4f1SMatthew Wilcox 	/* Releasing a used entry does nothing */
2859f14d4f1SMatthew Wilcox 	xa_reserve(xa, 12345678, GFP_KERNEL);
2869f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_NOWAIT) != NULL);
2879f14d4f1SMatthew Wilcox 	xa_release(xa, 12345678);
2889f14d4f1SMatthew Wilcox 	xa_erase_index(xa, 12345678);
2899f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
2909f14d4f1SMatthew Wilcox 
2919f14d4f1SMatthew Wilcox 	/* cmpxchg sees a reserved entry as NULL */
2929f14d4f1SMatthew Wilcox 	xa_reserve(xa, 12345678, GFP_KERNEL);
2939f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, NULL, xa_mk_value(12345678),
2949f14d4f1SMatthew Wilcox 				GFP_NOWAIT) != NULL);
2959f14d4f1SMatthew Wilcox 	xa_release(xa, 12345678);
2969f14d4f1SMatthew Wilcox 	xa_erase_index(xa, 12345678);
2979f14d4f1SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
2989f14d4f1SMatthew Wilcox 
2999f14d4f1SMatthew Wilcox 	/* Can iterate through a reserved entry */
3009f14d4f1SMatthew Wilcox 	xa_store_index(xa, 5, GFP_KERNEL);
3019f14d4f1SMatthew Wilcox 	xa_reserve(xa, 6, GFP_KERNEL);
3029f14d4f1SMatthew Wilcox 	xa_store_index(xa, 7, GFP_KERNEL);
3039f14d4f1SMatthew Wilcox 
3049f14d4f1SMatthew Wilcox 	xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
3059f14d4f1SMatthew Wilcox 		XA_BUG_ON(xa, index != 5 && index != 7);
3069f14d4f1SMatthew Wilcox 	}
3079f14d4f1SMatthew Wilcox 	xa_destroy(xa);
3089f14d4f1SMatthew Wilcox }
3099f14d4f1SMatthew Wilcox 
310b803b428SMatthew Wilcox static noinline void check_xas_erase(struct xarray *xa)
311b803b428SMatthew Wilcox {
312b803b428SMatthew Wilcox 	XA_STATE(xas, xa, 0);
313b803b428SMatthew Wilcox 	void *entry;
314b803b428SMatthew Wilcox 	unsigned long i, j;
315b803b428SMatthew Wilcox 
316b803b428SMatthew Wilcox 	for (i = 0; i < 200; i++) {
317b803b428SMatthew Wilcox 		for (j = i; j < 2 * i + 17; j++) {
318b803b428SMatthew Wilcox 			xas_set(&xas, j);
319b803b428SMatthew Wilcox 			do {
320b803b428SMatthew Wilcox 				xas_lock(&xas);
321b803b428SMatthew Wilcox 				xas_store(&xas, xa_mk_value(j));
322b803b428SMatthew Wilcox 				xas_unlock(&xas);
323b803b428SMatthew Wilcox 			} while (xas_nomem(&xas, GFP_KERNEL));
324b803b428SMatthew Wilcox 		}
325b803b428SMatthew Wilcox 
326b803b428SMatthew Wilcox 		xas_set(&xas, ULONG_MAX);
327b803b428SMatthew Wilcox 		do {
328b803b428SMatthew Wilcox 			xas_lock(&xas);
329b803b428SMatthew Wilcox 			xas_store(&xas, xa_mk_value(0));
330b803b428SMatthew Wilcox 			xas_unlock(&xas);
331b803b428SMatthew Wilcox 		} while (xas_nomem(&xas, GFP_KERNEL));
332b803b428SMatthew Wilcox 
333b803b428SMatthew Wilcox 		xas_lock(&xas);
334b803b428SMatthew Wilcox 		xas_store(&xas, NULL);
335b803b428SMatthew Wilcox 
336b803b428SMatthew Wilcox 		xas_set(&xas, 0);
337b803b428SMatthew Wilcox 		j = i;
338b803b428SMatthew Wilcox 		xas_for_each(&xas, entry, ULONG_MAX) {
339b803b428SMatthew Wilcox 			XA_BUG_ON(xa, entry != xa_mk_value(j));
340b803b428SMatthew Wilcox 			xas_store(&xas, NULL);
341b803b428SMatthew Wilcox 			j++;
342b803b428SMatthew Wilcox 		}
343b803b428SMatthew Wilcox 		xas_unlock(&xas);
344b803b428SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
345b803b428SMatthew Wilcox 	}
346b803b428SMatthew Wilcox }
347b803b428SMatthew Wilcox 
34858d6ea30SMatthew Wilcox static noinline void check_multi_store(struct xarray *xa)
34958d6ea30SMatthew Wilcox {
35058d6ea30SMatthew Wilcox #ifdef CONFIG_XARRAY_MULTI
35158d6ea30SMatthew Wilcox 	unsigned long i, j, k;
35258d6ea30SMatthew Wilcox 	unsigned int max_order = (sizeof(long) == 4) ? 30 : 60;
35358d6ea30SMatthew Wilcox 
35458d6ea30SMatthew Wilcox 	/* Loading from any position returns the same value */
35558d6ea30SMatthew Wilcox 	xa_store_order(xa, 0, 1, xa_mk_value(0), GFP_KERNEL);
35658d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
35758d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(0));
35858d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 2) != NULL);
35958d6ea30SMatthew Wilcox 	rcu_read_lock();
36058d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 2);
36158d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 2);
36258d6ea30SMatthew Wilcox 	rcu_read_unlock();
36358d6ea30SMatthew Wilcox 
36458d6ea30SMatthew Wilcox 	/* Storing adjacent to the value does not alter the value */
36558d6ea30SMatthew Wilcox 	xa_store(xa, 3, xa, GFP_KERNEL);
36658d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
36758d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(0));
36858d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 2) != NULL);
36958d6ea30SMatthew Wilcox 	rcu_read_lock();
37058d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 3);
37158d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 2);
37258d6ea30SMatthew Wilcox 	rcu_read_unlock();
37358d6ea30SMatthew Wilcox 
37458d6ea30SMatthew Wilcox 	/* Overwriting multiple indexes works */
37558d6ea30SMatthew Wilcox 	xa_store_order(xa, 0, 2, xa_mk_value(1), GFP_KERNEL);
37658d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(1));
37758d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(1));
37858d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 2) != xa_mk_value(1));
37958d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 3) != xa_mk_value(1));
38058d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, 4) != NULL);
38158d6ea30SMatthew Wilcox 	rcu_read_lock();
38258d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 4);
38358d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 4);
38458d6ea30SMatthew Wilcox 	rcu_read_unlock();
38558d6ea30SMatthew Wilcox 
38658d6ea30SMatthew Wilcox 	/* We can erase multiple values with a single store */
38758d6ea30SMatthew Wilcox 	xa_store_order(xa, 0, 63, NULL, GFP_KERNEL);
38858d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
38958d6ea30SMatthew Wilcox 
39058d6ea30SMatthew Wilcox 	/* Even when the first slot is empty but the others aren't */
39158d6ea30SMatthew Wilcox 	xa_store_index(xa, 1, GFP_KERNEL);
39258d6ea30SMatthew Wilcox 	xa_store_index(xa, 2, GFP_KERNEL);
39358d6ea30SMatthew Wilcox 	xa_store_order(xa, 0, 2, NULL, GFP_KERNEL);
39458d6ea30SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
39558d6ea30SMatthew Wilcox 
39658d6ea30SMatthew Wilcox 	for (i = 0; i < max_order; i++) {
39758d6ea30SMatthew Wilcox 		for (j = 0; j < max_order; j++) {
39858d6ea30SMatthew Wilcox 			xa_store_order(xa, 0, i, xa_mk_value(i), GFP_KERNEL);
39958d6ea30SMatthew Wilcox 			xa_store_order(xa, 0, j, xa_mk_value(j), GFP_KERNEL);
40058d6ea30SMatthew Wilcox 
40158d6ea30SMatthew Wilcox 			for (k = 0; k < max_order; k++) {
40258d6ea30SMatthew Wilcox 				void *entry = xa_load(xa, (1UL << k) - 1);
40358d6ea30SMatthew Wilcox 				if ((i < k) && (j < k))
40458d6ea30SMatthew Wilcox 					XA_BUG_ON(xa, entry != NULL);
40558d6ea30SMatthew Wilcox 				else
40658d6ea30SMatthew Wilcox 					XA_BUG_ON(xa, entry != xa_mk_value(j));
40758d6ea30SMatthew Wilcox 			}
40858d6ea30SMatthew Wilcox 
40958d6ea30SMatthew Wilcox 			xa_erase(xa, 0);
41058d6ea30SMatthew Wilcox 			XA_BUG_ON(xa, !xa_empty(xa));
41158d6ea30SMatthew Wilcox 		}
41258d6ea30SMatthew Wilcox 	}
41358d6ea30SMatthew Wilcox #endif
41458d6ea30SMatthew Wilcox }
41558d6ea30SMatthew Wilcox 
416*371c752dSMatthew Wilcox static DEFINE_XARRAY_ALLOC(xa0);
417*371c752dSMatthew Wilcox 
418*371c752dSMatthew Wilcox static noinline void check_xa_alloc(void)
419*371c752dSMatthew Wilcox {
420*371c752dSMatthew Wilcox 	int i;
421*371c752dSMatthew Wilcox 	u32 id;
422*371c752dSMatthew Wilcox 
423*371c752dSMatthew Wilcox 	/* An empty array should assign 0 to the first alloc */
424*371c752dSMatthew Wilcox 	xa_alloc_index(&xa0, 0, GFP_KERNEL);
425*371c752dSMatthew Wilcox 
426*371c752dSMatthew Wilcox 	/* Erasing it should make the array empty again */
427*371c752dSMatthew Wilcox 	xa_erase_index(&xa0, 0);
428*371c752dSMatthew Wilcox 	XA_BUG_ON(&xa0, !xa_empty(&xa0));
429*371c752dSMatthew Wilcox 
430*371c752dSMatthew Wilcox 	/* And it should assign 0 again */
431*371c752dSMatthew Wilcox 	xa_alloc_index(&xa0, 0, GFP_KERNEL);
432*371c752dSMatthew Wilcox 
433*371c752dSMatthew Wilcox 	/* The next assigned ID should be 1 */
434*371c752dSMatthew Wilcox 	xa_alloc_index(&xa0, 1, GFP_KERNEL);
435*371c752dSMatthew Wilcox 	xa_erase_index(&xa0, 1);
436*371c752dSMatthew Wilcox 
437*371c752dSMatthew Wilcox 	/* Storing a value should mark it used */
438*371c752dSMatthew Wilcox 	xa_store_index(&xa0, 1, GFP_KERNEL);
439*371c752dSMatthew Wilcox 	xa_alloc_index(&xa0, 2, GFP_KERNEL);
440*371c752dSMatthew Wilcox 
441*371c752dSMatthew Wilcox 	/* If we then erase 0, it should be free */
442*371c752dSMatthew Wilcox 	xa_erase_index(&xa0, 0);
443*371c752dSMatthew Wilcox 	xa_alloc_index(&xa0, 0, GFP_KERNEL);
444*371c752dSMatthew Wilcox 
445*371c752dSMatthew Wilcox 	xa_erase_index(&xa0, 1);
446*371c752dSMatthew Wilcox 	xa_erase_index(&xa0, 2);
447*371c752dSMatthew Wilcox 
448*371c752dSMatthew Wilcox 	for (i = 1; i < 5000; i++) {
449*371c752dSMatthew Wilcox 		xa_alloc_index(&xa0, i, GFP_KERNEL);
450*371c752dSMatthew Wilcox 	}
451*371c752dSMatthew Wilcox 
452*371c752dSMatthew Wilcox 	xa_destroy(&xa0);
453*371c752dSMatthew Wilcox 
454*371c752dSMatthew Wilcox 	id = 0xfffffffeU;
455*371c752dSMatthew Wilcox 	XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
456*371c752dSMatthew Wilcox 				GFP_KERNEL) != 0);
457*371c752dSMatthew Wilcox 	XA_BUG_ON(&xa0, id != 0xfffffffeU);
458*371c752dSMatthew Wilcox 	XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
459*371c752dSMatthew Wilcox 				GFP_KERNEL) != 0);
460*371c752dSMatthew Wilcox 	XA_BUG_ON(&xa0, id != 0xffffffffU);
461*371c752dSMatthew Wilcox 	XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0),
462*371c752dSMatthew Wilcox 				GFP_KERNEL) != -ENOSPC);
463*371c752dSMatthew Wilcox 	XA_BUG_ON(&xa0, id != 0xffffffffU);
464*371c752dSMatthew Wilcox 	xa_destroy(&xa0);
465*371c752dSMatthew Wilcox }
466*371c752dSMatthew Wilcox 
4674e99d4e9SMatthew Wilcox static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
4684e99d4e9SMatthew Wilcox 			unsigned int order, unsigned int present)
4694e99d4e9SMatthew Wilcox {
4704e99d4e9SMatthew Wilcox 	XA_STATE_ORDER(xas, xa, start, order);
4714e99d4e9SMatthew Wilcox 	void *entry;
4724e99d4e9SMatthew Wilcox 	unsigned int count = 0;
4734e99d4e9SMatthew Wilcox 
4744e99d4e9SMatthew Wilcox retry:
4754e99d4e9SMatthew Wilcox 	xas_lock(&xas);
4764e99d4e9SMatthew Wilcox 	xas_for_each_conflict(&xas, entry) {
4774e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, !xa_is_value(entry));
4784e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, entry < xa_mk_value(start));
4794e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, entry > xa_mk_value(start + (1UL << order) - 1));
4804e99d4e9SMatthew Wilcox 		count++;
4814e99d4e9SMatthew Wilcox 	}
4824e99d4e9SMatthew Wilcox 	xas_store(&xas, xa_mk_value(start));
4834e99d4e9SMatthew Wilcox 	xas_unlock(&xas);
4844e99d4e9SMatthew Wilcox 	if (xas_nomem(&xas, GFP_KERNEL)) {
4854e99d4e9SMatthew Wilcox 		count = 0;
4864e99d4e9SMatthew Wilcox 		goto retry;
4874e99d4e9SMatthew Wilcox 	}
4884e99d4e9SMatthew Wilcox 	XA_BUG_ON(xa, xas_error(&xas));
4894e99d4e9SMatthew Wilcox 	XA_BUG_ON(xa, count != present);
4904e99d4e9SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_value(start));
4914e99d4e9SMatthew Wilcox 	XA_BUG_ON(xa, xa_load(xa, start + (1UL << order) - 1) !=
4924e99d4e9SMatthew Wilcox 			xa_mk_value(start));
4934e99d4e9SMatthew Wilcox 	xa_erase_index(xa, start);
4944e99d4e9SMatthew Wilcox }
4954e99d4e9SMatthew Wilcox 
4964e99d4e9SMatthew Wilcox static noinline void check_store_iter(struct xarray *xa)
4974e99d4e9SMatthew Wilcox {
4984e99d4e9SMatthew Wilcox 	unsigned int i, j;
4994e99d4e9SMatthew Wilcox 	unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 20 : 1;
5004e99d4e9SMatthew Wilcox 
5014e99d4e9SMatthew Wilcox 	for (i = 0; i < max_order; i++) {
5024e99d4e9SMatthew Wilcox 		unsigned int min = 1 << i;
5034e99d4e9SMatthew Wilcox 		unsigned int max = (2 << i) - 1;
5044e99d4e9SMatthew Wilcox 		__check_store_iter(xa, 0, i, 0);
5054e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
5064e99d4e9SMatthew Wilcox 		__check_store_iter(xa, min, i, 0);
5074e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
5084e99d4e9SMatthew Wilcox 
5094e99d4e9SMatthew Wilcox 		xa_store_index(xa, min, GFP_KERNEL);
5104e99d4e9SMatthew Wilcox 		__check_store_iter(xa, min, i, 1);
5114e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
5124e99d4e9SMatthew Wilcox 		xa_store_index(xa, max, GFP_KERNEL);
5134e99d4e9SMatthew Wilcox 		__check_store_iter(xa, min, i, 1);
5144e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
5154e99d4e9SMatthew Wilcox 
5164e99d4e9SMatthew Wilcox 		for (j = 0; j < min; j++)
5174e99d4e9SMatthew Wilcox 			xa_store_index(xa, j, GFP_KERNEL);
5184e99d4e9SMatthew Wilcox 		__check_store_iter(xa, 0, i, min);
5194e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
5204e99d4e9SMatthew Wilcox 		for (j = 0; j < min; j++)
5214e99d4e9SMatthew Wilcox 			xa_store_index(xa, min + j, GFP_KERNEL);
5224e99d4e9SMatthew Wilcox 		__check_store_iter(xa, min, i, min);
5234e99d4e9SMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
5244e99d4e9SMatthew Wilcox 	}
5254e99d4e9SMatthew Wilcox #ifdef CONFIG_XARRAY_MULTI
5264e99d4e9SMatthew Wilcox 	xa_store_index(xa, 63, GFP_KERNEL);
5274e99d4e9SMatthew Wilcox 	xa_store_index(xa, 65, GFP_KERNEL);
5284e99d4e9SMatthew Wilcox 	__check_store_iter(xa, 64, 2, 1);
5294e99d4e9SMatthew Wilcox 	xa_erase_index(xa, 63);
5304e99d4e9SMatthew Wilcox #endif
5314e99d4e9SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
5324e99d4e9SMatthew Wilcox }
5334e99d4e9SMatthew Wilcox 
534b803b428SMatthew Wilcox static noinline void check_multi_find(struct xarray *xa)
535b803b428SMatthew Wilcox {
536b803b428SMatthew Wilcox #ifdef CONFIG_XARRAY_MULTI
537b803b428SMatthew Wilcox 	unsigned long index;
538b803b428SMatthew Wilcox 
539b803b428SMatthew Wilcox 	xa_store_order(xa, 12, 2, xa_mk_value(12), GFP_KERNEL);
540b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xa_store_index(xa, 16, GFP_KERNEL) != NULL);
541b803b428SMatthew Wilcox 
542b803b428SMatthew Wilcox 	index = 0;
543b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
544b803b428SMatthew Wilcox 			xa_mk_value(12));
545b803b428SMatthew Wilcox 	XA_BUG_ON(xa, index != 12);
546b803b428SMatthew Wilcox 	index = 13;
547b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
548b803b428SMatthew Wilcox 			xa_mk_value(12));
549b803b428SMatthew Wilcox 	XA_BUG_ON(xa, (index < 12) || (index >= 16));
550b803b428SMatthew Wilcox 	XA_BUG_ON(xa, xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT) !=
551b803b428SMatthew Wilcox 			xa_mk_value(16));
552b803b428SMatthew Wilcox 	XA_BUG_ON(xa, index != 16);
553b803b428SMatthew Wilcox 
554b803b428SMatthew Wilcox 	xa_erase_index(xa, 12);
555b803b428SMatthew Wilcox 	xa_erase_index(xa, 16);
556b803b428SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
557b803b428SMatthew Wilcox #endif
558b803b428SMatthew Wilcox }
559b803b428SMatthew Wilcox 
560b803b428SMatthew Wilcox static noinline void check_multi_find_2(struct xarray *xa)
561b803b428SMatthew Wilcox {
562b803b428SMatthew Wilcox 	unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 10 : 1;
563b803b428SMatthew Wilcox 	unsigned int i, j;
564b803b428SMatthew Wilcox 	void *entry;
565b803b428SMatthew Wilcox 
566b803b428SMatthew Wilcox 	for (i = 0; i < max_order; i++) {
567b803b428SMatthew Wilcox 		unsigned long index = 1UL << i;
568b803b428SMatthew Wilcox 		for (j = 0; j < index; j++) {
569b803b428SMatthew Wilcox 			XA_STATE(xas, xa, j + index);
570b803b428SMatthew Wilcox 			xa_store_index(xa, index - 1, GFP_KERNEL);
571b803b428SMatthew Wilcox 			xa_store_order(xa, index, i, xa_mk_value(index),
572b803b428SMatthew Wilcox 					GFP_KERNEL);
573b803b428SMatthew Wilcox 			rcu_read_lock();
574b803b428SMatthew Wilcox 			xas_for_each(&xas, entry, ULONG_MAX) {
575b803b428SMatthew Wilcox 				xa_erase_index(xa, index);
576b803b428SMatthew Wilcox 			}
577b803b428SMatthew Wilcox 			rcu_read_unlock();
578b803b428SMatthew Wilcox 			xa_erase_index(xa, index - 1);
579b803b428SMatthew Wilcox 			XA_BUG_ON(xa, !xa_empty(xa));
580b803b428SMatthew Wilcox 		}
581b803b428SMatthew Wilcox 	}
582b803b428SMatthew Wilcox }
583b803b428SMatthew Wilcox 
584b803b428SMatthew Wilcox static noinline void check_find(struct xarray *xa)
585b803b428SMatthew Wilcox {
586b803b428SMatthew Wilcox 	unsigned long i, j, k;
587b803b428SMatthew Wilcox 
588b803b428SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
589b803b428SMatthew Wilcox 
590b803b428SMatthew Wilcox 	/*
591b803b428SMatthew Wilcox 	 * Check xa_find with all pairs between 0 and 99 inclusive,
592b803b428SMatthew Wilcox 	 * starting at every index between 0 and 99
593b803b428SMatthew Wilcox 	 */
594b803b428SMatthew Wilcox 	for (i = 0; i < 100; i++) {
595b803b428SMatthew Wilcox 		XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
596b803b428SMatthew Wilcox 		xa_set_mark(xa, i, XA_MARK_0);
597b803b428SMatthew Wilcox 		for (j = 0; j < i; j++) {
598b803b428SMatthew Wilcox 			XA_BUG_ON(xa, xa_store_index(xa, j, GFP_KERNEL) !=
599b803b428SMatthew Wilcox 					NULL);
600b803b428SMatthew Wilcox 			xa_set_mark(xa, j, XA_MARK_0);
601b803b428SMatthew Wilcox 			for (k = 0; k < 100; k++) {
602b803b428SMatthew Wilcox 				unsigned long index = k;
603b803b428SMatthew Wilcox 				void *entry = xa_find(xa, &index, ULONG_MAX,
604b803b428SMatthew Wilcox 								XA_PRESENT);
605b803b428SMatthew Wilcox 				if (k <= j)
606b803b428SMatthew Wilcox 					XA_BUG_ON(xa, index != j);
607b803b428SMatthew Wilcox 				else if (k <= i)
608b803b428SMatthew Wilcox 					XA_BUG_ON(xa, index != i);
609b803b428SMatthew Wilcox 				else
610b803b428SMatthew Wilcox 					XA_BUG_ON(xa, entry != NULL);
611b803b428SMatthew Wilcox 
612b803b428SMatthew Wilcox 				index = k;
613b803b428SMatthew Wilcox 				entry = xa_find(xa, &index, ULONG_MAX,
614b803b428SMatthew Wilcox 								XA_MARK_0);
615b803b428SMatthew Wilcox 				if (k <= j)
616b803b428SMatthew Wilcox 					XA_BUG_ON(xa, index != j);
617b803b428SMatthew Wilcox 				else if (k <= i)
618b803b428SMatthew Wilcox 					XA_BUG_ON(xa, index != i);
619b803b428SMatthew Wilcox 				else
620b803b428SMatthew Wilcox 					XA_BUG_ON(xa, entry != NULL);
621b803b428SMatthew Wilcox 			}
622b803b428SMatthew Wilcox 			xa_erase_index(xa, j);
623b803b428SMatthew Wilcox 			XA_BUG_ON(xa, xa_get_mark(xa, j, XA_MARK_0));
624b803b428SMatthew Wilcox 			XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
625b803b428SMatthew Wilcox 		}
626b803b428SMatthew Wilcox 		xa_erase_index(xa, i);
627b803b428SMatthew Wilcox 		XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_0));
628b803b428SMatthew Wilcox 	}
629b803b428SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
630b803b428SMatthew Wilcox 	check_multi_find(xa);
631b803b428SMatthew Wilcox 	check_multi_find_2(xa);
632b803b428SMatthew Wilcox }
633b803b428SMatthew Wilcox 
63464d3e9a9SMatthew Wilcox static noinline void check_move_small(struct xarray *xa, unsigned long idx)
63564d3e9a9SMatthew Wilcox {
63664d3e9a9SMatthew Wilcox 	XA_STATE(xas, xa, 0);
63764d3e9a9SMatthew Wilcox 	unsigned long i;
63864d3e9a9SMatthew Wilcox 
63964d3e9a9SMatthew Wilcox 	xa_store_index(xa, 0, GFP_KERNEL);
64064d3e9a9SMatthew Wilcox 	xa_store_index(xa, idx, GFP_KERNEL);
64164d3e9a9SMatthew Wilcox 
64264d3e9a9SMatthew Wilcox 	rcu_read_lock();
64364d3e9a9SMatthew Wilcox 	for (i = 0; i < idx * 4; i++) {
64464d3e9a9SMatthew Wilcox 		void *entry = xas_next(&xas);
64564d3e9a9SMatthew Wilcox 		if (i <= idx)
64664d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
64764d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, xas.xa_index != i);
64864d3e9a9SMatthew Wilcox 		if (i == 0 || i == idx)
64964d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != xa_mk_value(i));
65064d3e9a9SMatthew Wilcox 		else
65164d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != NULL);
65264d3e9a9SMatthew Wilcox 	}
65364d3e9a9SMatthew Wilcox 	xas_next(&xas);
65464d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_index != i);
65564d3e9a9SMatthew Wilcox 
65664d3e9a9SMatthew Wilcox 	do {
65764d3e9a9SMatthew Wilcox 		void *entry = xas_prev(&xas);
65864d3e9a9SMatthew Wilcox 		i--;
65964d3e9a9SMatthew Wilcox 		if (i <= idx)
66064d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
66164d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, xas.xa_index != i);
66264d3e9a9SMatthew Wilcox 		if (i == 0 || i == idx)
66364d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != xa_mk_value(i));
66464d3e9a9SMatthew Wilcox 		else
66564d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != NULL);
66664d3e9a9SMatthew Wilcox 	} while (i > 0);
66764d3e9a9SMatthew Wilcox 
66864d3e9a9SMatthew Wilcox 	xas_set(&xas, ULONG_MAX);
66964d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas_next(&xas) != NULL);
67064d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
67164d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas_next(&xas) != xa_mk_value(0));
67264d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_index != 0);
67364d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas_prev(&xas) != NULL);
67464d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
67564d3e9a9SMatthew Wilcox 	rcu_read_unlock();
67664d3e9a9SMatthew Wilcox 
67764d3e9a9SMatthew Wilcox 	xa_erase_index(xa, 0);
67864d3e9a9SMatthew Wilcox 	xa_erase_index(xa, idx);
67964d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
68064d3e9a9SMatthew Wilcox }
68164d3e9a9SMatthew Wilcox 
68264d3e9a9SMatthew Wilcox static noinline void check_move(struct xarray *xa)
68364d3e9a9SMatthew Wilcox {
68464d3e9a9SMatthew Wilcox 	XA_STATE(xas, xa, (1 << 16) - 1);
68564d3e9a9SMatthew Wilcox 	unsigned long i;
68664d3e9a9SMatthew Wilcox 
68764d3e9a9SMatthew Wilcox 	for (i = 0; i < (1 << 16); i++)
68864d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
68964d3e9a9SMatthew Wilcox 
69064d3e9a9SMatthew Wilcox 	rcu_read_lock();
69164d3e9a9SMatthew Wilcox 	do {
69264d3e9a9SMatthew Wilcox 		void *entry = xas_prev(&xas);
69364d3e9a9SMatthew Wilcox 		i--;
69464d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, entry != xa_mk_value(i));
69564d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, i != xas.xa_index);
69664d3e9a9SMatthew Wilcox 	} while (i != 0);
69764d3e9a9SMatthew Wilcox 
69864d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas_prev(&xas) != NULL);
69964d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
70064d3e9a9SMatthew Wilcox 
70164d3e9a9SMatthew Wilcox 	do {
70264d3e9a9SMatthew Wilcox 		void *entry = xas_next(&xas);
70364d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, entry != xa_mk_value(i));
70464d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, i != xas.xa_index);
70564d3e9a9SMatthew Wilcox 		i++;
70664d3e9a9SMatthew Wilcox 	} while (i < (1 << 16));
70764d3e9a9SMatthew Wilcox 	rcu_read_unlock();
70864d3e9a9SMatthew Wilcox 
70964d3e9a9SMatthew Wilcox 	for (i = (1 << 8); i < (1 << 15); i++)
71064d3e9a9SMatthew Wilcox 		xa_erase_index(xa, i);
71164d3e9a9SMatthew Wilcox 
71264d3e9a9SMatthew Wilcox 	i = xas.xa_index;
71364d3e9a9SMatthew Wilcox 
71464d3e9a9SMatthew Wilcox 	rcu_read_lock();
71564d3e9a9SMatthew Wilcox 	do {
71664d3e9a9SMatthew Wilcox 		void *entry = xas_prev(&xas);
71764d3e9a9SMatthew Wilcox 		i--;
71864d3e9a9SMatthew Wilcox 		if ((i < (1 << 8)) || (i >= (1 << 15)))
71964d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != xa_mk_value(i));
72064d3e9a9SMatthew Wilcox 		else
72164d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != NULL);
72264d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, i != xas.xa_index);
72364d3e9a9SMatthew Wilcox 	} while (i != 0);
72464d3e9a9SMatthew Wilcox 
72564d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas_prev(&xas) != NULL);
72664d3e9a9SMatthew Wilcox 	XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
72764d3e9a9SMatthew Wilcox 
72864d3e9a9SMatthew Wilcox 	do {
72964d3e9a9SMatthew Wilcox 		void *entry = xas_next(&xas);
73064d3e9a9SMatthew Wilcox 		if ((i < (1 << 8)) || (i >= (1 << 15)))
73164d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != xa_mk_value(i));
73264d3e9a9SMatthew Wilcox 		else
73364d3e9a9SMatthew Wilcox 			XA_BUG_ON(xa, entry != NULL);
73464d3e9a9SMatthew Wilcox 		XA_BUG_ON(xa, i != xas.xa_index);
73564d3e9a9SMatthew Wilcox 		i++;
73664d3e9a9SMatthew Wilcox 	} while (i < (1 << 16));
73764d3e9a9SMatthew Wilcox 	rcu_read_unlock();
73864d3e9a9SMatthew Wilcox 
73964d3e9a9SMatthew Wilcox 	xa_destroy(xa);
74064d3e9a9SMatthew Wilcox 
74164d3e9a9SMatthew Wilcox 	for (i = 0; i < 16; i++)
74264d3e9a9SMatthew Wilcox 		check_move_small(xa, 1UL << i);
74364d3e9a9SMatthew Wilcox 
74464d3e9a9SMatthew Wilcox 	for (i = 2; i < 16; i++)
74564d3e9a9SMatthew Wilcox 		check_move_small(xa, (1UL << i) - 1);
74664d3e9a9SMatthew Wilcox }
74764d3e9a9SMatthew Wilcox 
7482264f513SMatthew Wilcox static noinline void xa_store_many_order(struct xarray *xa,
7492264f513SMatthew Wilcox 		unsigned long index, unsigned order)
7502264f513SMatthew Wilcox {
7512264f513SMatthew Wilcox 	XA_STATE_ORDER(xas, xa, index, order);
7522264f513SMatthew Wilcox 	unsigned int i = 0;
7532264f513SMatthew Wilcox 
7542264f513SMatthew Wilcox 	do {
7552264f513SMatthew Wilcox 		xas_lock(&xas);
7562264f513SMatthew Wilcox 		XA_BUG_ON(xa, xas_find_conflict(&xas));
7572264f513SMatthew Wilcox 		xas_create_range(&xas);
7582264f513SMatthew Wilcox 		if (xas_error(&xas))
7592264f513SMatthew Wilcox 			goto unlock;
7602264f513SMatthew Wilcox 		for (i = 0; i < (1U << order); i++) {
7612264f513SMatthew Wilcox 			XA_BUG_ON(xa, xas_store(&xas, xa_mk_value(index + i)));
7622264f513SMatthew Wilcox 			xas_next(&xas);
7632264f513SMatthew Wilcox 		}
7642264f513SMatthew Wilcox unlock:
7652264f513SMatthew Wilcox 		xas_unlock(&xas);
7662264f513SMatthew Wilcox 	} while (xas_nomem(&xas, GFP_KERNEL));
7672264f513SMatthew Wilcox 
7682264f513SMatthew Wilcox 	XA_BUG_ON(xa, xas_error(&xas));
7692264f513SMatthew Wilcox }
7702264f513SMatthew Wilcox 
7712264f513SMatthew Wilcox static noinline void check_create_range_1(struct xarray *xa,
7722264f513SMatthew Wilcox 		unsigned long index, unsigned order)
7732264f513SMatthew Wilcox {
7742264f513SMatthew Wilcox 	unsigned long i;
7752264f513SMatthew Wilcox 
7762264f513SMatthew Wilcox 	xa_store_many_order(xa, index, order);
7772264f513SMatthew Wilcox 	for (i = index; i < index + (1UL << order); i++)
7782264f513SMatthew Wilcox 		xa_erase_index(xa, i);
7792264f513SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
7802264f513SMatthew Wilcox }
7812264f513SMatthew Wilcox 
7822264f513SMatthew Wilcox static noinline void check_create_range_2(struct xarray *xa, unsigned order)
7832264f513SMatthew Wilcox {
7842264f513SMatthew Wilcox 	unsigned long i;
7852264f513SMatthew Wilcox 	unsigned long nr = 1UL << order;
7862264f513SMatthew Wilcox 
7872264f513SMatthew Wilcox 	for (i = 0; i < nr * nr; i += nr)
7882264f513SMatthew Wilcox 		xa_store_many_order(xa, i, order);
7892264f513SMatthew Wilcox 	for (i = 0; i < nr * nr; i++)
7902264f513SMatthew Wilcox 		xa_erase_index(xa, i);
7912264f513SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
7922264f513SMatthew Wilcox }
7932264f513SMatthew Wilcox 
7942264f513SMatthew Wilcox static noinline void check_create_range_3(void)
7952264f513SMatthew Wilcox {
7962264f513SMatthew Wilcox 	XA_STATE(xas, NULL, 0);
7972264f513SMatthew Wilcox 	xas_set_err(&xas, -EEXIST);
7982264f513SMatthew Wilcox 	xas_create_range(&xas);
7992264f513SMatthew Wilcox 	XA_BUG_ON(NULL, xas_error(&xas) != -EEXIST);
8002264f513SMatthew Wilcox }
8012264f513SMatthew Wilcox 
8022264f513SMatthew Wilcox static noinline void check_create_range_4(struct xarray *xa,
8032264f513SMatthew Wilcox 		unsigned long index, unsigned order)
8042264f513SMatthew Wilcox {
8052264f513SMatthew Wilcox 	XA_STATE_ORDER(xas, xa, index, order);
8062264f513SMatthew Wilcox 	unsigned long base = xas.xa_index;
8072264f513SMatthew Wilcox 	unsigned long i = 0;
8082264f513SMatthew Wilcox 
8092264f513SMatthew Wilcox 	xa_store_index(xa, index, GFP_KERNEL);
8102264f513SMatthew Wilcox 	do {
8112264f513SMatthew Wilcox 		xas_lock(&xas);
8122264f513SMatthew Wilcox 		xas_create_range(&xas);
8132264f513SMatthew Wilcox 		if (xas_error(&xas))
8142264f513SMatthew Wilcox 			goto unlock;
8152264f513SMatthew Wilcox 		for (i = 0; i < (1UL << order); i++) {
8162264f513SMatthew Wilcox 			void *old = xas_store(&xas, xa_mk_value(base + i));
8172264f513SMatthew Wilcox 			if (xas.xa_index == index)
8182264f513SMatthew Wilcox 				XA_BUG_ON(xa, old != xa_mk_value(base + i));
8192264f513SMatthew Wilcox 			else
8202264f513SMatthew Wilcox 				XA_BUG_ON(xa, old != NULL);
8212264f513SMatthew Wilcox 			xas_next(&xas);
8222264f513SMatthew Wilcox 		}
8232264f513SMatthew Wilcox unlock:
8242264f513SMatthew Wilcox 		xas_unlock(&xas);
8252264f513SMatthew Wilcox 	} while (xas_nomem(&xas, GFP_KERNEL));
8262264f513SMatthew Wilcox 
8272264f513SMatthew Wilcox 	XA_BUG_ON(xa, xas_error(&xas));
8282264f513SMatthew Wilcox 
8292264f513SMatthew Wilcox 	for (i = base; i < base + (1UL << order); i++)
8302264f513SMatthew Wilcox 		xa_erase_index(xa, i);
8312264f513SMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
8322264f513SMatthew Wilcox }
8332264f513SMatthew Wilcox 
8342264f513SMatthew Wilcox static noinline void check_create_range(struct xarray *xa)
8352264f513SMatthew Wilcox {
8362264f513SMatthew Wilcox 	unsigned int order;
8372264f513SMatthew Wilcox 	unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 12 : 1;
8382264f513SMatthew Wilcox 
8392264f513SMatthew Wilcox 	for (order = 0; order < max_order; order++) {
8402264f513SMatthew Wilcox 		check_create_range_1(xa, 0, order);
8412264f513SMatthew Wilcox 		check_create_range_1(xa, 1U << order, order);
8422264f513SMatthew Wilcox 		check_create_range_1(xa, 2U << order, order);
8432264f513SMatthew Wilcox 		check_create_range_1(xa, 3U << order, order);
8442264f513SMatthew Wilcox 		check_create_range_1(xa, 1U << 24, order);
8452264f513SMatthew Wilcox 		if (order < 10)
8462264f513SMatthew Wilcox 			check_create_range_2(xa, order);
8472264f513SMatthew Wilcox 
8482264f513SMatthew Wilcox 		check_create_range_4(xa, 0, order);
8492264f513SMatthew Wilcox 		check_create_range_4(xa, 1U << order, order);
8502264f513SMatthew Wilcox 		check_create_range_4(xa, 2U << order, order);
8512264f513SMatthew Wilcox 		check_create_range_4(xa, 3U << order, order);
8522264f513SMatthew Wilcox 		check_create_range_4(xa, 1U << 24, order);
8532264f513SMatthew Wilcox 
8542264f513SMatthew Wilcox 		check_create_range_4(xa, 1, order);
8552264f513SMatthew Wilcox 		check_create_range_4(xa, (1U << order) + 1, order);
8562264f513SMatthew Wilcox 		check_create_range_4(xa, (2U << order) + 1, order);
8572264f513SMatthew Wilcox 		check_create_range_4(xa, (2U << order) - 1, order);
8582264f513SMatthew Wilcox 		check_create_range_4(xa, (3U << order) + 1, order);
8592264f513SMatthew Wilcox 		check_create_range_4(xa, (3U << order) - 1, order);
8602264f513SMatthew Wilcox 		check_create_range_4(xa, (1U << 24) + 1, order);
8612264f513SMatthew Wilcox 	}
8622264f513SMatthew Wilcox 
8632264f513SMatthew Wilcox 	check_create_range_3();
8642264f513SMatthew Wilcox }
8652264f513SMatthew Wilcox 
866687149fcSMatthew Wilcox static noinline void check_destroy(struct xarray *xa)
867687149fcSMatthew Wilcox {
868687149fcSMatthew Wilcox 	unsigned long index;
869687149fcSMatthew Wilcox 
870687149fcSMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
871687149fcSMatthew Wilcox 
872687149fcSMatthew Wilcox 	/* Destroying an empty array is a no-op */
873687149fcSMatthew Wilcox 	xa_destroy(xa);
874687149fcSMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
875687149fcSMatthew Wilcox 
876687149fcSMatthew Wilcox 	/* Destroying an array with a single entry */
877687149fcSMatthew Wilcox 	for (index = 0; index < 1000; index++) {
878687149fcSMatthew Wilcox 		xa_store_index(xa, index, GFP_KERNEL);
879687149fcSMatthew Wilcox 		XA_BUG_ON(xa, xa_empty(xa));
880687149fcSMatthew Wilcox 		xa_destroy(xa);
881687149fcSMatthew Wilcox 		XA_BUG_ON(xa, !xa_empty(xa));
882687149fcSMatthew Wilcox 	}
883687149fcSMatthew Wilcox 
884687149fcSMatthew Wilcox 	/* Destroying an array with a single entry at ULONG_MAX */
885687149fcSMatthew Wilcox 	xa_store(xa, ULONG_MAX, xa, GFP_KERNEL);
886687149fcSMatthew Wilcox 	XA_BUG_ON(xa, xa_empty(xa));
887687149fcSMatthew Wilcox 	xa_destroy(xa);
888687149fcSMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
889687149fcSMatthew Wilcox 
890687149fcSMatthew Wilcox #ifdef CONFIG_XARRAY_MULTI
891687149fcSMatthew Wilcox 	/* Destroying an array with a multi-index entry */
892687149fcSMatthew Wilcox 	xa_store_order(xa, 1 << 11, 11, xa, GFP_KERNEL);
893687149fcSMatthew Wilcox 	XA_BUG_ON(xa, xa_empty(xa));
894687149fcSMatthew Wilcox 	xa_destroy(xa);
895687149fcSMatthew Wilcox 	XA_BUG_ON(xa, !xa_empty(xa));
896687149fcSMatthew Wilcox #endif
897687149fcSMatthew Wilcox }
898687149fcSMatthew Wilcox 
89958d6ea30SMatthew Wilcox static DEFINE_XARRAY(array);
900ad3d6c72SMatthew Wilcox 
901ad3d6c72SMatthew Wilcox static int xarray_checks(void)
902ad3d6c72SMatthew Wilcox {
90358d6ea30SMatthew Wilcox 	check_xa_err(&array);
904b803b428SMatthew Wilcox 	check_xas_retry(&array);
905ad3d6c72SMatthew Wilcox 	check_xa_load(&array);
9069b89a035SMatthew Wilcox 	check_xa_mark(&array);
90758d6ea30SMatthew Wilcox 	check_xa_shrink(&array);
908b803b428SMatthew Wilcox 	check_xas_erase(&array);
90941aec91fSMatthew Wilcox 	check_cmpxchg(&array);
9109f14d4f1SMatthew Wilcox 	check_reserve(&array);
91158d6ea30SMatthew Wilcox 	check_multi_store(&array);
912*371c752dSMatthew Wilcox 	check_xa_alloc();
913b803b428SMatthew Wilcox 	check_find(&array);
914687149fcSMatthew Wilcox 	check_destroy(&array);
91564d3e9a9SMatthew Wilcox 	check_move(&array);
9162264f513SMatthew Wilcox 	check_create_range(&array);
9174e99d4e9SMatthew Wilcox 	check_store_iter(&array);
918ad3d6c72SMatthew Wilcox 
919ad3d6c72SMatthew Wilcox 	printk("XArray: %u of %u tests passed\n", tests_passed, tests_run);
920ad3d6c72SMatthew Wilcox 	return (tests_run == tests_passed) ? 0 : -EINVAL;
921ad3d6c72SMatthew Wilcox }
922ad3d6c72SMatthew Wilcox 
923ad3d6c72SMatthew Wilcox static void xarray_exit(void)
924ad3d6c72SMatthew Wilcox {
925ad3d6c72SMatthew Wilcox }
926ad3d6c72SMatthew Wilcox 
927ad3d6c72SMatthew Wilcox module_init(xarray_checks);
928ad3d6c72SMatthew Wilcox module_exit(xarray_exit);
929ad3d6c72SMatthew Wilcox MODULE_AUTHOR("Matthew Wilcox <[email protected]>");
930ad3d6c72SMatthew Wilcox MODULE_LICENSE("GPL");
931