diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-26 14:48:42 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-26 14:48:42 -0400 |
| commit | aba16dc5cf9318b4e0fe92f8261779cd9f1d2d77 (patch) | |
| tree | 1f53d2cee40e82efe6a727208307af475327af9a /lib | |
| parent | c4726e774ed27680c418e138234dfd2b8e1e89ac (diff) | |
| parent | 1df895190233fcc30d46beca4550bcafb7b959a6 (diff) | |
Merge branch 'ida-4.19' of git://git.infradead.org/users/willy/linux-dax
Pull IDA updates from Matthew Wilcox:
"A better IDA API:
id = ida_alloc(ida, GFP_xxx);
ida_free(ida, id);
rather than the cumbersome ida_simple_get(), ida_simple_remove().
The new IDA API is similar to ida_simple_get() but better named. The
internal restructuring of the IDA code removes the bitmap
preallocation nonsense.
I hope the net -200 lines of code is convincing"
* 'ida-4.19' of git://git.infradead.org/users/willy/linux-dax: (29 commits)
ida: Change ida_get_new_above to return the id
ida: Remove old API
test_ida: check_ida_destroy and check_ida_alloc
test_ida: Convert check_ida_conv to new API
test_ida: Move ida_check_max
test_ida: Move ida_check_leaf
idr-test: Convert ida_check_nomem to new API
ida: Start new test_ida module
target/iscsi: Allocate session IDs from an IDA
iscsi target: fix session creation failure handling
drm/vmwgfx: Convert to new IDA API
dmaengine: Convert to new IDA API
ppc: Convert vas ID allocation to new IDA API
media: Convert entity ID allocation to new IDA API
ppc: Convert mmu context allocation to new IDA API
Convert net_namespace to new IDA API
cb710: Convert to new IDA API
rsxx: Convert to new IDA API
osd: Convert to new IDA API
sd: Convert to new IDA API
...
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Kconfig.debug | 3 | ||||
| -rw-r--r-- | lib/Makefile | 1 | ||||
| -rw-r--r-- | lib/idr.c | 155 | ||||
| -rw-r--r-- | lib/radix-tree.c | 11 | ||||
| -rw-r--r-- | lib/test_ida.c | 177 |
5 files changed, 238 insertions, 109 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 3589765141a8..613316724c6a 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -1833,6 +1833,9 @@ config TEST_HASH | |||
| 1833 | This is intended to help people writing architecture-specific | 1833 | This is intended to help people writing architecture-specific |
| 1834 | optimized versions. If unsure, say N. | 1834 | optimized versions. If unsure, say N. |
| 1835 | 1835 | ||
| 1836 | config TEST_IDA | ||
| 1837 | tristate "Perform selftest on IDA functions" | ||
| 1838 | |||
| 1836 | config TEST_PARMAN | 1839 | config TEST_PARMAN |
| 1837 | tristate "Perform selftest on priority array manager" | 1840 | tristate "Perform selftest on priority array manager" |
| 1838 | depends on PARMAN | 1841 | depends on PARMAN |
diff --git a/lib/Makefile b/lib/Makefile index 9baefb6cb1a1..ca3f7ebb900d 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -50,6 +50,7 @@ obj-$(CONFIG_TEST_BPF) += test_bpf.o | |||
| 50 | obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o | 50 | obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o |
| 51 | obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o | 51 | obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o |
| 52 | obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o | 52 | obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o |
| 53 | obj-$(CONFIG_TEST_IDA) += test_ida.o | ||
| 53 | obj-$(CONFIG_TEST_KASAN) += test_kasan.o | 54 | obj-$(CONFIG_TEST_KASAN) += test_kasan.o |
| 54 | CFLAGS_test_kasan.o += -fno-builtin | 55 | CFLAGS_test_kasan.o += -fno-builtin |
| 55 | obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o | 56 | obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o |
| @@ -317,18 +317,12 @@ EXPORT_SYMBOL(idr_replace); | |||
| 317 | * bit per ID, and so is more space efficient than an IDR. To use an IDA, | 317 | * bit per ID, and so is more space efficient than an IDR. To use an IDA, |
| 318 | * define it using DEFINE_IDA() (or embed a &struct ida in a data structure, | 318 | * define it using DEFINE_IDA() (or embed a &struct ida in a data structure, |
| 319 | * then initialise it using ida_init()). To allocate a new ID, call | 319 | * then initialise it using ida_init()). To allocate a new ID, call |
| 320 | * ida_simple_get(). To free an ID, call ida_simple_remove(). | 320 | * ida_alloc(), ida_alloc_min(), ida_alloc_max() or ida_alloc_range(). |
| 321 | * To free an ID, call ida_free(). | ||
| 321 | * | 322 | * |
| 322 | * If you have more complex locking requirements, use a loop around | 323 | * ida_destroy() can be used to dispose of an IDA without needing to |
| 323 | * ida_pre_get() and ida_get_new() to allocate a new ID. Then use | 324 | * free the individual IDs in it. You can use ida_is_empty() to find |
| 324 | * ida_remove() to free an ID. You must make sure that ida_get_new() and | 325 | * out whether the IDA has any IDs currently allocated. |
| 325 | * ida_remove() cannot be called at the same time as each other for the | ||
| 326 | * same IDA. | ||
| 327 | * | ||
| 328 | * You can also use ida_get_new_above() if you need an ID to be allocated | ||
| 329 | * above a particular number. ida_destroy() can be used to dispose of an | ||
| 330 | * IDA without needing to free the individual IDs in it. You can use | ||
| 331 | * ida_is_empty() to find out whether the IDA has any IDs currently allocated. | ||
| 332 | * | 326 | * |
| 333 | * IDs are currently limited to the range [0-INT_MAX]. If this is an awkward | 327 | * IDs are currently limited to the range [0-INT_MAX]. If this is an awkward |
| 334 | * limitation, it should be quite straightforward to raise the maximum. | 328 | * limitation, it should be quite straightforward to raise the maximum. |
| @@ -369,25 +363,7 @@ EXPORT_SYMBOL(idr_replace); | |||
| 369 | 363 | ||
| 370 | #define IDA_MAX (0x80000000U / IDA_BITMAP_BITS - 1) | 364 | #define IDA_MAX (0x80000000U / IDA_BITMAP_BITS - 1) |
| 371 | 365 | ||
| 372 | /** | 366 | static int ida_get_new_above(struct ida *ida, int start) |
| 373 | * ida_get_new_above - allocate new ID above or equal to a start id | ||
| 374 | * @ida: ida handle | ||
| 375 | * @start: id to start search at | ||
| 376 | * @id: pointer to the allocated handle | ||
| 377 | * | ||
| 378 | * Allocate new ID above or equal to @start. It should be called | ||
| 379 | * with any required locks to ensure that concurrent calls to | ||
| 380 | * ida_get_new_above() / ida_get_new() / ida_remove() are not allowed. | ||
| 381 | * Consider using ida_simple_get() if you do not have complex locking | ||
| 382 | * requirements. | ||
| 383 | * | ||
| 384 | * If memory is required, it will return %-EAGAIN, you should unlock | ||
| 385 | * and go back to the ida_pre_get() call. If the ida is full, it will | ||
| 386 | * return %-ENOSPC. On success, it will return 0. | ||
| 387 | * | ||
| 388 | * @id returns a value in the range @start ... %0x7fffffff. | ||
| 389 | */ | ||
| 390 | int ida_get_new_above(struct ida *ida, int start, int *id) | ||
| 391 | { | 367 | { |
| 392 | struct radix_tree_root *root = &ida->ida_rt; | 368 | struct radix_tree_root *root = &ida->ida_rt; |
| 393 | void __rcu **slot; | 369 | void __rcu **slot; |
| @@ -426,8 +402,8 @@ int ida_get_new_above(struct ida *ida, int start, int *id) | |||
| 426 | if (ebit < BITS_PER_LONG) { | 402 | if (ebit < BITS_PER_LONG) { |
| 427 | tmp |= 1UL << ebit; | 403 | tmp |= 1UL << ebit; |
| 428 | rcu_assign_pointer(*slot, (void *)tmp); | 404 | rcu_assign_pointer(*slot, (void *)tmp); |
| 429 | *id = new + ebit - RADIX_TREE_EXCEPTIONAL_SHIFT; | 405 | return new + ebit - |
| 430 | return 0; | 406 | RADIX_TREE_EXCEPTIONAL_SHIFT; |
| 431 | } | 407 | } |
| 432 | bitmap = this_cpu_xchg(ida_bitmap, NULL); | 408 | bitmap = this_cpu_xchg(ida_bitmap, NULL); |
| 433 | if (!bitmap) | 409 | if (!bitmap) |
| @@ -458,8 +434,7 @@ int ida_get_new_above(struct ida *ida, int start, int *id) | |||
| 458 | RADIX_TREE_EXCEPTIONAL_ENTRY); | 434 | RADIX_TREE_EXCEPTIONAL_ENTRY); |
| 459 | radix_tree_iter_replace(root, &iter, slot, | 435 | radix_tree_iter_replace(root, &iter, slot, |
| 460 | bitmap); | 436 | bitmap); |
| 461 | *id = new; | 437 | return new; |
| 462 | return 0; | ||
| 463 | } | 438 | } |
| 464 | bitmap = this_cpu_xchg(ida_bitmap, NULL); | 439 | bitmap = this_cpu_xchg(ida_bitmap, NULL); |
| 465 | if (!bitmap) | 440 | if (!bitmap) |
| @@ -468,20 +443,11 @@ int ida_get_new_above(struct ida *ida, int start, int *id) | |||
| 468 | radix_tree_iter_replace(root, &iter, slot, bitmap); | 443 | radix_tree_iter_replace(root, &iter, slot, bitmap); |
| 469 | } | 444 | } |
| 470 | 445 | ||
| 471 | *id = new; | 446 | return new; |
| 472 | return 0; | ||
| 473 | } | 447 | } |
| 474 | } | 448 | } |
| 475 | EXPORT_SYMBOL(ida_get_new_above); | ||
| 476 | 449 | ||
| 477 | /** | 450 | static void ida_remove(struct ida *ida, int id) |
| 478 | * ida_remove - Free the given ID | ||
| 479 | * @ida: ida handle | ||
| 480 | * @id: ID to free | ||
| 481 | * | ||
| 482 | * This function should not be called at the same time as ida_get_new_above(). | ||
| 483 | */ | ||
| 484 | void ida_remove(struct ida *ida, int id) | ||
| 485 | { | 451 | { |
| 486 | unsigned long index = id / IDA_BITMAP_BITS; | 452 | unsigned long index = id / IDA_BITMAP_BITS; |
| 487 | unsigned offset = id % IDA_BITMAP_BITS; | 453 | unsigned offset = id % IDA_BITMAP_BITS; |
| @@ -518,99 +484,90 @@ void ida_remove(struct ida *ida, int id) | |||
| 518 | } | 484 | } |
| 519 | return; | 485 | return; |
| 520 | err: | 486 | err: |
| 521 | WARN(1, "ida_remove called for id=%d which is not allocated.\n", id); | 487 | WARN(1, "ida_free called for id=%d which is not allocated.\n", id); |
| 522 | } | 488 | } |
| 523 | EXPORT_SYMBOL(ida_remove); | ||
| 524 | 489 | ||
| 525 | /** | 490 | /** |
| 526 | * ida_destroy - Free the contents of an ida | 491 | * ida_destroy() - Free all IDs. |
| 527 | * @ida: ida handle | 492 | * @ida: IDA handle. |
| 493 | * | ||
| 494 | * Calling this function frees all IDs and releases all resources used | ||
| 495 | * by an IDA. When this call returns, the IDA is empty and can be reused | ||
| 496 | * or freed. If the IDA is already empty, there is no need to call this | ||
| 497 | * function. | ||
| 528 | * | 498 | * |
| 529 | * Calling this function releases all resources associated with an IDA. When | 499 | * Context: Any context. |
| 530 | * this call returns, the IDA is empty and can be reused or freed. The caller | ||
| 531 | * should not allow ida_remove() or ida_get_new_above() to be called at the | ||
| 532 | * same time. | ||
| 533 | */ | 500 | */ |
| 534 | void ida_destroy(struct ida *ida) | 501 | void ida_destroy(struct ida *ida) |
| 535 | { | 502 | { |
| 503 | unsigned long flags; | ||
| 536 | struct radix_tree_iter iter; | 504 | struct radix_tree_iter iter; |
| 537 | void __rcu **slot; | 505 | void __rcu **slot; |
| 538 | 506 | ||
| 507 | xa_lock_irqsave(&ida->ida_rt, flags); | ||
| 539 | radix_tree_for_each_slot(slot, &ida->ida_rt, &iter, 0) { | 508 | radix_tree_for_each_slot(slot, &ida->ida_rt, &iter, 0) { |
| 540 | struct ida_bitmap *bitmap = rcu_dereference_raw(*slot); | 509 | struct ida_bitmap *bitmap = rcu_dereference_raw(*slot); |
| 541 | if (!radix_tree_exception(bitmap)) | 510 | if (!radix_tree_exception(bitmap)) |
| 542 | kfree(bitmap); | 511 | kfree(bitmap); |
| 543 | radix_tree_iter_delete(&ida->ida_rt, &iter, slot); | 512 | radix_tree_iter_delete(&ida->ida_rt, &iter, slot); |
| 544 | } | 513 | } |
| 514 | xa_unlock_irqrestore(&ida->ida_rt, flags); | ||
| 545 | } | 515 | } |
| 546 | EXPORT_SYMBOL(ida_destroy); | 516 | EXPORT_SYMBOL(ida_destroy); |
| 547 | 517 | ||
| 548 | /** | 518 | /** |
| 549 | * ida_simple_get - get a new id. | 519 | * ida_alloc_range() - Allocate an unused ID. |
| 550 | * @ida: the (initialized) ida. | 520 | * @ida: IDA handle. |
| 551 | * @start: the minimum id (inclusive, < 0x8000000) | 521 | * @min: Lowest ID to allocate. |
| 552 | * @end: the maximum id (exclusive, < 0x8000000 or 0) | 522 | * @max: Highest ID to allocate. |
| 553 | * @gfp_mask: memory allocation flags | 523 | * @gfp: Memory allocation flags. |
| 554 | * | ||
| 555 | * Allocates an id in the range start <= id < end, or returns -ENOSPC. | ||
| 556 | * On memory allocation failure, returns -ENOMEM. | ||
| 557 | * | 524 | * |
| 558 | * Compared to ida_get_new_above() this function does its own locking, and | 525 | * Allocate an ID between @min and @max, inclusive. The allocated ID will |
| 559 | * should be used unless there are special requirements. | 526 | * not exceed %INT_MAX, even if @max is larger. |
| 560 | * | 527 | * |
| 561 | * Use ida_simple_remove() to get rid of an id. | 528 | * Context: Any context. |
| 529 | * Return: The allocated ID, or %-ENOMEM if memory could not be allocated, | ||
| 530 | * or %-ENOSPC if there are no free IDs. | ||
| 562 | */ | 531 | */ |
| 563 | int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, | 532 | int ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max, |
| 564 | gfp_t gfp_mask) | 533 | gfp_t gfp) |
| 565 | { | 534 | { |
| 566 | int ret, id; | 535 | int id = 0; |
| 567 | unsigned int max; | ||
| 568 | unsigned long flags; | 536 | unsigned long flags; |
| 569 | 537 | ||
| 570 | BUG_ON((int)start < 0); | 538 | if ((int)min < 0) |
| 571 | BUG_ON((int)end < 0); | 539 | return -ENOSPC; |
| 572 | 540 | ||
| 573 | if (end == 0) | 541 | if ((int)max < 0) |
| 574 | max = 0x80000000; | 542 | max = INT_MAX; |
| 575 | else { | ||
| 576 | BUG_ON(end < start); | ||
| 577 | max = end - 1; | ||
| 578 | } | ||
| 579 | 543 | ||
| 580 | again: | 544 | again: |
| 581 | if (!ida_pre_get(ida, gfp_mask)) | ||
| 582 | return -ENOMEM; | ||
| 583 | |||
| 584 | xa_lock_irqsave(&ida->ida_rt, flags); | 545 | xa_lock_irqsave(&ida->ida_rt, flags); |
| 585 | ret = ida_get_new_above(ida, start, &id); | 546 | id = ida_get_new_above(ida, min); |
| 586 | if (!ret) { | 547 | if (id > (int)max) { |
| 587 | if (id > max) { | 548 | ida_remove(ida, id); |
| 588 | ida_remove(ida, id); | 549 | id = -ENOSPC; |
| 589 | ret = -ENOSPC; | ||
| 590 | } else { | ||
| 591 | ret = id; | ||
| 592 | } | ||
| 593 | } | 550 | } |
| 594 | xa_unlock_irqrestore(&ida->ida_rt, flags); | 551 | xa_unlock_irqrestore(&ida->ida_rt, flags); |
| 595 | 552 | ||
| 596 | if (unlikely(ret == -EAGAIN)) | 553 | if (unlikely(id == -EAGAIN)) { |
| 554 | if (!ida_pre_get(ida, gfp)) | ||
| 555 | return -ENOMEM; | ||
| 597 | goto again; | 556 | goto again; |
| 557 | } | ||
| 598 | 558 | ||
| 599 | return ret; | 559 | return id; |
| 600 | } | 560 | } |
| 601 | EXPORT_SYMBOL(ida_simple_get); | 561 | EXPORT_SYMBOL(ida_alloc_range); |
| 602 | 562 | ||
| 603 | /** | 563 | /** |
| 604 | * ida_simple_remove - remove an allocated id. | 564 | * ida_free() - Release an allocated ID. |
| 605 | * @ida: the (initialized) ida. | 565 | * @ida: IDA handle. |
| 606 | * @id: the id returned by ida_simple_get. | 566 | * @id: Previously allocated ID. |
| 607 | * | ||
| 608 | * Use to release an id allocated with ida_simple_get(). | ||
| 609 | * | 567 | * |
| 610 | * Compared to ida_remove() this function does its own locking, and should be | 568 | * Context: Any context. |
| 611 | * used unless there are special requirements. | ||
| 612 | */ | 569 | */ |
| 613 | void ida_simple_remove(struct ida *ida, unsigned int id) | 570 | void ida_free(struct ida *ida, unsigned int id) |
| 614 | { | 571 | { |
| 615 | unsigned long flags; | 572 | unsigned long flags; |
| 616 | 573 | ||
| @@ -619,4 +576,4 @@ void ida_simple_remove(struct ida *ida, unsigned int id) | |||
| 619 | ida_remove(ida, id); | 576 | ida_remove(ida, id); |
| 620 | xa_unlock_irqrestore(&ida->ida_rt, flags); | 577 | xa_unlock_irqrestore(&ida->ida_rt, flags); |
| 621 | } | 578 | } |
| 622 | EXPORT_SYMBOL(ida_simple_remove); | 579 | EXPORT_SYMBOL(ida_free); |
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index a9e41aed6de4..bc03ecc4dfd2 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
| @@ -120,7 +120,7 @@ bool is_sibling_entry(const struct radix_tree_node *parent, void *node) | |||
| 120 | static inline unsigned long | 120 | static inline unsigned long |
| 121 | get_slot_offset(const struct radix_tree_node *parent, void __rcu **slot) | 121 | get_slot_offset(const struct radix_tree_node *parent, void __rcu **slot) |
| 122 | { | 122 | { |
| 123 | return slot - parent->slots; | 123 | return parent ? slot - parent->slots : 0; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | static unsigned int radix_tree_descend(const struct radix_tree_node *parent, | 126 | static unsigned int radix_tree_descend(const struct radix_tree_node *parent, |
| @@ -2106,14 +2106,6 @@ void idr_preload(gfp_t gfp_mask) | |||
| 2106 | } | 2106 | } |
| 2107 | EXPORT_SYMBOL(idr_preload); | 2107 | EXPORT_SYMBOL(idr_preload); |
| 2108 | 2108 | ||
| 2109 | /** | ||
| 2110 | * ida_pre_get - reserve resources for ida allocation | ||
| 2111 | * @ida: ida handle | ||
| 2112 | * @gfp: memory allocation flags | ||
| 2113 | * | ||
| 2114 | * This function should be called before calling ida_get_new_above(). If it | ||
| 2115 | * is unable to allocate memory, it will return %0. On success, it returns %1. | ||
| 2116 | */ | ||
| 2117 | int ida_pre_get(struct ida *ida, gfp_t gfp) | 2109 | int ida_pre_get(struct ida *ida, gfp_t gfp) |
| 2118 | { | 2110 | { |
| 2119 | /* | 2111 | /* |
| @@ -2134,7 +2126,6 @@ int ida_pre_get(struct ida *ida, gfp_t gfp) | |||
| 2134 | 2126 | ||
| 2135 | return 1; | 2127 | return 1; |
| 2136 | } | 2128 | } |
| 2137 | EXPORT_SYMBOL(ida_pre_get); | ||
| 2138 | 2129 | ||
| 2139 | void __rcu **idr_get_free(struct radix_tree_root *root, | 2130 | void __rcu **idr_get_free(struct radix_tree_root *root, |
| 2140 | struct radix_tree_iter *iter, gfp_t gfp, | 2131 | struct radix_tree_iter *iter, gfp_t gfp, |
diff --git a/lib/test_ida.c b/lib/test_ida.c new file mode 100644 index 000000000000..2d1637d8136b --- /dev/null +++ b/lib/test_ida.c | |||
| @@ -0,0 +1,177 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | /* | ||
| 3 | * test_ida.c: Test the IDA API | ||
| 4 | * Copyright (c) 2016-2018 Microsoft Corporation | ||
| 5 | * Copyright (c) 2018 Oracle Corporation | ||
| 6 | * Author: Matthew Wilcox <willy@infradead.org> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/idr.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | |||
| 12 | static unsigned int tests_run; | ||
| 13 | static unsigned int tests_passed; | ||
| 14 | |||
| 15 | #ifdef __KERNEL__ | ||
| 16 | void ida_dump(struct ida *ida) { } | ||
| 17 | #endif | ||
| 18 | #define IDA_BUG_ON(ida, x) do { \ | ||
| 19 | tests_run++; \ | ||
| 20 | if (x) { \ | ||
| 21 | ida_dump(ida); \ | ||
| 22 | dump_stack(); \ | ||
| 23 | } else { \ | ||
| 24 | tests_passed++; \ | ||
| 25 | } \ | ||
| 26 | } while (0) | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Straightforward checks that allocating and freeing IDs work. | ||
| 30 | */ | ||
| 31 | static void ida_check_alloc(struct ida *ida) | ||
| 32 | { | ||
| 33 | int i, id; | ||
| 34 | |||
| 35 | for (i = 0; i < 10000; i++) | ||
| 36 | IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != i); | ||
| 37 | |||
| 38 | ida_free(ida, 20); | ||
| 39 | ida_free(ida, 21); | ||
| 40 | for (i = 0; i < 3; i++) { | ||
| 41 | id = ida_alloc(ida, GFP_KERNEL); | ||
| 42 | IDA_BUG_ON(ida, id < 0); | ||
| 43 | if (i == 2) | ||
| 44 | IDA_BUG_ON(ida, id != 10000); | ||
| 45 | } | ||
| 46 | |||
| 47 | for (i = 0; i < 5000; i++) | ||
| 48 | ida_free(ida, i); | ||
| 49 | |||
| 50 | IDA_BUG_ON(ida, ida_alloc_min(ida, 5000, GFP_KERNEL) != 10001); | ||
| 51 | ida_destroy(ida); | ||
| 52 | |||
| 53 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 54 | } | ||
| 55 | |||
| 56 | /* Destroy an IDA with a single entry at @base */ | ||
| 57 | static void ida_check_destroy_1(struct ida *ida, unsigned int base) | ||
| 58 | { | ||
| 59 | IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) != base); | ||
| 60 | IDA_BUG_ON(ida, ida_is_empty(ida)); | ||
| 61 | ida_destroy(ida); | ||
| 62 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 63 | } | ||
| 64 | |||
| 65 | /* Check that ida_destroy and ida_is_empty work */ | ||
| 66 | static void ida_check_destroy(struct ida *ida) | ||
| 67 | { | ||
| 68 | /* Destroy an already-empty IDA */ | ||
| 69 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 70 | ida_destroy(ida); | ||
| 71 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 72 | |||
| 73 | ida_check_destroy_1(ida, 0); | ||
| 74 | ida_check_destroy_1(ida, 1); | ||
| 75 | ida_check_destroy_1(ida, 1023); | ||
| 76 | ida_check_destroy_1(ida, 1024); | ||
| 77 | ida_check_destroy_1(ida, 12345678); | ||
| 78 | } | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Check what happens when we fill a leaf and then delete it. This may | ||
| 82 | * discover mishandling of IDR_FREE. | ||
| 83 | */ | ||
| 84 | static void ida_check_leaf(struct ida *ida, unsigned int base) | ||
| 85 | { | ||
| 86 | unsigned long i; | ||
| 87 | |||
| 88 | for (i = 0; i < IDA_BITMAP_BITS; i++) { | ||
| 89 | IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) != | ||
| 90 | base + i); | ||
| 91 | } | ||
| 92 | |||
| 93 | ida_destroy(ida); | ||
| 94 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 95 | |||
| 96 | IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != 0); | ||
| 97 | IDA_BUG_ON(ida, ida_is_empty(ida)); | ||
| 98 | ida_free(ida, 0); | ||
| 99 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Check allocations up to and slightly above the maximum allowed (2^31-1) ID. | ||
| 104 | * Allocating up to 2^31-1 should succeed, and then allocating the next one | ||
| 105 | * should fail. | ||
| 106 | */ | ||
| 107 | static void ida_check_max(struct ida *ida) | ||
| 108 | { | ||
| 109 | unsigned long i, j; | ||
| 110 | |||
| 111 | for (j = 1; j < 65537; j *= 2) { | ||
| 112 | unsigned long base = (1UL << 31) - j; | ||
| 113 | for (i = 0; i < j; i++) { | ||
| 114 | IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) != | ||
| 115 | base + i); | ||
| 116 | } | ||
| 117 | IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) != | ||
| 118 | -ENOSPC); | ||
| 119 | ida_destroy(ida); | ||
| 120 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Check handling of conversions between exceptional entries and full bitmaps. | ||
| 126 | */ | ||
| 127 | static void ida_check_conv(struct ida *ida) | ||
| 128 | { | ||
| 129 | unsigned long i; | ||
| 130 | |||
| 131 | for (i = 0; i < IDA_BITMAP_BITS * 2; i += IDA_BITMAP_BITS) { | ||
| 132 | IDA_BUG_ON(ida, ida_alloc_min(ida, i + 1, GFP_KERNEL) != i + 1); | ||
| 133 | IDA_BUG_ON(ida, ida_alloc_min(ida, i + BITS_PER_LONG, | ||
| 134 | GFP_KERNEL) != i + BITS_PER_LONG); | ||
| 135 | ida_free(ida, i + 1); | ||
| 136 | ida_free(ida, i + BITS_PER_LONG); | ||
| 137 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 138 | } | ||
| 139 | |||
| 140 | for (i = 0; i < IDA_BITMAP_BITS * 2; i++) | ||
| 141 | IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != i); | ||
| 142 | for (i = IDA_BITMAP_BITS * 2; i > 0; i--) | ||
| 143 | ida_free(ida, i - 1); | ||
| 144 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 145 | |||
| 146 | for (i = 0; i < IDA_BITMAP_BITS + BITS_PER_LONG - 4; i++) | ||
| 147 | IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != i); | ||
| 148 | for (i = IDA_BITMAP_BITS + BITS_PER_LONG - 4; i > 0; i--) | ||
| 149 | ida_free(ida, i - 1); | ||
| 150 | IDA_BUG_ON(ida, !ida_is_empty(ida)); | ||
| 151 | } | ||
| 152 | |||
| 153 | static int ida_checks(void) | ||
| 154 | { | ||
| 155 | DEFINE_IDA(ida); | ||
| 156 | |||
| 157 | IDA_BUG_ON(&ida, !ida_is_empty(&ida)); | ||
| 158 | ida_check_alloc(&ida); | ||
| 159 | ida_check_destroy(&ida); | ||
| 160 | ida_check_leaf(&ida, 0); | ||
| 161 | ida_check_leaf(&ida, 1024); | ||
| 162 | ida_check_leaf(&ida, 1024 * 64); | ||
| 163 | ida_check_max(&ida); | ||
| 164 | ida_check_conv(&ida); | ||
| 165 | |||
| 166 | printk("IDA: %u of %u tests passed\n", tests_passed, tests_run); | ||
| 167 | return (tests_run != tests_passed) ? 0 : -EINVAL; | ||
| 168 | } | ||
| 169 | |||
| 170 | static void ida_exit(void) | ||
| 171 | { | ||
| 172 | } | ||
| 173 | |||
| 174 | module_init(ida_checks); | ||
| 175 | module_exit(ida_exit); | ||
| 176 | MODULE_AUTHOR("Matthew Wilcox <willy@infradead.org>"); | ||
| 177 | MODULE_LICENSE("GPL"); | ||
