Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'xarray-4.20-rc7' of git://git.infradead.org/users/willy/linux-dax

Pull XArray fixes from Matthew Wilcox:
"Two bugfixes, each with test-suite updates, two improvements to the
test-suite without associated bugs, and one patch adding a missing
API"

* tag 'xarray-4.20-rc7' of git://git.infradead.org/users/willy/linux-dax:
XArray: Fix xa_alloc when id exceeds max
XArray tests: Check iterating over multiorder entries
XArray tests: Handle larger indices more elegantly
XArray: Add xa_cmpxchg_irq and xa_cmpxchg_bh
radix tree: Don't return retry entries from lookup

+258 -54
+4 -1
Documentation/core-api/xarray.rst
··· 187 187 * :c:func:`xa_erase_bh` 188 188 * :c:func:`xa_erase_irq` 189 189 * :c:func:`xa_cmpxchg` 190 + * :c:func:`xa_cmpxchg_bh` 191 + * :c:func:`xa_cmpxchg_irq` 190 192 * :c:func:`xa_store_range` 191 193 * :c:func:`xa_alloc` 192 194 * :c:func:`xa_alloc_bh` ··· 265 263 context, or :c:func:`xa_lock_irq` in process context and :c:func:`xa_lock` 266 264 in the interrupt handler. Some of the more common patterns have helper 267 265 functions such as :c:func:`xa_store_bh`, :c:func:`xa_store_irq`, 268 - :c:func:`xa_erase_bh` and :c:func:`xa_erase_irq`. 266 + :c:func:`xa_erase_bh`, :c:func:`xa_erase_irq`, :c:func:`xa_cmpxchg_bh` 267 + and :c:func:`xa_cmpxchg_irq`. 269 268 270 269 Sometimes you need to protect access to the XArray with a mutex because 271 270 that lock sits above another mutex in the locking hierarchy. That does
+54
include/linux/xarray.h
··· 554 554 } 555 555 556 556 /** 557 + * xa_cmpxchg_bh() - Conditionally replace an entry in the XArray. 558 + * @xa: XArray. 559 + * @index: Index into array. 560 + * @old: Old value to test against. 561 + * @entry: New value to place in array. 562 + * @gfp: Memory allocation flags. 563 + * 564 + * This function is like calling xa_cmpxchg() except it disables softirqs 565 + * while holding the array lock. 566 + * 567 + * Context: Any context. Takes and releases the xa_lock while 568 + * disabling softirqs. May sleep if the @gfp flags permit. 569 + * Return: The old value at this index or xa_err() if an error happened. 570 + */ 571 + static inline void *xa_cmpxchg_bh(struct xarray *xa, unsigned long index, 572 + void *old, void *entry, gfp_t gfp) 573 + { 574 + void *curr; 575 + 576 + xa_lock_bh(xa); 577 + curr = __xa_cmpxchg(xa, index, old, entry, gfp); 578 + xa_unlock_bh(xa); 579 + 580 + return curr; 581 + } 582 + 583 + /** 584 + * xa_cmpxchg_irq() - Conditionally replace an entry in the XArray. 585 + * @xa: XArray. 586 + * @index: Index into array. 587 + * @old: Old value to test against. 588 + * @entry: New value to place in array. 589 + * @gfp: Memory allocation flags. 590 + * 591 + * This function is like calling xa_cmpxchg() except it disables interrupts 592 + * while holding the array lock. 593 + * 594 + * Context: Process context. Takes and releases the xa_lock while 595 + * disabling interrupts. May sleep if the @gfp flags permit. 596 + * Return: The old value at this index or xa_err() if an error happened. 597 + */ 598 + static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index, 599 + void *old, void *entry, gfp_t gfp) 600 + { 601 + void *curr; 602 + 603 + xa_lock_irq(xa); 604 + curr = __xa_cmpxchg(xa, index, old, entry, gfp); 605 + xa_unlock_irq(xa); 606 + 607 + return curr; 608 + } 609 + 610 + /** 557 611 * xa_insert() - Store this entry in the XArray unless another entry is 558 612 * already present. 559 613 * @xa: XArray.
+2 -2
lib/radix-tree.c
··· 784 784 while (radix_tree_is_internal_node(node)) { 785 785 unsigned offset; 786 786 787 - if (node == RADIX_TREE_RETRY) 788 - goto restart; 789 787 parent = entry_to_node(node); 790 788 offset = radix_tree_descend(parent, &node, index); 791 789 slot = parent->slots + offset; 790 + if (node == RADIX_TREE_RETRY) 791 + goto restart; 792 792 if (parent->shift == 0) 793 793 break; 794 794 }
+112 -43
lib/test_xarray.c
··· 28 28 } while (0) 29 29 #endif 30 30 31 + static void *xa_mk_index(unsigned long index) 32 + { 33 + return xa_mk_value(index & LONG_MAX); 34 + } 35 + 31 36 static void *xa_store_index(struct xarray *xa, unsigned long index, gfp_t gfp) 32 37 { 33 - return xa_store(xa, index, xa_mk_value(index & LONG_MAX), gfp); 38 + return xa_store(xa, index, xa_mk_index(index), gfp); 34 39 } 35 40 36 41 static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp) 37 42 { 38 43 u32 id = 0; 39 44 40 - XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_value(index & LONG_MAX), 45 + XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, xa_mk_index(index), 41 46 gfp) != 0); 42 47 XA_BUG_ON(xa, id != index); 43 48 } 44 49 45 50 static void xa_erase_index(struct xarray *xa, unsigned long index) 46 51 { 47 - XA_BUG_ON(xa, xa_erase(xa, index) != xa_mk_value(index & LONG_MAX)); 52 + XA_BUG_ON(xa, xa_erase(xa, index) != xa_mk_index(index)); 48 53 XA_BUG_ON(xa, xa_load(xa, index) != NULL); 49 54 } 50 55 ··· 123 118 124 119 xas_set(&xas, 0); 125 120 xas_for_each(&xas, entry, ULONG_MAX) { 126 - xas_store(&xas, xa_mk_value(xas.xa_index)); 121 + xas_store(&xas, xa_mk_index(xas.xa_index)); 127 122 } 128 123 xas_unlock(&xas); 129 124 ··· 201 196 XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL)); 202 197 xa_set_mark(xa, index + 2, XA_MARK_1); 203 198 XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL)); 204 - xa_store_order(xa, index, order, xa_mk_value(index), 199 + xa_store_order(xa, index, order, xa_mk_index(index), 205 200 GFP_KERNEL); 206 201 for (i = base; i < next; i++) { 207 202 XA_STATE(xas, xa, i); ··· 410 405 xas_set(&xas, j); 411 406 do { 412 407 xas_lock(&xas); 413 - xas_store(&xas, xa_mk_value(j)); 408 + xas_store(&xas, xa_mk_index(j)); 414 409 xas_unlock(&xas); 415 410 } while (xas_nomem(&xas, GFP_KERNEL)); 416 411 } ··· 428 423 xas_set(&xas, 0); 429 424 j = i; 430 425 xas_for_each(&xas, entry, ULONG_MAX) { 431 - XA_BUG_ON(xa, entry != xa_mk_value(j)); 426 + XA_BUG_ON(xa, entry != xa_mk_index(j)); 432 427 xas_store(&xas, NULL); 433 428 j++; 434 429 } ··· 445 440 unsigned long min = index & ~((1UL << order) - 1); 446 441 unsigned long max = min + (1UL << order); 447 442 448 - xa_store_order(xa, index, order, xa_mk_value(index), GFP_KERNEL); 449 - XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_value(index)); 450 - XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_value(index)); 443 + xa_store_order(xa, index, order, xa_mk_index(index), GFP_KERNEL); 444 + XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_index(index)); 445 + XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_index(index)); 451 446 XA_BUG_ON(xa, xa_load(xa, max) != NULL); 452 447 XA_BUG_ON(xa, xa_load(xa, min - 1) != NULL); 453 448 454 449 xas_lock(&xas); 455 - XA_BUG_ON(xa, xas_store(&xas, xa_mk_value(min)) != xa_mk_value(index)); 450 + XA_BUG_ON(xa, xas_store(&xas, xa_mk_index(min)) != xa_mk_index(index)); 456 451 xas_unlock(&xas); 457 - XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_value(min)); 458 - XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_value(min)); 452 + XA_BUG_ON(xa, xa_load(xa, min) != xa_mk_index(min)); 453 + XA_BUG_ON(xa, xa_load(xa, max - 1) != xa_mk_index(min)); 459 454 XA_BUG_ON(xa, xa_load(xa, max) != NULL); 460 455 XA_BUG_ON(xa, xa_load(xa, min - 1) != NULL); 461 456 ··· 475 470 XA_BUG_ON(xa, xas_store(&xas, NULL) != xa_mk_value(1)); 476 471 xas_unlock(&xas); 477 472 XA_BUG_ON(xa, !xa_empty(xa)); 473 + } 474 + 475 + static noinline void check_multi_store_3(struct xarray *xa, unsigned long index, 476 + unsigned int order) 477 + { 478 + XA_STATE(xas, xa, 0); 479 + void *entry; 480 + int n = 0; 481 + 482 + xa_store_order(xa, index, order, xa_mk_index(index), GFP_KERNEL); 483 + 484 + xas_lock(&xas); 485 + xas_for_each(&xas, entry, ULONG_MAX) { 486 + XA_BUG_ON(xa, entry != xa_mk_index(index)); 487 + n++; 488 + } 489 + XA_BUG_ON(xa, n != 1); 490 + xas_set(&xas, index + 1); 491 + xas_for_each(&xas, entry, ULONG_MAX) { 492 + XA_BUG_ON(xa, entry != xa_mk_index(index)); 493 + n++; 494 + } 495 + XA_BUG_ON(xa, n != 2); 496 + xas_unlock(&xas); 497 + 498 + xa_destroy(xa); 478 499 } 479 500 #endif 480 501 ··· 554 523 555 524 for (i = 0; i < max_order; i++) { 556 525 for (j = 0; j < max_order; j++) { 557 - xa_store_order(xa, 0, i, xa_mk_value(i), GFP_KERNEL); 558 - xa_store_order(xa, 0, j, xa_mk_value(j), GFP_KERNEL); 526 + xa_store_order(xa, 0, i, xa_mk_index(i), GFP_KERNEL); 527 + xa_store_order(xa, 0, j, xa_mk_index(j), GFP_KERNEL); 559 528 560 529 for (k = 0; k < max_order; k++) { 561 530 void *entry = xa_load(xa, (1UL << k) - 1); 562 531 if ((i < k) && (j < k)) 563 532 XA_BUG_ON(xa, entry != NULL); 564 533 else 565 - XA_BUG_ON(xa, entry != xa_mk_value(j)); 534 + XA_BUG_ON(xa, entry != xa_mk_index(j)); 566 535 } 567 536 568 537 xa_erase(xa, 0); ··· 576 545 check_multi_store_1(xa, (1UL << i) + 1, i); 577 546 } 578 547 check_multi_store_2(xa, 4095, 9); 548 + 549 + for (i = 1; i < 20; i++) { 550 + check_multi_store_3(xa, 0, i); 551 + check_multi_store_3(xa, 1UL << i, i); 552 + } 579 553 #endif 580 554 } 581 555 ··· 623 587 xa_destroy(&xa0); 624 588 625 589 id = 0xfffffffeU; 626 - XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0), 590 + XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id), 627 591 GFP_KERNEL) != 0); 628 592 XA_BUG_ON(&xa0, id != 0xfffffffeU); 629 - XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0), 593 + XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id), 630 594 GFP_KERNEL) != 0); 631 595 XA_BUG_ON(&xa0, id != 0xffffffffU); 632 - XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_value(0), 596 + XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, UINT_MAX, xa_mk_index(id), 633 597 GFP_KERNEL) != -ENOSPC); 634 598 XA_BUG_ON(&xa0, id != 0xffffffffU); 635 599 xa_destroy(&xa0); 600 + 601 + id = 10; 602 + XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id), 603 + GFP_KERNEL) != -ENOSPC); 604 + XA_BUG_ON(&xa0, xa_store_index(&xa0, 3, GFP_KERNEL) != 0); 605 + XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id), 606 + GFP_KERNEL) != -ENOSPC); 607 + xa_erase_index(&xa0, 3); 608 + XA_BUG_ON(&xa0, !xa_empty(&xa0)); 636 609 } 637 610 638 611 static noinline void __check_store_iter(struct xarray *xa, unsigned long start, ··· 655 610 xas_lock(&xas); 656 611 xas_for_each_conflict(&xas, entry) { 657 612 XA_BUG_ON(xa, !xa_is_value(entry)); 658 - XA_BUG_ON(xa, entry < xa_mk_value(start)); 659 - XA_BUG_ON(xa, entry > xa_mk_value(start + (1UL << order) - 1)); 613 + XA_BUG_ON(xa, entry < xa_mk_index(start)); 614 + XA_BUG_ON(xa, entry > xa_mk_index(start + (1UL << order) - 1)); 660 615 count++; 661 616 } 662 - xas_store(&xas, xa_mk_value(start)); 617 + xas_store(&xas, xa_mk_index(start)); 663 618 xas_unlock(&xas); 664 619 if (xas_nomem(&xas, GFP_KERNEL)) { 665 620 count = 0; ··· 667 622 } 668 623 XA_BUG_ON(xa, xas_error(&xas)); 669 624 XA_BUG_ON(xa, count != present); 670 - XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_value(start)); 625 + XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_index(start)); 671 626 XA_BUG_ON(xa, xa_load(xa, start + (1UL << order) - 1) != 672 - xa_mk_value(start)); 627 + xa_mk_index(start)); 673 628 xa_erase_index(xa, start); 674 629 } 675 630 ··· 748 703 for (j = 0; j < index; j++) { 749 704 XA_STATE(xas, xa, j + index); 750 705 xa_store_index(xa, index - 1, GFP_KERNEL); 751 - xa_store_order(xa, index, i, xa_mk_value(index), 706 + xa_store_order(xa, index, i, xa_mk_index(index), 752 707 GFP_KERNEL); 753 708 rcu_read_lock(); 754 709 xas_for_each(&xas, entry, ULONG_MAX) { ··· 823 778 j = 0; 824 779 index = 0; 825 780 xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) { 826 - XA_BUG_ON(xa, xa_mk_value(index) != entry); 781 + XA_BUG_ON(xa, xa_mk_index(index) != entry); 827 782 XA_BUG_ON(xa, index != j++); 828 783 } 829 784 } ··· 831 786 xa_destroy(xa); 832 787 } 833 788 789 + static noinline void check_find_3(struct xarray *xa) 790 + { 791 + XA_STATE(xas, xa, 0); 792 + unsigned long i, j, k; 793 + void *entry; 794 + 795 + for (i = 0; i < 100; i++) { 796 + for (j = 0; j < 100; j++) { 797 + for (k = 0; k < 100; k++) { 798 + xas_set(&xas, j); 799 + xas_for_each_marked(&xas, entry, k, XA_MARK_0) 800 + ; 801 + if (j > k) 802 + XA_BUG_ON(xa, 803 + xas.xa_node != XAS_RESTART); 804 + } 805 + } 806 + xa_store_index(xa, i, GFP_KERNEL); 807 + xa_set_mark(xa, i, XA_MARK_0); 808 + } 809 + xa_destroy(xa); 810 + } 811 + 834 812 static noinline void check_find(struct xarray *xa) 835 813 { 836 814 check_find_1(xa); 837 815 check_find_2(xa); 816 + check_find_3(xa); 838 817 check_multi_find(xa); 839 818 check_multi_find_2(xa); 840 819 } ··· 898 829 for (index = 0; index < (1UL << (order + 5)); 899 830 index += (1UL << order)) { 900 831 xa_store_order(xa, index, order, 901 - xa_mk_value(index), GFP_KERNEL); 832 + xa_mk_index(index), GFP_KERNEL); 902 833 XA_BUG_ON(xa, xa_load(xa, index) != 903 - xa_mk_value(index)); 834 + xa_mk_index(index)); 904 835 XA_BUG_ON(xa, xa_find_entry(xa, 905 - xa_mk_value(index)) != index); 836 + xa_mk_index(index)) != index); 906 837 } 907 838 XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1); 908 839 xa_destroy(xa); ··· 913 844 XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1); 914 845 xa_store_index(xa, ULONG_MAX, GFP_KERNEL); 915 846 XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1); 916 - XA_BUG_ON(xa, xa_find_entry(xa, xa_mk_value(LONG_MAX)) != -1); 847 + XA_BUG_ON(xa, xa_find_entry(xa, xa_mk_index(ULONG_MAX)) != -1); 917 848 xa_erase_index(xa, ULONG_MAX); 918 849 XA_BUG_ON(xa, !xa_empty(xa)); 919 850 } ··· 933 864 XA_BUG_ON(xa, xas.xa_node == XAS_RESTART); 934 865 XA_BUG_ON(xa, xas.xa_index != i); 935 866 if (i == 0 || i == idx) 936 - XA_BUG_ON(xa, entry != xa_mk_value(i)); 867 + XA_BUG_ON(xa, entry != xa_mk_index(i)); 937 868 else 938 869 XA_BUG_ON(xa, entry != NULL); 939 870 } ··· 947 878 XA_BUG_ON(xa, xas.xa_node == XAS_RESTART); 948 879 XA_BUG_ON(xa, xas.xa_index != i); 949 880 if (i == 0 || i == idx) 950 - XA_BUG_ON(xa, entry != xa_mk_value(i)); 881 + XA_BUG_ON(xa, entry != xa_mk_index(i)); 951 882 else 952 883 XA_BUG_ON(xa, entry != NULL); 953 884 } while (i > 0); ··· 978 909 do { 979 910 void *entry = xas_prev(&xas); 980 911 i--; 981 - XA_BUG_ON(xa, entry != xa_mk_value(i)); 912 + XA_BUG_ON(xa, entry != xa_mk_index(i)); 982 913 XA_BUG_ON(xa, i != xas.xa_index); 983 914 } while (i != 0); 984 915 ··· 987 918 988 919 do { 989 920 void *entry = xas_next(&xas); 990 - XA_BUG_ON(xa, entry != xa_mk_value(i)); 921 + XA_BUG_ON(xa, entry != xa_mk_index(i)); 991 922 XA_BUG_ON(xa, i != xas.xa_index); 992 923 i++; 993 924 } while (i < (1 << 16)); ··· 1003 934 void *entry = xas_prev(&xas); 1004 935 i--; 1005 936 if ((i < (1 << 8)) || (i >= (1 << 15))) 1006 - XA_BUG_ON(xa, entry != xa_mk_value(i)); 937 + XA_BUG_ON(xa, entry != xa_mk_index(i)); 1007 938 else 1008 939 XA_BUG_ON(xa, entry != NULL); 1009 940 XA_BUG_ON(xa, i != xas.xa_index); ··· 1015 946 do { 1016 947 void *entry = xas_next(&xas); 1017 948 if ((i < (1 << 8)) || (i >= (1 << 15))) 1018 - XA_BUG_ON(xa, entry != xa_mk_value(i)); 949 + XA_BUG_ON(xa, entry != xa_mk_index(i)); 1019 950 else 1020 951 XA_BUG_ON(xa, entry != NULL); 1021 952 XA_BUG_ON(xa, i != xas.xa_index); ··· 1045 976 if (xas_error(&xas)) 1046 977 goto unlock; 1047 978 for (i = 0; i < (1U << order); i++) { 1048 - XA_BUG_ON(xa, xas_store(&xas, xa_mk_value(index + i))); 979 + XA_BUG_ON(xa, xas_store(&xas, xa_mk_index(index + i))); 1049 980 xas_next(&xas); 1050 981 } 1051 982 unlock: ··· 1100 1031 if (xas_error(&xas)) 1101 1032 goto unlock; 1102 1033 for (i = 0; i < (1UL << order); i++) { 1103 - void *old = xas_store(&xas, xa_mk_value(base + i)); 1034 + void *old = xas_store(&xas, xa_mk_index(base + i)); 1104 1035 if (xas.xa_index == index) 1105 - XA_BUG_ON(xa, old != xa_mk_value(base + i)); 1036 + XA_BUG_ON(xa, old != xa_mk_index(base + i)); 1106 1037 else 1107 1038 XA_BUG_ON(xa, old != NULL); 1108 1039 xas_next(&xas); ··· 1154 1085 unsigned long last) 1155 1086 { 1156 1087 #ifdef CONFIG_XARRAY_MULTI 1157 - xa_store_range(xa, first, last, xa_mk_value(first), GFP_KERNEL); 1088 + xa_store_range(xa, first, last, xa_mk_index(first), GFP_KERNEL); 1158 1089 1159 - XA_BUG_ON(xa, xa_load(xa, first) != xa_mk_value(first)); 1160 - XA_BUG_ON(xa, xa_load(xa, last) != xa_mk_value(first)); 1090 + XA_BUG_ON(xa, xa_load(xa, first) != xa_mk_index(first)); 1091 + XA_BUG_ON(xa, xa_load(xa, last) != xa_mk_index(first)); 1161 1092 XA_BUG_ON(xa, xa_load(xa, first - 1) != NULL); 1162 1093 XA_BUG_ON(xa, xa_load(xa, last + 1) != NULL); 1163 1094 ··· 1264 1195 XA_BUG_ON(xa, xas.xa_node->nr_values != 0); 1265 1196 rcu_read_unlock(); 1266 1197 1267 - xa_store_order(xa, 1 << order, order, xa_mk_value(1 << order), 1198 + xa_store_order(xa, 1 << order, order, xa_mk_index(1UL << order), 1268 1199 GFP_KERNEL); 1269 1200 XA_BUG_ON(xa, xas.xa_node->count != xas.xa_node->nr_values * 2); 1270 1201
+3 -5
lib/xarray.c
··· 1131 1131 entry = xa_head(xas->xa); 1132 1132 xas->xa_node = NULL; 1133 1133 if (xas->xa_index > max_index(entry)) 1134 - goto bounds; 1134 + goto out; 1135 1135 if (!xa_is_node(entry)) { 1136 1136 if (xa_marked(xas->xa, mark)) 1137 1137 return entry; ··· 1180 1180 } 1181 1181 1182 1182 out: 1183 - if (!max) 1183 + if (xas->xa_index > max) 1184 1184 goto max; 1185 - bounds: 1186 - xas->xa_node = XAS_BOUNDS; 1187 - return NULL; 1185 + return set_bounds(xas); 1188 1186 max: 1189 1187 xas->xa_node = XAS_RESTART; 1190 1188 return NULL;
+1 -3
mm/shmem.c
··· 661 661 { 662 662 void *old; 663 663 664 - xa_lock_irq(&mapping->i_pages); 665 - old = __xa_cmpxchg(&mapping->i_pages, index, radswap, NULL, 0); 666 - xa_unlock_irq(&mapping->i_pages); 664 + old = xa_cmpxchg_irq(&mapping->i_pages, index, radswap, NULL, 0); 667 665 if (old != radswap) 668 666 return -ENOENT; 669 667 free_swap_and_cache(radix_to_swp_entry(radswap));
+1
tools/testing/radix-tree/Makefile
··· 7 7 TARGETS = main idr-test multiorder xarray 8 8 CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o bitmap.o 9 9 OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ 10 + regression4.o \ 10 11 tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o 11 12 12 13 ifndef SHIFT
+1
tools/testing/radix-tree/main.c
··· 308 308 regression1_test(); 309 309 regression2_test(); 310 310 regression3_test(); 311 + regression4_test(); 311 312 iteration_test(0, 10 + 90 * long_run); 312 313 iteration_test(7, 10 + 90 * long_run); 313 314 single_thread_tests(long_run);
+1
tools/testing/radix-tree/regression.h
··· 5 5 void regression1_test(void); 6 6 void regression2_test(void); 7 7 void regression3_test(void); 8 + void regression4_test(void); 8 9 9 10 #endif
+79
tools/testing/radix-tree/regression4.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/kernel.h> 3 + #include <linux/gfp.h> 4 + #include <linux/slab.h> 5 + #include <linux/radix-tree.h> 6 + #include <linux/rcupdate.h> 7 + #include <stdlib.h> 8 + #include <pthread.h> 9 + #include <stdio.h> 10 + #include <assert.h> 11 + 12 + #include "regression.h" 13 + 14 + static pthread_barrier_t worker_barrier; 15 + static int obj0, obj1; 16 + static RADIX_TREE(mt_tree, GFP_KERNEL); 17 + 18 + static void *reader_fn(void *arg) 19 + { 20 + int i; 21 + void *entry; 22 + 23 + rcu_register_thread(); 24 + pthread_barrier_wait(&worker_barrier); 25 + 26 + for (i = 0; i < 1000000; i++) { 27 + rcu_read_lock(); 28 + entry = radix_tree_lookup(&mt_tree, 0); 29 + rcu_read_unlock(); 30 + if (entry != &obj0) { 31 + printf("iteration %d bad entry = %p\n", i, entry); 32 + abort(); 33 + } 34 + } 35 + 36 + rcu_unregister_thread(); 37 + 38 + return NULL; 39 + } 40 + 41 + static void *writer_fn(void *arg) 42 + { 43 + int i; 44 + 45 + rcu_register_thread(); 46 + pthread_barrier_wait(&worker_barrier); 47 + 48 + for (i = 0; i < 1000000; i++) { 49 + radix_tree_insert(&mt_tree, 1, &obj1); 50 + radix_tree_delete(&mt_tree, 1); 51 + } 52 + 53 + rcu_unregister_thread(); 54 + 55 + return NULL; 56 + } 57 + 58 + void regression4_test(void) 59 + { 60 + pthread_t reader, writer; 61 + 62 + printv(1, "regression test 4 starting\n"); 63 + 64 + radix_tree_insert(&mt_tree, 0, &obj0); 65 + pthread_barrier_init(&worker_barrier, NULL, 2); 66 + 67 + if (pthread_create(&reader, NULL, reader_fn, NULL) || 68 + pthread_create(&writer, NULL, writer_fn, NULL)) { 69 + perror("pthread_create"); 70 + exit(1); 71 + } 72 + 73 + if (pthread_join(reader, NULL) || pthread_join(writer, NULL)) { 74 + perror("pthread_join"); 75 + exit(1); 76 + } 77 + 78 + printv(1, "regression test 4 passed\n"); 79 + }