diff options
Diffstat (limited to 'lib/test_xarray.c')
| -rw-r--r-- | lib/test_xarray.c | 288 |
1 files changed, 232 insertions, 56 deletions
diff --git a/lib/test_xarray.c b/lib/test_xarray.c index c596a957f764..5d4bad8bd96a 100644 --- a/lib/test_xarray.c +++ b/lib/test_xarray.c | |||
| @@ -40,9 +40,9 @@ static void *xa_store_index(struct xarray *xa, unsigned long index, gfp_t gfp) | |||
| 40 | 40 | ||
| 41 | static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp) | 41 | static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp) |
| 42 | { | 42 | { |
| 43 | u32 id = 0; | 43 | u32 id; |
| 44 | 44 | ||
| 45 | XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_index(index), | 45 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(index), xa_limit_32b, |
| 46 | gfp) != 0); | 46 | gfp) != 0); |
| 47 | XA_BUG_ON(xa, id != index); | 47 | XA_BUG_ON(xa, id != index); |
| 48 | } | 48 | } |
| @@ -107,8 +107,11 @@ static noinline void check_xas_retry(struct xarray *xa) | |||
| 107 | XA_BUG_ON(xa, xas.xa_node != XAS_RESTART); | 107 | XA_BUG_ON(xa, xas.xa_node != XAS_RESTART); |
| 108 | XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0)); | 108 | XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0)); |
| 109 | XA_BUG_ON(xa, xas.xa_node != NULL); | 109 | XA_BUG_ON(xa, xas.xa_node != NULL); |
| 110 | rcu_read_unlock(); | ||
| 110 | 111 | ||
| 111 | XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL); | 112 | XA_BUG_ON(xa, xa_store_index(xa, 1, GFP_KERNEL) != NULL); |
| 113 | |||
| 114 | rcu_read_lock(); | ||
| 112 | XA_BUG_ON(xa, !xa_is_internal(xas_reload(&xas))); | 115 | XA_BUG_ON(xa, !xa_is_internal(xas_reload(&xas))); |
| 113 | xas.xa_node = XAS_RESTART; | 116 | xas.xa_node = XAS_RESTART; |
| 114 | XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0)); | 117 | XA_BUG_ON(xa, xas_next_entry(&xas, ULONG_MAX) != xa_mk_value(0)); |
| @@ -343,7 +346,7 @@ static noinline void check_cmpxchg(struct xarray *xa) | |||
| 343 | 346 | ||
| 344 | XA_BUG_ON(xa, !xa_empty(xa)); | 347 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 345 | XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_KERNEL) != NULL); | 348 | XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_KERNEL) != NULL); |
| 346 | XA_BUG_ON(xa, xa_insert(xa, 12345678, xa, GFP_KERNEL) != -EEXIST); | 349 | XA_BUG_ON(xa, xa_insert(xa, 12345678, xa, GFP_KERNEL) != -EBUSY); |
| 347 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, SIX, FIVE, GFP_KERNEL) != LOTS); | 350 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, SIX, FIVE, GFP_KERNEL) != LOTS); |
| 348 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, LOTS, FIVE, GFP_KERNEL) != LOTS); | 351 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, LOTS, FIVE, GFP_KERNEL) != LOTS); |
| 349 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, FIVE, LOTS, GFP_KERNEL) != FIVE); | 352 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, FIVE, LOTS, GFP_KERNEL) != FIVE); |
| @@ -358,46 +361,65 @@ static noinline void check_reserve(struct xarray *xa) | |||
| 358 | { | 361 | { |
| 359 | void *entry; | 362 | void *entry; |
| 360 | unsigned long index; | 363 | unsigned long index; |
| 364 | int count; | ||
| 361 | 365 | ||
| 362 | /* An array with a reserved entry is not empty */ | 366 | /* An array with a reserved entry is not empty */ |
| 363 | XA_BUG_ON(xa, !xa_empty(xa)); | 367 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 364 | xa_reserve(xa, 12345678, GFP_KERNEL); | 368 | XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0); |
| 365 | XA_BUG_ON(xa, xa_empty(xa)); | 369 | XA_BUG_ON(xa, xa_empty(xa)); |
| 366 | XA_BUG_ON(xa, xa_load(xa, 12345678)); | 370 | XA_BUG_ON(xa, xa_load(xa, 12345678)); |
| 367 | xa_release(xa, 12345678); | 371 | xa_release(xa, 12345678); |
| 368 | XA_BUG_ON(xa, !xa_empty(xa)); | 372 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 369 | 373 | ||
| 370 | /* Releasing a used entry does nothing */ | 374 | /* Releasing a used entry does nothing */ |
| 371 | xa_reserve(xa, 12345678, GFP_KERNEL); | 375 | XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0); |
| 372 | XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_NOWAIT) != NULL); | 376 | XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_NOWAIT) != NULL); |
| 373 | xa_release(xa, 12345678); | 377 | xa_release(xa, 12345678); |
| 374 | xa_erase_index(xa, 12345678); | 378 | xa_erase_index(xa, 12345678); |
| 375 | XA_BUG_ON(xa, !xa_empty(xa)); | 379 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 376 | 380 | ||
| 377 | /* cmpxchg sees a reserved entry as NULL */ | 381 | /* cmpxchg sees a reserved entry as ZERO */ |
| 378 | xa_reserve(xa, 12345678, GFP_KERNEL); | 382 | XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0); |
| 379 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, NULL, xa_mk_value(12345678), | 383 | XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, XA_ZERO_ENTRY, |
| 380 | GFP_NOWAIT) != NULL); | 384 | xa_mk_value(12345678), GFP_NOWAIT) != NULL); |
| 381 | xa_release(xa, 12345678); | 385 | xa_release(xa, 12345678); |
| 382 | xa_erase_index(xa, 12345678); | 386 | xa_erase_index(xa, 12345678); |
| 383 | XA_BUG_ON(xa, !xa_empty(xa)); | 387 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 384 | 388 | ||
| 385 | /* But xa_insert does not */ | 389 | /* xa_insert treats it as busy */ |
| 386 | xa_reserve(xa, 12345678, GFP_KERNEL); | 390 | XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0); |
| 387 | XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != | 391 | XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != |
| 388 | -EEXIST); | 392 | -EBUSY); |
| 389 | XA_BUG_ON(xa, xa_empty(xa)); | 393 | XA_BUG_ON(xa, xa_empty(xa)); |
| 390 | XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL); | 394 | XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL); |
| 391 | XA_BUG_ON(xa, !xa_empty(xa)); | 395 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 392 | 396 | ||
| 393 | /* Can iterate through a reserved entry */ | 397 | /* Can iterate through a reserved entry */ |
| 394 | xa_store_index(xa, 5, GFP_KERNEL); | 398 | xa_store_index(xa, 5, GFP_KERNEL); |
| 395 | xa_reserve(xa, 6, GFP_KERNEL); | 399 | XA_BUG_ON(xa, xa_reserve(xa, 6, GFP_KERNEL) != 0); |
| 396 | xa_store_index(xa, 7, GFP_KERNEL); | 400 | xa_store_index(xa, 7, GFP_KERNEL); |
| 397 | 401 | ||
| 402 | count = 0; | ||
| 398 | xa_for_each(xa, index, entry) { | 403 | xa_for_each(xa, index, entry) { |
| 399 | XA_BUG_ON(xa, index != 5 && index != 7); | 404 | XA_BUG_ON(xa, index != 5 && index != 7); |
| 405 | count++; | ||
| 406 | } | ||
| 407 | XA_BUG_ON(xa, count != 2); | ||
| 408 | |||
| 409 | /* If we free a reserved entry, we should be able to allocate it */ | ||
| 410 | if (xa->xa_flags & XA_FLAGS_ALLOC) { | ||
| 411 | u32 id; | ||
| 412 | |||
| 413 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_value(8), | ||
| 414 | XA_LIMIT(5, 10), GFP_KERNEL) != 0); | ||
| 415 | XA_BUG_ON(xa, id != 8); | ||
| 416 | |||
| 417 | xa_release(xa, 6); | ||
| 418 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_value(6), | ||
| 419 | XA_LIMIT(5, 10), GFP_KERNEL) != 0); | ||
| 420 | XA_BUG_ON(xa, id != 6); | ||
| 400 | } | 421 | } |
| 422 | |||
| 401 | xa_destroy(xa); | 423 | xa_destroy(xa); |
| 402 | } | 424 | } |
| 403 | 425 | ||
| @@ -586,64 +608,194 @@ static noinline void check_multi_store(struct xarray *xa) | |||
| 586 | #endif | 608 | #endif |
| 587 | } | 609 | } |
| 588 | 610 | ||
| 589 | static DEFINE_XARRAY_ALLOC(xa0); | 611 | static noinline void check_xa_alloc_1(struct xarray *xa, unsigned int base) |
| 590 | |||
| 591 | static noinline void check_xa_alloc(void) | ||
| 592 | { | 612 | { |
| 593 | int i; | 613 | int i; |
| 594 | u32 id; | 614 | u32 id; |
| 595 | 615 | ||
| 596 | /* An empty array should assign 0 to the first alloc */ | 616 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 597 | xa_alloc_index(&xa0, 0, GFP_KERNEL); | 617 | /* An empty array should assign %base to the first alloc */ |
| 618 | xa_alloc_index(xa, base, GFP_KERNEL); | ||
| 598 | 619 | ||
| 599 | /* Erasing it should make the array empty again */ | 620 | /* Erasing it should make the array empty again */ |
| 600 | xa_erase_index(&xa0, 0); | 621 | xa_erase_index(xa, base); |
| 601 | XA_BUG_ON(&xa0, !xa_empty(&xa0)); | 622 | XA_BUG_ON(xa, !xa_empty(xa)); |
| 623 | |||
| 624 | /* And it should assign %base again */ | ||
| 625 | xa_alloc_index(xa, base, GFP_KERNEL); | ||
| 626 | |||
| 627 | /* Allocating and then erasing a lot should not lose base */ | ||
| 628 | for (i = base + 1; i < 2 * XA_CHUNK_SIZE; i++) | ||
| 629 | xa_alloc_index(xa, i, GFP_KERNEL); | ||
| 630 | for (i = base; i < 2 * XA_CHUNK_SIZE; i++) | ||
| 631 | xa_erase_index(xa, i); | ||
| 632 | xa_alloc_index(xa, base, GFP_KERNEL); | ||
| 602 | 633 | ||
| 603 | /* And it should assign 0 again */ | 634 | /* Destroying the array should do the same as erasing */ |
| 604 | xa_alloc_index(&xa0, 0, GFP_KERNEL); | 635 | xa_destroy(xa); |
| 636 | |||
| 637 | /* And it should assign %base again */ | ||
| 638 | xa_alloc_index(xa, base, GFP_KERNEL); | ||
| 605 | 639 | ||
| 606 | /* The next assigned ID should be 1 */ | 640 | /* The next assigned ID should be base+1 */ |
| 607 | xa_alloc_index(&xa0, 1, GFP_KERNEL); | 641 | xa_alloc_index(xa, base + 1, GFP_KERNEL); |
| 608 | xa_erase_index(&xa0, 1); | 642 | xa_erase_index(xa, base + 1); |
| 609 | 643 | ||
| 610 | /* Storing a value should mark it used */ | 644 | /* Storing a value should mark it used */ |
| 611 | xa_store_index(&xa0, 1, GFP_KERNEL); | 645 | xa_store_index(xa, base + 1, GFP_KERNEL); |
| 612 | xa_alloc_index(&xa0, 2, GFP_KERNEL); | 646 | xa_alloc_index(xa, base + 2, GFP_KERNEL); |
| 613 | 647 | ||
| 614 | /* If we then erase 0, it should be free */ | 648 | /* If we then erase base, it should be free */ |
| 615 | xa_erase_index(&xa0, 0); | 649 | xa_erase_index(xa, base); |
| 616 | xa_alloc_index(&xa0, 0, GFP_KERNEL); | 650 | xa_alloc_index(xa, base, GFP_KERNEL); |
| 617 | 651 | ||
| 618 | xa_erase_index(&xa0, 1); | 652 | xa_erase_index(xa, base + 1); |
| 619 | xa_erase_index(&xa0, 2); | 653 | xa_erase_index(xa, base + 2); |
| 620 | 654 | ||
| 621 | for (i = 1; i < 5000; i++) { | 655 | for (i = 1; i < 5000; i++) { |
| 622 | xa_alloc_index(&xa0, i, GFP_KERNEL); | 656 | xa_alloc_index(xa, base + i, GFP_KERNEL); |
| 623 | } | 657 | } |
| 624 | 658 | ||
| 625 | xa_destroy(&xa0); | 659 | xa_destroy(xa); |
| 626 | 660 | ||
| 627 | id = 0xfffffffeU; | 661 | /* Check that we fail properly at the limit of allocation */ |
| 628 | XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id), | 662 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(UINT_MAX - 1), |
| 663 | XA_LIMIT(UINT_MAX - 1, UINT_MAX), | ||
| 629 | GFP_KERNEL) != 0); | 664 | GFP_KERNEL) != 0); |
| 630 | XA_BUG_ON(&xa0, id != 0xfffffffeU); | 665 | XA_BUG_ON(xa, id != 0xfffffffeU); |
| 631 | XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id), | 666 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(UINT_MAX), |
| 667 | XA_LIMIT(UINT_MAX - 1, UINT_MAX), | ||
| 632 | GFP_KERNEL) != 0); | 668 | GFP_KERNEL) != 0); |
| 633 | XA_BUG_ON(&xa0, id != 0xffffffffU); | 669 | XA_BUG_ON(xa, id != 0xffffffffU); |
| 634 | XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id), | 670 | id = 3; |
| 635 | GFP_KERNEL) != -ENOSPC); | 671 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(0), |
| 636 | XA_BUG_ON(&xa0, id != 0xffffffffU); | 672 | XA_LIMIT(UINT_MAX - 1, UINT_MAX), |
| 637 | xa_destroy(&xa0); | 673 | GFP_KERNEL) != -EBUSY); |
| 638 | 674 | XA_BUG_ON(xa, id != 3); | |
| 639 | id = 10; | 675 | xa_destroy(xa); |
| 640 | XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id), | 676 | |
| 641 | GFP_KERNEL) != -ENOSPC); | 677 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(10), XA_LIMIT(10, 5), |
| 642 | XA_BUG_ON(&xa0, xa_store_index(&xa0, 3, GFP_KERNEL) != 0); | 678 | GFP_KERNEL) != -EBUSY); |
| 643 | XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id), | 679 | XA_BUG_ON(xa, xa_store_index(xa, 3, GFP_KERNEL) != 0); |
| 644 | GFP_KERNEL) != -ENOSPC); | 680 | XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_index(10), XA_LIMIT(10, 5), |
| 645 | xa_erase_index(&xa0, 3); | 681 | GFP_KERNEL) != -EBUSY); |
| 646 | XA_BUG_ON(&xa0, !xa_empty(&xa0)); | 682 | xa_erase_index(xa, 3); |
| 683 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 684 | } | ||
| 685 | |||
| 686 | static noinline void check_xa_alloc_2(struct xarray *xa, unsigned int base) | ||
| 687 | { | ||
| 688 | unsigned int i, id; | ||
| 689 | unsigned long index; | ||
| 690 | void *entry; | ||
| 691 | |||
| 692 | /* Allocate and free a NULL and check xa_empty() behaves */ | ||
| 693 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 694 | XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b, GFP_KERNEL) != 0); | ||
| 695 | XA_BUG_ON(xa, id != base); | ||
| 696 | XA_BUG_ON(xa, xa_empty(xa)); | ||
| 697 | XA_BUG_ON(xa, xa_erase(xa, id) != NULL); | ||
| 698 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 699 | |||
| 700 | /* Ditto, but check destroy instead of erase */ | ||
| 701 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 702 | XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b, GFP_KERNEL) != 0); | ||
| 703 | XA_BUG_ON(xa, id != base); | ||
| 704 | XA_BUG_ON(xa, xa_empty(xa)); | ||
| 705 | xa_destroy(xa); | ||
| 706 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 707 | |||
| 708 | for (i = base; i < base + 10; i++) { | ||
| 709 | XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b, | ||
| 710 | GFP_KERNEL) != 0); | ||
| 711 | XA_BUG_ON(xa, id != i); | ||
| 712 | } | ||
| 713 | |||
| 714 | XA_BUG_ON(xa, xa_store(xa, 3, xa_mk_index(3), GFP_KERNEL) != NULL); | ||
| 715 | XA_BUG_ON(xa, xa_store(xa, 4, xa_mk_index(4), GFP_KERNEL) != NULL); | ||
| 716 | XA_BUG_ON(xa, xa_store(xa, 4, NULL, GFP_KERNEL) != xa_mk_index(4)); | ||
| 717 | XA_BUG_ON(xa, xa_erase(xa, 5) != NULL); | ||
| 718 | XA_BUG_ON(xa, xa_alloc(xa, &id, NULL, xa_limit_32b, GFP_KERNEL) != 0); | ||
| 719 | XA_BUG_ON(xa, id != 5); | ||
| 720 | |||
| 721 | xa_for_each(xa, index, entry) { | ||
| 722 | xa_erase_index(xa, index); | ||
| 723 | } | ||
| 724 | |||
| 725 | for (i = base; i < base + 9; i++) { | ||
| 726 | XA_BUG_ON(xa, xa_erase(xa, i) != NULL); | ||
| 727 | XA_BUG_ON(xa, xa_empty(xa)); | ||
| 728 | } | ||
| 729 | XA_BUG_ON(xa, xa_erase(xa, 8) != NULL); | ||
| 730 | XA_BUG_ON(xa, xa_empty(xa)); | ||
| 731 | XA_BUG_ON(xa, xa_erase(xa, base + 9) != NULL); | ||
| 732 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 733 | |||
| 734 | xa_destroy(xa); | ||
| 735 | } | ||
| 736 | |||
| 737 | static noinline void check_xa_alloc_3(struct xarray *xa, unsigned int base) | ||
| 738 | { | ||
| 739 | struct xa_limit limit = XA_LIMIT(1, 0x3fff); | ||
| 740 | u32 next = 0; | ||
| 741 | unsigned int i, id; | ||
| 742 | unsigned long index; | ||
| 743 | void *entry; | ||
| 744 | |||
| 745 | XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(1), limit, | ||
| 746 | &next, GFP_KERNEL) != 0); | ||
| 747 | XA_BUG_ON(xa, id != 1); | ||
| 748 | |||
| 749 | next = 0x3ffd; | ||
| 750 | XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(0x3ffd), limit, | ||
| 751 | &next, GFP_KERNEL) != 0); | ||
| 752 | XA_BUG_ON(xa, id != 0x3ffd); | ||
| 753 | xa_erase_index(xa, 0x3ffd); | ||
| 754 | xa_erase_index(xa, 1); | ||
| 755 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 756 | |||
| 757 | for (i = 0x3ffe; i < 0x4003; i++) { | ||
| 758 | if (i < 0x4000) | ||
| 759 | entry = xa_mk_index(i); | ||
| 760 | else | ||
| 761 | entry = xa_mk_index(i - 0x3fff); | ||
| 762 | XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, entry, limit, | ||
| 763 | &next, GFP_KERNEL) != (id == 1)); | ||
| 764 | XA_BUG_ON(xa, xa_mk_index(id) != entry); | ||
| 765 | } | ||
| 766 | |||
| 767 | /* Check wrap-around is handled correctly */ | ||
| 768 | if (base != 0) | ||
| 769 | xa_erase_index(xa, base); | ||
| 770 | xa_erase_index(xa, base + 1); | ||
| 771 | next = UINT_MAX; | ||
| 772 | XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(UINT_MAX), | ||
| 773 | xa_limit_32b, &next, GFP_KERNEL) != 0); | ||
| 774 | XA_BUG_ON(xa, id != UINT_MAX); | ||
| 775 | XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(base), | ||
| 776 | xa_limit_32b, &next, GFP_KERNEL) != 1); | ||
| 777 | XA_BUG_ON(xa, id != base); | ||
| 778 | XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(base + 1), | ||
| 779 | xa_limit_32b, &next, GFP_KERNEL) != 0); | ||
| 780 | XA_BUG_ON(xa, id != base + 1); | ||
| 781 | |||
| 782 | xa_for_each(xa, index, entry) | ||
| 783 | xa_erase_index(xa, index); | ||
| 784 | |||
| 785 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 786 | } | ||
| 787 | |||
| 788 | static DEFINE_XARRAY_ALLOC(xa0); | ||
| 789 | static DEFINE_XARRAY_ALLOC1(xa1); | ||
| 790 | |||
| 791 | static noinline void check_xa_alloc(void) | ||
| 792 | { | ||
| 793 | check_xa_alloc_1(&xa0, 0); | ||
| 794 | check_xa_alloc_1(&xa1, 1); | ||
| 795 | check_xa_alloc_2(&xa0, 0); | ||
| 796 | check_xa_alloc_2(&xa1, 1); | ||
| 797 | check_xa_alloc_3(&xa0, 0); | ||
| 798 | check_xa_alloc_3(&xa1, 1); | ||
| 647 | } | 799 | } |
| 648 | 800 | ||
| 649 | static noinline void __check_store_iter(struct xarray *xa, unsigned long start, | 801 | static noinline void __check_store_iter(struct xarray *xa, unsigned long start, |
| @@ -1194,9 +1346,8 @@ static void check_align_1(struct xarray *xa, char *name) | |||
| 1194 | void *entry; | 1346 | void *entry; |
| 1195 | 1347 | ||
| 1196 | for (i = 0; i < 8; i++) { | 1348 | for (i = 0; i < 8; i++) { |
| 1197 | id = 0; | 1349 | XA_BUG_ON(xa, xa_alloc(xa, &id, name + i, xa_limit_32b, |
| 1198 | XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, name + i, GFP_KERNEL) | 1350 | GFP_KERNEL) != 0); |
| 1199 | != 0); | ||
| 1200 | XA_BUG_ON(xa, id != i); | 1351 | XA_BUG_ON(xa, id != i); |
| 1201 | } | 1352 | } |
| 1202 | xa_for_each(xa, index, entry) | 1353 | xa_for_each(xa, index, entry) |
| @@ -1204,6 +1355,30 @@ static void check_align_1(struct xarray *xa, char *name) | |||
| 1204 | xa_destroy(xa); | 1355 | xa_destroy(xa); |
| 1205 | } | 1356 | } |
| 1206 | 1357 | ||
| 1358 | /* | ||
| 1359 | * We should always be able to store without allocating memory after | ||
| 1360 | * reserving a slot. | ||
| 1361 | */ | ||
| 1362 | static void check_align_2(struct xarray *xa, char *name) | ||
| 1363 | { | ||
| 1364 | int i; | ||
| 1365 | |||
| 1366 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 1367 | |||
| 1368 | for (i = 0; i < 8; i++) { | ||
| 1369 | XA_BUG_ON(xa, xa_store(xa, 0, name + i, GFP_KERNEL) != NULL); | ||
| 1370 | xa_erase(xa, 0); | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | for (i = 0; i < 8; i++) { | ||
| 1374 | XA_BUG_ON(xa, xa_reserve(xa, 0, GFP_KERNEL) != 0); | ||
| 1375 | XA_BUG_ON(xa, xa_store(xa, 0, name + i, 0) != NULL); | ||
| 1376 | xa_erase(xa, 0); | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | XA_BUG_ON(xa, !xa_empty(xa)); | ||
| 1380 | } | ||
| 1381 | |||
| 1207 | static noinline void check_align(struct xarray *xa) | 1382 | static noinline void check_align(struct xarray *xa) |
| 1208 | { | 1383 | { |
| 1209 | char name[] = "Motorola 68000"; | 1384 | char name[] = "Motorola 68000"; |
| @@ -1212,7 +1387,7 @@ static noinline void check_align(struct xarray *xa) | |||
| 1212 | check_align_1(xa, name + 1); | 1387 | check_align_1(xa, name + 1); |
| 1213 | check_align_1(xa, name + 2); | 1388 | check_align_1(xa, name + 2); |
| 1214 | check_align_1(xa, name + 3); | 1389 | check_align_1(xa, name + 3); |
| 1215 | // check_align_2(xa, name); | 1390 | check_align_2(xa, name); |
| 1216 | } | 1391 | } |
| 1217 | 1392 | ||
| 1218 | static LIST_HEAD(shadow_nodes); | 1393 | static LIST_HEAD(shadow_nodes); |
| @@ -1354,6 +1529,7 @@ static int xarray_checks(void) | |||
| 1354 | check_xas_erase(&array); | 1529 | check_xas_erase(&array); |
| 1355 | check_cmpxchg(&array); | 1530 | check_cmpxchg(&array); |
| 1356 | check_reserve(&array); | 1531 | check_reserve(&array); |
| 1532 | check_reserve(&xa0); | ||
| 1357 | check_multi_store(&array); | 1533 | check_multi_store(&array); |
| 1358 | check_xa_alloc(); | 1534 | check_xa_alloc(); |
| 1359 | check_find(&array); | 1535 | check_find(&array); |
