test_xarray.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  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_multi_find(struct xarray *xa)
  321. {
  322. #ifdef CONFIG_XARRAY_MULTI
  323. unsigned long index;
  324. xa_store_order(xa, 12, 2, xa_mk_value(12), GFP_KERNEL);
  325. XA_BUG_ON(xa, xa_store_index(xa, 16, GFP_KERNEL) != NULL);
  326. index = 0;
  327. XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
  328. xa_mk_value(12));
  329. XA_BUG_ON(xa, index != 12);
  330. index = 13;
  331. XA_BUG_ON(xa, xa_find(xa, &index, ULONG_MAX, XA_PRESENT) !=
  332. xa_mk_value(12));
  333. XA_BUG_ON(xa, (index < 12) || (index >= 16));
  334. XA_BUG_ON(xa, xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT) !=
  335. xa_mk_value(16));
  336. XA_BUG_ON(xa, index != 16);
  337. xa_erase_index(xa, 12);
  338. xa_erase_index(xa, 16);
  339. XA_BUG_ON(xa, !xa_empty(xa));
  340. #endif
  341. }
  342. static noinline void check_multi_find_2(struct xarray *xa)
  343. {
  344. unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 10 : 1;
  345. unsigned int i, j;
  346. void *entry;
  347. for (i = 0; i < max_order; i++) {
  348. unsigned long index = 1UL << i;
  349. for (j = 0; j < index; j++) {
  350. XA_STATE(xas, xa, j + index);
  351. xa_store_index(xa, index - 1, GFP_KERNEL);
  352. xa_store_order(xa, index, i, xa_mk_value(index),
  353. GFP_KERNEL);
  354. rcu_read_lock();
  355. xas_for_each(&xas, entry, ULONG_MAX) {
  356. xa_erase_index(xa, index);
  357. }
  358. rcu_read_unlock();
  359. xa_erase_index(xa, index - 1);
  360. XA_BUG_ON(xa, !xa_empty(xa));
  361. }
  362. }
  363. }
  364. static noinline void check_find(struct xarray *xa)
  365. {
  366. unsigned long i, j, k;
  367. XA_BUG_ON(xa, !xa_empty(xa));
  368. /*
  369. * Check xa_find with all pairs between 0 and 99 inclusive,
  370. * starting at every index between 0 and 99
  371. */
  372. for (i = 0; i < 100; i++) {
  373. XA_BUG_ON(xa, xa_store_index(xa, i, GFP_KERNEL) != NULL);
  374. xa_set_mark(xa, i, XA_MARK_0);
  375. for (j = 0; j < i; j++) {
  376. XA_BUG_ON(xa, xa_store_index(xa, j, GFP_KERNEL) !=
  377. NULL);
  378. xa_set_mark(xa, j, XA_MARK_0);
  379. for (k = 0; k < 100; k++) {
  380. unsigned long index = k;
  381. void *entry = xa_find(xa, &index, ULONG_MAX,
  382. XA_PRESENT);
  383. if (k <= j)
  384. XA_BUG_ON(xa, index != j);
  385. else if (k <= i)
  386. XA_BUG_ON(xa, index != i);
  387. else
  388. XA_BUG_ON(xa, entry != NULL);
  389. index = k;
  390. entry = xa_find(xa, &index, ULONG_MAX,
  391. XA_MARK_0);
  392. if (k <= j)
  393. XA_BUG_ON(xa, index != j);
  394. else if (k <= i)
  395. XA_BUG_ON(xa, index != i);
  396. else
  397. XA_BUG_ON(xa, entry != NULL);
  398. }
  399. xa_erase_index(xa, j);
  400. XA_BUG_ON(xa, xa_get_mark(xa, j, XA_MARK_0));
  401. XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
  402. }
  403. xa_erase_index(xa, i);
  404. XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_0));
  405. }
  406. XA_BUG_ON(xa, !xa_empty(xa));
  407. check_multi_find(xa);
  408. check_multi_find_2(xa);
  409. }
  410. static DEFINE_XARRAY(array);
  411. static int xarray_checks(void)
  412. {
  413. check_xa_err(&array);
  414. check_xas_retry(&array);
  415. check_xa_load(&array);
  416. check_xa_mark(&array);
  417. check_xa_shrink(&array);
  418. check_xas_erase(&array);
  419. check_cmpxchg(&array);
  420. check_multi_store(&array);
  421. check_find(&array);
  422. printk("XArray: %u of %u tests passed\n", tests_passed, tests_run);
  423. return (tests_run == tests_passed) ? 0 : -EINVAL;
  424. }
  425. static void xarray_exit(void)
  426. {
  427. }
  428. module_init(xarray_checks);
  429. module_exit(xarray_exit);
  430. MODULE_AUTHOR("Matthew Wilcox <willy@infradead.org>");
  431. MODULE_LICENSE("GPL");