test_xarray.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  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. #include <linux/xarray.h>
  8. #include <linux/module.h>
  9. static unsigned int tests_run;
  10. static unsigned int tests_passed;
  11. #ifndef XA_DEBUG
  12. # ifdef __KERNEL__
  13. void xa_dump(const struct xarray *xa) { }
  14. # endif
  15. #undef XA_BUG_ON
  16. #define XA_BUG_ON(xa, x) do { \
  17. tests_run++; \
  18. if (x) { \
  19. printk("BUG at %s:%d\n", __func__, __LINE__); \
  20. xa_dump(xa); \
  21. dump_stack(); \
  22. } else { \
  23. tests_passed++; \
  24. } \
  25. } while (0)
  26. #endif
  27. static void *xa_store_index(struct xarray *xa, unsigned long index, gfp_t gfp)
  28. {
  29. return xa_store(xa, index, xa_mk_value(index & LONG_MAX), gfp);
  30. }
  31. static void xa_erase_index(struct xarray *xa, unsigned long index)
  32. {
  33. XA_BUG_ON(xa, xa_erase(xa, index) != xa_mk_value(index & LONG_MAX));
  34. XA_BUG_ON(xa, xa_load(xa, index) != NULL);
  35. }
  36. /*
  37. * If anyone needs this, please move it to xarray.c. We have no current
  38. * users outside the test suite because all current multislot users want
  39. * to use the advanced API.
  40. */
  41. static void *xa_store_order(struct xarray *xa, unsigned long index,
  42. unsigned order, void *entry, gfp_t gfp)
  43. {
  44. XA_STATE_ORDER(xas, xa, index, order);
  45. void *curr;
  46. do {
  47. xas_lock(&xas);
  48. curr = xas_store(&xas, entry);
  49. xas_unlock(&xas);
  50. } while (xas_nomem(&xas, gfp));
  51. return curr;
  52. }
  53. static noinline void check_xa_err(struct xarray *xa)
  54. {
  55. XA_BUG_ON(xa, xa_err(xa_store_index(xa, 0, GFP_NOWAIT)) != 0);
  56. XA_BUG_ON(xa, xa_err(xa_erase(xa, 0)) != 0);
  57. #ifndef __KERNEL__
  58. /* The kernel does not fail GFP_NOWAIT allocations */
  59. XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_NOWAIT)) != -ENOMEM);
  60. XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_NOWAIT)) != -ENOMEM);
  61. #endif
  62. XA_BUG_ON(xa, xa_err(xa_store_index(xa, 1, GFP_KERNEL)) != 0);
  63. XA_BUG_ON(xa, xa_err(xa_store(xa, 1, xa_mk_value(0), GFP_KERNEL)) != 0);
  64. XA_BUG_ON(xa, xa_err(xa_erase(xa, 1)) != 0);
  65. // kills the test-suite :-(
  66. // XA_BUG_ON(xa, xa_err(xa_store(xa, 0, xa_mk_internal(0), 0)) != -EINVAL);
  67. }
  68. static noinline void check_xas_retry(struct xarray *xa)
  69. {
  70. XA_STATE(xas, xa, 0);
  71. void *entry;
  72. xa_store_index(xa, 0, GFP_KERNEL);
  73. xa_store_index(xa, 1, GFP_KERNEL);
  74. rcu_read_lock();
  75. XA_BUG_ON(xa, xas_find(&xas, ULONG_MAX) != xa_mk_value(0));
  76. xa_erase_index(xa, 1);
  77. XA_BUG_ON(xa, !xa_is_retry(xas_reload(&xas)));
  78. XA_BUG_ON(xa, xas_retry(&xas, NULL));
  79. XA_BUG_ON(xa, xas_retry(&xas, xa_mk_value(0)));
  80. xas_reset(&xas);
  81. XA_BUG_ON(xa, xas.xa_node != XAS_RESTART);
  82. XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
  83. XA_BUG_ON(xa, xas.xa_node != NULL);
  84. XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL);
  85. XA_BUG_ON(xa, !xa_is_internal(xas_reload(&xas)));
  86. xas.xa_node = XAS_RESTART;
  87. XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0));
  88. rcu_read_unlock();
  89. /* Make sure we can iterate through retry entries */
  90. xas_lock(&xas);
  91. xas_set(&xas, 0);
  92. xas_store(&xas, XA_RETRY_ENTRY);
  93. xas_set(&xas, 1);
  94. xas_store(&xas, XA_RETRY_ENTRY);
  95. xas_set(&xas, 0);
  96. xas_for_each(&xas, entry, ULONG_MAX) {
  97. xas_store(&xas, xa_mk_value(xas.xa_index));
  98. }
  99. xas_unlock(&xas);
  100. xa_erase_index(xa, 0);
  101. xa_erase_index(xa, 1);
  102. }
  103. static noinline void check_xa_load(struct xarray *xa)
  104. {
  105. unsigned long i, j;
  106. for (i = 0; i < 1024; i++) {
  107. for (j = 0; j < 1024; j++) {
  108. void *entry = xa_load(xa, j);
  109. if (j < i)
  110. XA_BUG_ON(xa, xa_to_value(entry) != j);
  111. else
  112. XA_BUG_ON(xa, entry);
  113. }
  114. XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
  115. }
  116. for (i = 0; i < 1024; i++) {
  117. for (j = 0; j < 1024; j++) {
  118. void *entry = xa_load(xa, j);
  119. if (j >= i)
  120. XA_BUG_ON(xa, xa_to_value(entry) != j);
  121. else
  122. XA_BUG_ON(xa, entry);
  123. }
  124. xa_erase_index(xa, i);
  125. }
  126. XA_BUG_ON(xa, !xa_empty(xa));
  127. }
  128. static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
  129. {
  130. unsigned int order;
  131. unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 8 : 1;
  132. /* NULL elements have no marks set */
  133. XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
  134. xa_set_mark(xa, index, XA_MARK_0);
  135. XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
  136. /* Storing a pointer will not make a mark appear */
  137. XA_BUG_ON(xa, xa_store_index(xa, index, GFP_KERNEL) != NULL);
  138. XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
  139. xa_set_mark(xa, index, XA_MARK_0);
  140. XA_BUG_ON(xa, !xa_get_mark(xa, index, XA_MARK_0));
  141. /* Setting one mark will not set another mark */
  142. XA_BUG_ON(xa, xa_get_mark(xa, index + 1, XA_MARK_0));
  143. XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_1));
  144. /* Storing NULL clears marks, and they can't be set again */
  145. xa_erase_index(xa, index);
  146. XA_BUG_ON(xa, !xa_empty(xa));
  147. XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
  148. xa_set_mark(xa, index, XA_MARK_0);
  149. XA_BUG_ON(xa, xa_get_mark(xa, index, XA_MARK_0));
  150. /*
  151. * Storing a multi-index entry over entries with marks gives the
  152. * entire entry the union of the marks
  153. */
  154. BUG_ON((index % 4) != 0);
  155. for (order = 2; order < max_order; order++) {
  156. unsigned long base = round_down(index, 1UL << order);
  157. unsigned long next = base + (1UL << order);
  158. unsigned long i;
  159. XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL));
  160. xa_set_mark(xa, index + 1, XA_MARK_0);
  161. XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL));
  162. xa_set_mark(xa, index + 2, XA_MARK_1);
  163. XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL));
  164. xa_store_order(xa, index, order, xa_mk_value(index),
  165. GFP_KERNEL);
  166. for (i = base; i < next; i++) {
  167. XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
  168. XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1));
  169. XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2));
  170. }
  171. XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_0));
  172. XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_1));
  173. XA_BUG_ON(xa, xa_get_mark(xa, next, XA_MARK_2));
  174. xa_erase_index(xa, index);
  175. xa_erase_index(xa, next);
  176. XA_BUG_ON(xa, !xa_empty(xa));
  177. }
  178. XA_BUG_ON(xa, !xa_empty(xa));
  179. }
  180. static noinline void check_xa_mark(struct xarray *xa)
  181. {
  182. unsigned long index;
  183. for (index = 0; index < 16384; index += 4)
  184. check_xa_mark_1(xa, index);
  185. }
  186. static noinline void check_xa_shrink(struct xarray *xa)
  187. {
  188. XA_STATE(xas, xa, 1);
  189. struct xa_node *node;
  190. XA_BUG_ON(xa, !xa_empty(xa));
  191. XA_BUG_ON(xa, xa_store_index(xa, 0, GFP_KERNEL) != NULL);
  192. XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL);
  193. /*
  194. * Check that erasing the entry at 1 shrinks the tree and properly
  195. * marks the node as being deleted.
  196. */
  197. xas_lock(&xas);
  198. XA_BUG_ON(xa, xas_load(&xas) != xa_mk_value(1));
  199. node = xas.xa_node;
  200. XA_BUG_ON(xa, xa_entry_locked(xa, node, 0) != xa_mk_value(0));
  201. XA_BUG_ON(xa, xas_store(&xas, NULL) != xa_mk_value(1));
  202. XA_BUG_ON(xa, xa_load(xa, 1) != NULL);
  203. XA_BUG_ON(xa, xas.xa_node != XAS_BOUNDS);
  204. XA_BUG_ON(xa, xa_entry_locked(xa, node, 0) != XA_RETRY_ENTRY);
  205. XA_BUG_ON(xa, xas_load(&xas) != NULL);
  206. xas_unlock(&xas);
  207. XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
  208. xa_erase_index(xa, 0);
  209. XA_BUG_ON(xa, !xa_empty(xa));
  210. }
  211. static noinline void check_cmpxchg(struct xarray *xa)
  212. {
  213. void *FIVE = xa_mk_value(5);
  214. void *SIX = xa_mk_value(6);
  215. void *LOTS = xa_mk_value(12345678);
  216. XA_BUG_ON(xa, !xa_empty(xa));
  217. XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_KERNEL) != NULL);
  218. XA_BUG_ON(xa, xa_insert(xa, 12345678, xa, GFP_KERNEL) != -EEXIST);
  219. XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, SIX, FIVE, GFP_KERNEL) != LOTS);
  220. XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, LOTS, FIVE, GFP_KERNEL) != LOTS);
  221. XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, FIVE, LOTS, GFP_KERNEL) != FIVE);
  222. XA_BUG_ON(xa, xa_cmpxchg(xa, 5, FIVE, NULL, GFP_KERNEL) != NULL);
  223. XA_BUG_ON(xa, xa_cmpxchg(xa, 5, NULL, FIVE, GFP_KERNEL) != NULL);
  224. xa_erase_index(xa, 12345678);
  225. xa_erase_index(xa, 5);
  226. XA_BUG_ON(xa, !xa_empty(xa));
  227. }
  228. static noinline void check_xas_erase(struct xarray *xa)
  229. {
  230. XA_STATE(xas, xa, 0);
  231. void *entry;
  232. unsigned long i, j;
  233. for (i = 0; i < 200; i++) {
  234. for (j = i; j < 2 * i + 17; j++) {
  235. xas_set(&xas, j);
  236. do {
  237. xas_lock(&xas);
  238. xas_store(&xas, xa_mk_value(j));
  239. xas_unlock(&xas);
  240. } while (xas_nomem(&xas, GFP_KERNEL));
  241. }
  242. xas_set(&xas, ULONG_MAX);
  243. do {
  244. xas_lock(&xas);
  245. xas_store(&xas, xa_mk_value(0));
  246. xas_unlock(&xas);
  247. } while (xas_nomem(&xas, GFP_KERNEL));
  248. xas_lock(&xas);
  249. xas_store(&xas, NULL);
  250. xas_set(&xas, 0);
  251. j = i;
  252. xas_for_each(&xas, entry, ULONG_MAX) {
  253. XA_BUG_ON(xa, entry != xa_mk_value(j));
  254. xas_store(&xas, NULL);
  255. j++;
  256. }
  257. xas_unlock(&xas);
  258. XA_BUG_ON(xa, !xa_empty(xa));
  259. }
  260. }
  261. static noinline void check_multi_store(struct xarray *xa)
  262. {
  263. #ifdef CONFIG_XARRAY_MULTI
  264. unsigned long i, j, k;
  265. unsigned int max_order = (sizeof(long) == 4) ? 30 : 60;
  266. /* Loading from any position returns the same value */
  267. xa_store_order(xa, 0, 1, xa_mk_value(0), GFP_KERNEL);
  268. XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
  269. XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(0));
  270. XA_BUG_ON(xa, xa_load(xa, 2) != NULL);
  271. rcu_read_lock();
  272. XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 2);
  273. XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 2);
  274. rcu_read_unlock();
  275. /* Storing adjacent to the value does not alter the value */
  276. xa_store(xa, 3, xa, GFP_KERNEL);
  277. XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(0));
  278. XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(0));
  279. XA_BUG_ON(xa, xa_load(xa, 2) != NULL);
  280. rcu_read_lock();
  281. XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 3);
  282. XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 2);
  283. rcu_read_unlock();
  284. /* Overwriting multiple indexes works */
  285. xa_store_order(xa, 0, 2, xa_mk_value(1), GFP_KERNEL);
  286. XA_BUG_ON(xa, xa_load(xa, 0) != xa_mk_value(1));
  287. XA_BUG_ON(xa, xa_load(xa, 1) != xa_mk_value(1));
  288. XA_BUG_ON(xa, xa_load(xa, 2) != xa_mk_value(1));
  289. XA_BUG_ON(xa, xa_load(xa, 3) != xa_mk_value(1));
  290. XA_BUG_ON(xa, xa_load(xa, 4) != NULL);
  291. rcu_read_lock();
  292. XA_BUG_ON(xa, xa_to_node(xa_head(xa))->count != 4);
  293. XA_BUG_ON(xa, xa_to_node(xa_head(xa))->nr_values != 4);
  294. rcu_read_unlock();
  295. /* We can erase multiple values with a single store */
  296. xa_store_order(xa, 0, 63, NULL, GFP_KERNEL);
  297. XA_BUG_ON(xa, !xa_empty(xa));
  298. /* Even when the first slot is empty but the others aren't */
  299. xa_store_index(xa, 1, GFP_KERNEL);
  300. xa_store_index(xa, 2, GFP_KERNEL);
  301. xa_store_order(xa, 0, 2, NULL, GFP_KERNEL);
  302. XA_BUG_ON(xa, !xa_empty(xa));
  303. for (i = 0; i < max_order; i++) {
  304. for (j = 0; j < max_order; j++) {
  305. xa_store_order(xa, 0, i, xa_mk_value(i), GFP_KERNEL);
  306. xa_store_order(xa, 0, j, xa_mk_value(j), GFP_KERNEL);
  307. for (k = 0; k < max_order; k++) {
  308. void *entry = xa_load(xa, (1UL << k) - 1);
  309. if ((i < k) && (j < k))
  310. XA_BUG_ON(xa, entry != NULL);
  311. else
  312. XA_BUG_ON(xa, entry != xa_mk_value(j));
  313. }
  314. xa_erase(xa, 0);
  315. XA_BUG_ON(xa, !xa_empty(xa));
  316. }
  317. }
  318. #endif
  319. }
  320. static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
  321. unsigned int order, unsigned int present)
  322. {
  323. XA_STATE_ORDER(xas, xa, start, order);
  324. void *entry;
  325. unsigned int count = 0;
  326. retry:
  327. xas_lock(&xas);
  328. xas_for_each_conflict(&xas, entry) {
  329. XA_BUG_ON(xa, !xa_is_value(entry));
  330. XA_BUG_ON(xa, entry < xa_mk_value(start));
  331. XA_BUG_ON(xa, entry > xa_mk_value(start + (1UL << order) - 1));
  332. count++;
  333. }
  334. xas_store(&xas, xa_mk_value(start));
  335. xas_unlock(&xas);
  336. if (xas_nomem(&xas, GFP_KERNEL)) {
  337. count = 0;
  338. goto retry;
  339. }
  340. XA_BUG_ON(xa, xas_error(&xas));
  341. XA_BUG_ON(xa, count != present);
  342. XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_value(start));
  343. XA_BUG_ON(xa, xa_load(xa, start + (1UL << order) - 1) !=
  344. xa_mk_value(start));
  345. xa_erase_index(xa, start);
  346. }
  347. static noinline void check_store_iter(struct xarray *xa)
  348. {
  349. unsigned int i, j;
  350. unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 20 : 1;
  351. for (i = 0; i < max_order; i++) {
  352. unsigned int min = 1 << i;
  353. unsigned int max = (2 << i) - 1;
  354. __check_store_iter(xa, 0, i, 0);
  355. XA_BUG_ON(xa, !xa_empty(xa));
  356. __check_store_iter(xa, min, i, 0);
  357. XA_BUG_ON(xa, !xa_empty(xa));
  358. xa_store_index(xa, min, GFP_KERNEL);
  359. __check_store_iter(xa, min, i, 1);
  360. XA_BUG_ON(xa, !xa_empty(xa));
  361. xa_store_index(xa, max, GFP_KERNEL);
  362. __check_store_iter(xa, min, i, 1);
  363. XA_BUG_ON(xa, !xa_empty(xa));
  364. for (j = 0; j < min; j++)
  365. xa_store_index(xa, j, GFP_KERNEL);
  366. __check_store_iter(xa, 0, i, min);
  367. XA_BUG_ON(xa, !xa_empty(xa));
  368. for (j = 0; j < min; j++)
  369. xa_store_index(xa, min + j, GFP_KERNEL);
  370. __check_store_iter(xa, min, i, min);
  371. XA_BUG_ON(xa, !xa_empty(xa));
  372. }
  373. #ifdef CONFIG_XARRAY_MULTI
  374. xa_store_index(xa, 63, GFP_KERNEL);
  375. xa_store_index(xa, 65, GFP_KERNEL);
  376. __check_store_iter(xa, 64, 2, 1);
  377. xa_erase_index(xa, 63);
  378. #endif
  379. XA_BUG_ON(xa, !xa_empty(xa));
  380. }
  381. static noinline void check_multi_find(struct xarray *xa)
  382. {
  383. #ifdef CONFIG_XARRAY_MULTI
  384. unsigned long index;
  385. xa_store_order(xa, 12, 2, xa_mk_value(12), GFP_KERNEL);
  386. XA_BUG_ON(xa, xa_store_index(xa, 16, GFP_KERNEL) != NULL);
  387. index = 0;
  388. XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
  389. xa_mk_value(12));
  390. XA_BUG_ON(xa, index != 12);
  391. index = 13;
  392. XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
  393. xa_mk_value(12));
  394. XA_BUG_ON(xa, (index < 12) || (index >= 16));
  395. XA_BUG_ON(xa, xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT) !=
  396. xa_mk_value(16));
  397. XA_BUG_ON(xa, index != 16);
  398. xa_erase_index(xa, 12);
  399. xa_erase_index(xa, 16);
  400. XA_BUG_ON(xa, !xa_empty(xa));
  401. #endif
  402. }
  403. static noinline void check_multi_find_2(struct xarray *xa)
  404. {
  405. unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 10 : 1;
  406. unsigned int i, j;
  407. void *entry;
  408. for (i = 0; i < max_order; i++) {
  409. unsigned long index = 1UL << i;
  410. for (j = 0; j < index; j++) {
  411. XA_STATE(xas, xa, j + index);
  412. xa_store_index(xa, index - 1, GFP_KERNEL);
  413. xa_store_order(xa, index, i, xa_mk_value(index),
  414. GFP_KERNEL);
  415. rcu_read_lock();
  416. xas_for_each(&xas, entry, ULONG_MAX) {
  417. xa_erase_index(xa, index);
  418. }
  419. rcu_read_unlock();
  420. xa_erase_index(xa, index - 1);
  421. XA_BUG_ON(xa, !xa_empty(xa));
  422. }
  423. }
  424. }
  425. static noinline void check_find(struct xarray *xa)
  426. {
  427. unsigned long i, j, k;
  428. XA_BUG_ON(xa, !xa_empty(xa));
  429. /*
  430. * Check xa_find with all pairs between 0 and 99 inclusive,
  431. * starting at every index between 0 and 99
  432. */
  433. for (i = 0; i < 100; i++) {
  434. XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
  435. xa_set_mark(xa, i, XA_MARK_0);
  436. for (j = 0; j < i; j++) {
  437. XA_BUG_ON(xa, xa_store_index(xa, j, GFP_KERNEL) !=
  438. NULL);
  439. xa_set_mark(xa, j, XA_MARK_0);
  440. for (k = 0; k < 100; k++) {
  441. unsigned long index = k;
  442. void *entry = xa_find(xa, &index, ULONG_MAX,
  443. XA_PRESENT);
  444. if (k <= j)
  445. XA_BUG_ON(xa, index != j);
  446. else if (k <= i)
  447. XA_BUG_ON(xa, index != i);
  448. else
  449. XA_BUG_ON(xa, entry != NULL);
  450. index = k;
  451. entry = xa_find(xa, &index, ULONG_MAX,
  452. XA_MARK_0);
  453. if (k <= j)
  454. XA_BUG_ON(xa, index != j);
  455. else if (k <= i)
  456. XA_BUG_ON(xa, index != i);
  457. else
  458. XA_BUG_ON(xa, entry != NULL);
  459. }
  460. xa_erase_index(xa, j);
  461. XA_BUG_ON(xa, xa_get_mark(xa, j, XA_MARK_0));
  462. XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
  463. }
  464. xa_erase_index(xa, i);
  465. XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_0));
  466. }
  467. XA_BUG_ON(xa, !xa_empty(xa));
  468. check_multi_find(xa);
  469. check_multi_find_2(xa);
  470. }
  471. static noinline void check_move_small(struct xarray *xa, unsigned long idx)
  472. {
  473. XA_STATE(xas, xa, 0);
  474. unsigned long i;
  475. xa_store_index(xa, 0, GFP_KERNEL);
  476. xa_store_index(xa, idx, GFP_KERNEL);
  477. rcu_read_lock();
  478. for (i = 0; i < idx * 4; i++) {
  479. void *entry = xas_next(&xas);
  480. if (i <= idx)
  481. XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
  482. XA_BUG_ON(xa, xas.xa_index != i);
  483. if (i == 0 || i == idx)
  484. XA_BUG_ON(xa, entry != xa_mk_value(i));
  485. else
  486. XA_BUG_ON(xa, entry != NULL);
  487. }
  488. xas_next(&xas);
  489. XA_BUG_ON(xa, xas.xa_index != i);
  490. do {
  491. void *entry = xas_prev(&xas);
  492. i--;
  493. if (i <= idx)
  494. XA_BUG_ON(xa, xas.xa_node == XAS_RESTART);
  495. XA_BUG_ON(xa, xas.xa_index != i);
  496. if (i == 0 || i == idx)
  497. XA_BUG_ON(xa, entry != xa_mk_value(i));
  498. else
  499. XA_BUG_ON(xa, entry != NULL);
  500. } while (i > 0);
  501. xas_set(&xas, ULONG_MAX);
  502. XA_BUG_ON(xa, xas_next(&xas) != NULL);
  503. XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
  504. XA_BUG_ON(xa, xas_next(&xas) != xa_mk_value(0));
  505. XA_BUG_ON(xa, xas.xa_index != 0);
  506. XA_BUG_ON(xa, xas_prev(&xas) != NULL);
  507. XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
  508. rcu_read_unlock();
  509. xa_erase_index(xa, 0);
  510. xa_erase_index(xa, idx);
  511. XA_BUG_ON(xa, !xa_empty(xa));
  512. }
  513. static noinline void check_move(struct xarray *xa)
  514. {
  515. XA_STATE(xas, xa, (1 << 16) - 1);
  516. unsigned long i;
  517. for (i = 0; i < (1 << 16); i++)
  518. XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
  519. rcu_read_lock();
  520. do {
  521. void *entry = xas_prev(&xas);
  522. i--;
  523. XA_BUG_ON(xa, entry != xa_mk_value(i));
  524. XA_BUG_ON(xa, i != xas.xa_index);
  525. } while (i != 0);
  526. XA_BUG_ON(xa, xas_prev(&xas) != NULL);
  527. XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
  528. do {
  529. void *entry = xas_next(&xas);
  530. XA_BUG_ON(xa, entry != xa_mk_value(i));
  531. XA_BUG_ON(xa, i != xas.xa_index);
  532. i++;
  533. } while (i < (1 << 16));
  534. rcu_read_unlock();
  535. for (i = (1 << 8); i < (1 << 15); i++)
  536. xa_erase_index(xa, i);
  537. i = xas.xa_index;
  538. rcu_read_lock();
  539. do {
  540. void *entry = xas_prev(&xas);
  541. i--;
  542. if ((i < (1 << 8)) || (i >= (1 << 15)))
  543. XA_BUG_ON(xa, entry != xa_mk_value(i));
  544. else
  545. XA_BUG_ON(xa, entry != NULL);
  546. XA_BUG_ON(xa, i != xas.xa_index);
  547. } while (i != 0);
  548. XA_BUG_ON(xa, xas_prev(&xas) != NULL);
  549. XA_BUG_ON(xa, xas.xa_index != ULONG_MAX);
  550. do {
  551. void *entry = xas_next(&xas);
  552. if ((i < (1 << 8)) || (i >= (1 << 15)))
  553. XA_BUG_ON(xa, entry != xa_mk_value(i));
  554. else
  555. XA_BUG_ON(xa, entry != NULL);
  556. XA_BUG_ON(xa, i != xas.xa_index);
  557. i++;
  558. } while (i < (1 << 16));
  559. rcu_read_unlock();
  560. xa_destroy(xa);
  561. for (i = 0; i < 16; i++)
  562. check_move_small(xa, 1UL << i);
  563. for (i = 2; i < 16; i++)
  564. check_move_small(xa, (1UL << i) - 1);
  565. }
  566. static noinline void check_destroy(struct xarray *xa)
  567. {
  568. unsigned long index;
  569. XA_BUG_ON(xa, !xa_empty(xa));
  570. /* Destroying an empty array is a no-op */
  571. xa_destroy(xa);
  572. XA_BUG_ON(xa, !xa_empty(xa));
  573. /* Destroying an array with a single entry */
  574. for (index = 0; index < 1000; index++) {
  575. xa_store_index(xa, index, GFP_KERNEL);
  576. XA_BUG_ON(xa, xa_empty(xa));
  577. xa_destroy(xa);
  578. XA_BUG_ON(xa, !xa_empty(xa));
  579. }
  580. /* Destroying an array with a single entry at ULONG_MAX */
  581. xa_store(xa, ULONG_MAX, xa, GFP_KERNEL);
  582. XA_BUG_ON(xa, xa_empty(xa));
  583. xa_destroy(xa);
  584. XA_BUG_ON(xa, !xa_empty(xa));
  585. #ifdef CONFIG_XARRAY_MULTI
  586. /* Destroying an array with a multi-index entry */
  587. xa_store_order(xa, 1 << 11, 11, xa, GFP_KERNEL);
  588. XA_BUG_ON(xa, xa_empty(xa));
  589. xa_destroy(xa);
  590. XA_BUG_ON(xa, !xa_empty(xa));
  591. #endif
  592. }
  593. static DEFINE_XARRAY(array);
  594. static int xarray_checks(void)
  595. {
  596. check_xa_err(&array);
  597. check_xas_retry(&array);
  598. check_xa_load(&array);
  599. check_xa_mark(&array);
  600. check_xa_shrink(&array);
  601. check_xas_erase(&array);
  602. check_cmpxchg(&array);
  603. check_multi_store(&array);
  604. check_find(&array);
  605. check_destroy(&array);
  606. check_move(&array);
  607. check_store_iter(&array);
  608. printk("XArray: %u of %u tests passed\n", tests_passed, tests_run);
  609. return (tests_run == tests_passed) ? 0 : -EINVAL;
  610. }
  611. static void xarray_exit(void)
  612. {
  613. }
  614. module_init(xarray_checks);
  615. module_exit(xarray_exit);
  616. MODULE_AUTHOR("Matthew Wilcox <willy@infradead.org>");
  617. MODULE_LICENSE("GPL");