idr-test.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * idr-test.c: Test the IDR API
  4. * Copyright (c) 2016 Matthew Wilcox <[email protected]>
  5. */
  6. #include <linux/bitmap.h>
  7. #include <linux/idr.h>
  8. #include <linux/slab.h>
  9. #include <linux/kernel.h>
  10. #include <linux/errno.h>
  11. #include "test.h"
  12. #define DUMMY_PTR ((void *)0x10)
  13. int item_idr_free(int id, void *p, void *data)
  14. {
  15. struct item *item = p;
  16. assert(item->index == id);
  17. free(p);
  18. return 0;
  19. }
  20. void item_idr_remove(struct idr *idr, int id)
  21. {
  22. struct item *item = idr_find(idr, id);
  23. assert(item->index == id);
  24. idr_remove(idr, id);
  25. free(item);
  26. }
  27. void idr_alloc_test(void)
  28. {
  29. unsigned long i;
  30. DEFINE_IDR(idr);
  31. assert(idr_alloc_cyclic(&idr, DUMMY_PTR, 0, 0x4000, GFP_KERNEL) == 0);
  32. assert(idr_alloc_cyclic(&idr, DUMMY_PTR, 0x3ffd, 0x4000, GFP_KERNEL) == 0x3ffd);
  33. idr_remove(&idr, 0x3ffd);
  34. idr_remove(&idr, 0);
  35. for (i = 0x3ffe; i < 0x4003; i++) {
  36. int id;
  37. struct item *item;
  38. if (i < 0x4000)
  39. item = item_create(i, 0);
  40. else
  41. item = item_create(i - 0x3fff, 0);
  42. id = idr_alloc_cyclic(&idr, item, 1, 0x4000, GFP_KERNEL);
  43. assert(id == item->index);
  44. }
  45. idr_for_each(&idr, item_idr_free, &idr);
  46. idr_destroy(&idr);
  47. }
  48. void idr_replace_test(void)
  49. {
  50. DEFINE_IDR(idr);
  51. idr_alloc(&idr, (void *)-1, 10, 11, GFP_KERNEL);
  52. idr_replace(&idr, &idr, 10);
  53. idr_destroy(&idr);
  54. }
  55. /*
  56. * Unlike the radix tree, you can put a NULL pointer -- with care -- into
  57. * the IDR. Some interfaces, like idr_find() do not distinguish between
  58. * "present, value is NULL" and "not present", but that's exactly what some
  59. * users want.
  60. */
  61. void idr_null_test(void)
  62. {
  63. int i;
  64. DEFINE_IDR(idr);
  65. assert(idr_is_empty(&idr));
  66. assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 0);
  67. assert(!idr_is_empty(&idr));
  68. idr_remove(&idr, 0);
  69. assert(idr_is_empty(&idr));
  70. assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 0);
  71. assert(!idr_is_empty(&idr));
  72. idr_destroy(&idr);
  73. assert(idr_is_empty(&idr));
  74. for (i = 0; i < 10; i++) {
  75. assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == i);
  76. }
  77. assert(idr_replace(&idr, DUMMY_PTR, 3) == NULL);
  78. assert(idr_replace(&idr, DUMMY_PTR, 4) == NULL);
  79. assert(idr_replace(&idr, NULL, 4) == DUMMY_PTR);
  80. assert(idr_replace(&idr, DUMMY_PTR, 11) == ERR_PTR(-ENOENT));
  81. idr_remove(&idr, 5);
  82. assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 5);
  83. idr_remove(&idr, 5);
  84. for (i = 0; i < 9; i++) {
  85. idr_remove(&idr, i);
  86. assert(!idr_is_empty(&idr));
  87. }
  88. idr_remove(&idr, 8);
  89. assert(!idr_is_empty(&idr));
  90. idr_remove(&idr, 9);
  91. assert(idr_is_empty(&idr));
  92. assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 0);
  93. assert(idr_replace(&idr, DUMMY_PTR, 3) == ERR_PTR(-ENOENT));
  94. assert(idr_replace(&idr, DUMMY_PTR, 0) == NULL);
  95. assert(idr_replace(&idr, NULL, 0) == DUMMY_PTR);
  96. idr_destroy(&idr);
  97. assert(idr_is_empty(&idr));
  98. for (i = 1; i < 10; i++) {
  99. assert(idr_alloc(&idr, NULL, 1, 0, GFP_KERNEL) == i);
  100. }
  101. idr_destroy(&idr);
  102. assert(idr_is_empty(&idr));
  103. }
  104. void idr_nowait_test(void)
  105. {
  106. unsigned int i;
  107. DEFINE_IDR(idr);
  108. idr_preload(GFP_KERNEL);
  109. for (i = 0; i < 3; i++) {
  110. struct item *item = item_create(i, 0);
  111. assert(idr_alloc(&idr, item, i, i + 1, GFP_NOWAIT) == i);
  112. }
  113. idr_preload_end();
  114. idr_for_each(&idr, item_idr_free, &idr);
  115. idr_destroy(&idr);
  116. }
  117. void idr_get_next_test(int base)
  118. {
  119. unsigned long i;
  120. int nextid;
  121. DEFINE_IDR(idr);
  122. idr_init_base(&idr, base);
  123. int indices[] = {4, 7, 9, 15, 65, 128, 1000, 99999, 0};
  124. for(i = 0; indices[i]; i++) {
  125. struct item *item = item_create(indices[i], 0);
  126. assert(idr_alloc(&idr, item, indices[i], indices[i+1],
  127. GFP_KERNEL) == indices[i]);
  128. }
  129. for(i = 0, nextid = 0; indices[i]; i++) {
  130. idr_get_next(&idr, &nextid);
  131. assert(nextid == indices[i]);
  132. nextid++;
  133. }
  134. idr_for_each(&idr, item_idr_free, &idr);
  135. idr_destroy(&idr);
  136. }
  137. int idr_u32_cb(int id, void *ptr, void *data)
  138. {
  139. BUG_ON(id < 0);
  140. BUG_ON(ptr != DUMMY_PTR);
  141. return 0;
  142. }
  143. void idr_u32_test1(struct idr *idr, u32 handle)
  144. {
  145. static bool warned = false;
  146. u32 id = handle;
  147. int sid = 0;
  148. void *ptr;
  149. BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL));
  150. BUG_ON(id != handle);
  151. BUG_ON(idr_alloc_u32(idr, DUMMY_PTR, &id, id, GFP_KERNEL) != -ENOSPC);
  152. BUG_ON(id != handle);
  153. if (!warned && id > INT_MAX)
  154. printk("vvv Ignore these warnings\n");
  155. ptr = idr_get_next(idr, &sid);
  156. if (id > INT_MAX) {
  157. BUG_ON(ptr != NULL);
  158. BUG_ON(sid != 0);
  159. } else {
  160. BUG_ON(ptr != DUMMY_PTR);
  161. BUG_ON(sid != id);
  162. }
  163. idr_for_each(idr, idr_u32_cb, NULL);
  164. if (!warned && id > INT_MAX) {
  165. printk("^^^ Warnings over\n");
  166. warned = true;
  167. }
  168. BUG_ON(idr_remove(idr, id) != DUMMY_PTR);
  169. BUG_ON(!idr_is_empty(idr));
  170. }
  171. void idr_u32_test(int base)
  172. {
  173. DEFINE_IDR(idr);
  174. idr_init_base(&idr, base);
  175. idr_u32_test1(&idr, 10);
  176. idr_u32_test1(&idr, 0x7fffffff);
  177. idr_u32_test1(&idr, 0x80000000);
  178. idr_u32_test1(&idr, 0x80000001);
  179. idr_u32_test1(&idr, 0xffe00000);
  180. idr_u32_test1(&idr, 0xffffffff);
  181. }
  182. static void idr_align_test(struct idr *idr)
  183. {
  184. char name[] = "Motorola 68000";
  185. int i, id;
  186. void *entry;
  187. for (i = 0; i < 9; i++) {
  188. BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i);
  189. idr_for_each_entry(idr, entry, id);
  190. }
  191. idr_destroy(idr);
  192. for (i = 1; i < 10; i++) {
  193. BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 1);
  194. idr_for_each_entry(idr, entry, id);
  195. }
  196. idr_destroy(idr);
  197. for (i = 2; i < 11; i++) {
  198. BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 2);
  199. idr_for_each_entry(idr, entry, id);
  200. }
  201. idr_destroy(idr);
  202. for (i = 3; i < 12; i++) {
  203. BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != i - 3);
  204. idr_for_each_entry(idr, entry, id);
  205. }
  206. idr_destroy(idr);
  207. for (i = 0; i < 8; i++) {
  208. BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0);
  209. BUG_ON(idr_alloc(idr, &name[i + 1], 0, 0, GFP_KERNEL) != 1);
  210. idr_for_each_entry(idr, entry, id);
  211. idr_remove(idr, 1);
  212. idr_for_each_entry(idr, entry, id);
  213. idr_remove(idr, 0);
  214. BUG_ON(!idr_is_empty(idr));
  215. }
  216. for (i = 0; i < 8; i++) {
  217. BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 0);
  218. idr_for_each_entry(idr, entry, id);
  219. idr_replace(idr, &name[i], 0);
  220. idr_for_each_entry(idr, entry, id);
  221. BUG_ON(idr_find(idr, 0) != &name[i]);
  222. idr_remove(idr, 0);
  223. }
  224. for (i = 0; i < 8; i++) {
  225. BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0);
  226. BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 1);
  227. idr_remove(idr, 1);
  228. idr_for_each_entry(idr, entry, id);
  229. idr_replace(idr, &name[i + 1], 0);
  230. idr_for_each_entry(idr, entry, id);
  231. idr_remove(idr, 0);
  232. }
  233. }
  234. DEFINE_IDR(find_idr);
  235. static void *idr_throbber(void *arg)
  236. {
  237. time_t start = time(NULL);
  238. int id = *(int *)arg;
  239. rcu_register_thread();
  240. do {
  241. idr_alloc(&find_idr, xa_mk_value(id), id, id + 1, GFP_KERNEL);
  242. idr_remove(&find_idr, id);
  243. } while (time(NULL) < start + 10);
  244. rcu_unregister_thread();
  245. return NULL;
  246. }
  247. /*
  248. * There are always either 1 or 2 objects in the IDR. If we find nothing,
  249. * or we find something at an ID we didn't expect, that's a bug.
  250. */
  251. void idr_find_test_1(int anchor_id, int throbber_id)
  252. {
  253. pthread_t throbber;
  254. time_t start = time(NULL);
  255. BUG_ON(idr_alloc(&find_idr, xa_mk_value(anchor_id), anchor_id,
  256. anchor_id + 1, GFP_KERNEL) != anchor_id);
  257. pthread_create(&throbber, NULL, idr_throbber, &throbber_id);
  258. rcu_read_lock();
  259. do {
  260. int id = 0;
  261. void *entry = idr_get_next(&find_idr, &id);
  262. rcu_read_unlock();
  263. if ((id != anchor_id && id != throbber_id) ||
  264. entry != xa_mk_value(id)) {
  265. printf("%s(%d, %d): %p at %d\n", __func__, anchor_id,
  266. throbber_id, entry, id);
  267. abort();
  268. }
  269. rcu_read_lock();
  270. } while (time(NULL) < start + 11);
  271. rcu_read_unlock();
  272. pthread_join(throbber, NULL);
  273. idr_remove(&find_idr, anchor_id);
  274. BUG_ON(!idr_is_empty(&find_idr));
  275. }
  276. void idr_find_test(void)
  277. {
  278. idr_find_test_1(100000, 0);
  279. idr_find_test_1(0, 100000);
  280. }
  281. void idr_checks(void)
  282. {
  283. unsigned long i;
  284. DEFINE_IDR(idr);
  285. for (i = 0; i < 10000; i++) {
  286. struct item *item = item_create(i, 0);
  287. assert(idr_alloc(&idr, item, 0, 20000, GFP_KERNEL) == i);
  288. }
  289. assert(idr_alloc(&idr, DUMMY_PTR, 5, 30, GFP_KERNEL) < 0);
  290. for (i = 0; i < 5000; i++)
  291. item_idr_remove(&idr, i);
  292. idr_remove(&idr, 3);
  293. idr_for_each(&idr, item_idr_free, &idr);
  294. idr_destroy(&idr);
  295. assert(idr_is_empty(&idr));
  296. idr_remove(&idr, 3);
  297. idr_remove(&idr, 0);
  298. assert(idr_alloc(&idr, DUMMY_PTR, 0, 0, GFP_KERNEL) == 0);
  299. idr_remove(&idr, 1);
  300. for (i = 1; i < RADIX_TREE_MAP_SIZE; i++)
  301. assert(idr_alloc(&idr, DUMMY_PTR, 0, 0, GFP_KERNEL) == i);
  302. idr_remove(&idr, 1 << 30);
  303. idr_destroy(&idr);
  304. for (i = INT_MAX - 3UL; i < INT_MAX + 1UL; i++) {
  305. struct item *item = item_create(i, 0);
  306. assert(idr_alloc(&idr, item, i, i + 10, GFP_KERNEL) == i);
  307. }
  308. assert(idr_alloc(&idr, DUMMY_PTR, i - 2, i, GFP_KERNEL) == -ENOSPC);
  309. assert(idr_alloc(&idr, DUMMY_PTR, i - 2, i + 10, GFP_KERNEL) == -ENOSPC);
  310. idr_for_each(&idr, item_idr_free, &idr);
  311. idr_destroy(&idr);
  312. idr_destroy(&idr);
  313. assert(idr_is_empty(&idr));
  314. idr_set_cursor(&idr, INT_MAX - 3UL);
  315. for (i = INT_MAX - 3UL; i < INT_MAX + 3UL; i++) {
  316. struct item *item;
  317. unsigned int id;
  318. if (i <= INT_MAX)
  319. item = item_create(i, 0);
  320. else
  321. item = item_create(i - INT_MAX - 1, 0);
  322. id = idr_alloc_cyclic(&idr, item, 0, 0, GFP_KERNEL);
  323. assert(id == item->index);
  324. }
  325. idr_for_each(&idr, item_idr_free, &idr);
  326. idr_destroy(&idr);
  327. assert(idr_is_empty(&idr));
  328. for (i = 1; i < 10000; i++) {
  329. struct item *item = item_create(i, 0);
  330. assert(idr_alloc(&idr, item, 1, 20000, GFP_KERNEL) == i);
  331. }
  332. idr_for_each(&idr, item_idr_free, &idr);
  333. idr_destroy(&idr);
  334. idr_replace_test();
  335. idr_alloc_test();
  336. idr_null_test();
  337. idr_nowait_test();
  338. idr_get_next_test(0);
  339. idr_get_next_test(1);
  340. idr_get_next_test(4);
  341. idr_u32_test(4);
  342. idr_u32_test(1);
  343. idr_u32_test(0);
  344. idr_align_test(&idr);
  345. idr_find_test();
  346. }
  347. #define module_init(x)
  348. #define module_exit(x)
  349. #define MODULE_AUTHOR(x)
  350. #define MODULE_LICENSE(x)
  351. #define dump_stack() assert(0)
  352. void ida_dump(struct ida *);
  353. #include "../../../lib/test_ida.c"
  354. /*
  355. * Check that we get the correct error when we run out of memory doing
  356. * allocations. In userspace, GFP_NOWAIT will always fail an allocation.
  357. * The first test is for not having a bitmap available, and the second test
  358. * is for not being able to allocate a level of the radix tree.
  359. */
  360. void ida_check_nomem(void)
  361. {
  362. DEFINE_IDA(ida);
  363. int id;
  364. id = ida_alloc_min(&ida, 256, GFP_NOWAIT);
  365. IDA_BUG_ON(&ida, id != -ENOMEM);
  366. id = ida_alloc_min(&ida, 1UL << 30, GFP_NOWAIT);
  367. IDA_BUG_ON(&ida, id != -ENOMEM);
  368. IDA_BUG_ON(&ida, !ida_is_empty(&ida));
  369. }
  370. /*
  371. * Check handling of conversions between exceptional entries and full bitmaps.
  372. */
  373. void ida_check_conv_user(void)
  374. {
  375. DEFINE_IDA(ida);
  376. unsigned long i;
  377. for (i = 0; i < 1000000; i++) {
  378. int id = ida_alloc(&ida, GFP_NOWAIT);
  379. if (id == -ENOMEM) {
  380. IDA_BUG_ON(&ida, ((i % IDA_BITMAP_BITS) !=
  381. BITS_PER_XA_VALUE) &&
  382. ((i % IDA_BITMAP_BITS) != 0));
  383. id = ida_alloc(&ida, GFP_KERNEL);
  384. } else {
  385. IDA_BUG_ON(&ida, (i % IDA_BITMAP_BITS) ==
  386. BITS_PER_XA_VALUE);
  387. }
  388. IDA_BUG_ON(&ida, id != i);
  389. }
  390. ida_destroy(&ida);
  391. }
  392. void ida_check_random(void)
  393. {
  394. DEFINE_IDA(ida);
  395. DECLARE_BITMAP(bitmap, 2048);
  396. unsigned int i;
  397. time_t s = time(NULL);
  398. repeat:
  399. memset(bitmap, 0, sizeof(bitmap));
  400. for (i = 0; i < 100000; i++) {
  401. int i = rand();
  402. int bit = i & 2047;
  403. if (test_bit(bit, bitmap)) {
  404. __clear_bit(bit, bitmap);
  405. ida_free(&ida, bit);
  406. } else {
  407. __set_bit(bit, bitmap);
  408. IDA_BUG_ON(&ida, ida_alloc_min(&ida, bit, GFP_KERNEL)
  409. != bit);
  410. }
  411. }
  412. ida_destroy(&ida);
  413. if (time(NULL) < s + 10)
  414. goto repeat;
  415. }
  416. void ida_simple_get_remove_test(void)
  417. {
  418. DEFINE_IDA(ida);
  419. unsigned long i;
  420. for (i = 0; i < 10000; i++) {
  421. assert(ida_simple_get(&ida, 0, 20000, GFP_KERNEL) == i);
  422. }
  423. assert(ida_simple_get(&ida, 5, 30, GFP_KERNEL) < 0);
  424. for (i = 0; i < 10000; i++) {
  425. ida_simple_remove(&ida, i);
  426. }
  427. assert(ida_is_empty(&ida));
  428. ida_destroy(&ida);
  429. }
  430. void user_ida_checks(void)
  431. {
  432. radix_tree_cpu_dead(1);
  433. ida_check_nomem();
  434. ida_check_conv_user();
  435. ida_check_random();
  436. ida_simple_get_remove_test();
  437. radix_tree_cpu_dead(1);
  438. }
  439. static void *ida_random_fn(void *arg)
  440. {
  441. rcu_register_thread();
  442. ida_check_random();
  443. rcu_unregister_thread();
  444. return NULL;
  445. }
  446. static void *ida_leak_fn(void *arg)
  447. {
  448. struct ida *ida = arg;
  449. time_t s = time(NULL);
  450. int i, ret;
  451. rcu_register_thread();
  452. do for (i = 0; i < 1000; i++) {
  453. ret = ida_alloc_range(ida, 128, 128, GFP_KERNEL);
  454. if (ret >= 0)
  455. ida_free(ida, 128);
  456. } while (time(NULL) < s + 2);
  457. rcu_unregister_thread();
  458. return NULL;
  459. }
  460. void ida_thread_tests(void)
  461. {
  462. DEFINE_IDA(ida);
  463. pthread_t threads[20];
  464. int i;
  465. for (i = 0; i < ARRAY_SIZE(threads); i++)
  466. if (pthread_create(&threads[i], NULL, ida_random_fn, NULL)) {
  467. perror("creating ida thread");
  468. exit(1);
  469. }
  470. while (i--)
  471. pthread_join(threads[i], NULL);
  472. for (i = 0; i < ARRAY_SIZE(threads); i++)
  473. if (pthread_create(&threads[i], NULL, ida_leak_fn, &ida)) {
  474. perror("creating ida thread");
  475. exit(1);
  476. }
  477. while (i--)
  478. pthread_join(threads[i], NULL);
  479. assert(ida_is_empty(&ida));
  480. }
  481. void ida_tests(void)
  482. {
  483. user_ida_checks();
  484. ida_checks();
  485. ida_exit();
  486. ida_thread_tests();
  487. }
  488. int __weak main(void)
  489. {
  490. rcu_register_thread();
  491. radix_tree_init();
  492. idr_checks();
  493. ida_tests();
  494. radix_tree_cpu_dead(1);
  495. rcu_barrier();
  496. if (nr_allocated)
  497. printf("nr_allocated = %d\n", nr_allocated);
  498. rcu_unregister_thread();
  499. return 0;
  500. }