diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/assoc_array.c | 8 | ||||
-rw-r--r-- | lib/crc32.c | 4 | ||||
-rw-r--r-- | lib/int_sqrt.c | 2 | ||||
-rw-r--r-- | lib/sbitmap.c | 13 | ||||
-rw-r--r-- | lib/test_kmod.c | 2 | ||||
-rw-r--r-- | lib/test_rhashtable.c | 23 | ||||
-rw-r--r-- | lib/test_xarray.c | 57 | ||||
-rw-r--r-- | lib/xarray.c | 92 |
8 files changed, 126 insertions, 75 deletions
diff --git a/lib/assoc_array.c b/lib/assoc_array.c index c6659cb37033..59875eb278ea 100644 --- a/lib/assoc_array.c +++ b/lib/assoc_array.c | |||
@@ -768,9 +768,11 @@ all_leaves_cluster_together: | |||
768 | new_s0->index_key[i] = | 768 | new_s0->index_key[i] = |
769 | ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE); | 769 | ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE); |
770 | 770 | ||
771 | blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK); | 771 | if (level & ASSOC_ARRAY_KEY_CHUNK_MASK) { |
772 | pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank); | 772 | blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK); |
773 | new_s0->index_key[keylen - 1] &= ~blank; | 773 | pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank); |
774 | new_s0->index_key[keylen - 1] &= ~blank; | ||
775 | } | ||
774 | 776 | ||
775 | /* This now reduces to a node splitting exercise for which we'll need | 777 | /* This now reduces to a node splitting exercise for which we'll need |
776 | * to regenerate the disparity table. | 778 | * to regenerate the disparity table. |
diff --git a/lib/crc32.c b/lib/crc32.c index 45b1d67a1767..4a20455d1f61 100644 --- a/lib/crc32.c +++ b/lib/crc32.c | |||
@@ -206,8 +206,8 @@ u32 __pure __weak __crc32c_le(u32 crc, unsigned char const *p, size_t len) | |||
206 | EXPORT_SYMBOL(crc32_le); | 206 | EXPORT_SYMBOL(crc32_le); |
207 | EXPORT_SYMBOL(__crc32c_le); | 207 | EXPORT_SYMBOL(__crc32c_le); |
208 | 208 | ||
209 | u32 crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le); | 209 | u32 __pure crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le); |
210 | u32 __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le); | 210 | u32 __pure __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le); |
211 | 211 | ||
212 | /* | 212 | /* |
213 | * This multiplies the polynomials x and y modulo the given modulus. | 213 | * This multiplies the polynomials x and y modulo the given modulus. |
diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c index 14436f4ca6bd..30e0f9770f88 100644 --- a/lib/int_sqrt.c +++ b/lib/int_sqrt.c | |||
@@ -52,7 +52,7 @@ u32 int_sqrt64(u64 x) | |||
52 | if (x <= ULONG_MAX) | 52 | if (x <= ULONG_MAX) |
53 | return int_sqrt((unsigned long) x); | 53 | return int_sqrt((unsigned long) x); |
54 | 54 | ||
55 | m = 1ULL << (fls64(x) & ~1ULL); | 55 | m = 1ULL << ((fls64(x) - 1) & ~1ULL); |
56 | while (m != 0) { | 56 | while (m != 0) { |
57 | b = y + m; | 57 | b = y + m; |
58 | y >>= 1; | 58 | y >>= 1; |
diff --git a/lib/sbitmap.c b/lib/sbitmap.c index 65c2d06250a6..5b382c1244ed 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c | |||
@@ -26,14 +26,10 @@ | |||
26 | static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) | 26 | static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) |
27 | { | 27 | { |
28 | unsigned long mask, val; | 28 | unsigned long mask, val; |
29 | unsigned long __maybe_unused flags; | ||
30 | bool ret = false; | 29 | bool ret = false; |
30 | unsigned long flags; | ||
31 | 31 | ||
32 | /* Silence bogus lockdep warning */ | 32 | spin_lock_irqsave(&sb->map[index].swap_lock, flags); |
33 | #if defined(CONFIG_LOCKDEP) | ||
34 | local_irq_save(flags); | ||
35 | #endif | ||
36 | spin_lock(&sb->map[index].swap_lock); | ||
37 | 33 | ||
38 | if (!sb->map[index].cleared) | 34 | if (!sb->map[index].cleared) |
39 | goto out_unlock; | 35 | goto out_unlock; |
@@ -54,10 +50,7 @@ static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) | |||
54 | 50 | ||
55 | ret = true; | 51 | ret = true; |
56 | out_unlock: | 52 | out_unlock: |
57 | spin_unlock(&sb->map[index].swap_lock); | 53 | spin_unlock_irqrestore(&sb->map[index].swap_lock, flags); |
58 | #if defined(CONFIG_LOCKDEP) | ||
59 | local_irq_restore(flags); | ||
60 | #endif | ||
61 | return ret; | 54 | return ret; |
62 | } | 55 | } |
63 | 56 | ||
diff --git a/lib/test_kmod.c b/lib/test_kmod.c index d82d022111e0..9cf77628fc91 100644 --- a/lib/test_kmod.c +++ b/lib/test_kmod.c | |||
@@ -632,7 +632,7 @@ static void __kmod_config_free(struct test_config *config) | |||
632 | config->test_driver = NULL; | 632 | config->test_driver = NULL; |
633 | 633 | ||
634 | kfree_const(config->test_fs); | 634 | kfree_const(config->test_fs); |
635 | config->test_driver = NULL; | 635 | config->test_fs = NULL; |
636 | } | 636 | } |
637 | 637 | ||
638 | static void kmod_config_free(struct kmod_test_device *test_dev) | 638 | static void kmod_config_free(struct kmod_test_device *test_dev) |
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index 6a8ac7626797..e52f8cafe227 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c | |||
@@ -541,38 +541,45 @@ static unsigned int __init print_ht(struct rhltable *rhlt) | |||
541 | static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects, | 541 | static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects, |
542 | int cnt, bool slow) | 542 | int cnt, bool slow) |
543 | { | 543 | { |
544 | struct rhltable rhlt; | 544 | struct rhltable *rhlt; |
545 | unsigned int i, ret; | 545 | unsigned int i, ret; |
546 | const char *key; | 546 | const char *key; |
547 | int err = 0; | 547 | int err = 0; |
548 | 548 | ||
549 | err = rhltable_init(&rhlt, &test_rht_params_dup); | 549 | rhlt = kmalloc(sizeof(*rhlt), GFP_KERNEL); |
550 | if (WARN_ON(err)) | 550 | if (WARN_ON(!rhlt)) |
551 | return -EINVAL; | ||
552 | |||
553 | err = rhltable_init(rhlt, &test_rht_params_dup); | ||
554 | if (WARN_ON(err)) { | ||
555 | kfree(rhlt); | ||
551 | return err; | 556 | return err; |
557 | } | ||
552 | 558 | ||
553 | for (i = 0; i < cnt; i++) { | 559 | for (i = 0; i < cnt; i++) { |
554 | rhl_test_objects[i].value.tid = i; | 560 | rhl_test_objects[i].value.tid = i; |
555 | key = rht_obj(&rhlt.ht, &rhl_test_objects[i].list_node.rhead); | 561 | key = rht_obj(&rhlt->ht, &rhl_test_objects[i].list_node.rhead); |
556 | key += test_rht_params_dup.key_offset; | 562 | key += test_rht_params_dup.key_offset; |
557 | 563 | ||
558 | if (slow) { | 564 | if (slow) { |
559 | err = PTR_ERR(rhashtable_insert_slow(&rhlt.ht, key, | 565 | err = PTR_ERR(rhashtable_insert_slow(&rhlt->ht, key, |
560 | &rhl_test_objects[i].list_node.rhead)); | 566 | &rhl_test_objects[i].list_node.rhead)); |
561 | if (err == -EAGAIN) | 567 | if (err == -EAGAIN) |
562 | err = 0; | 568 | err = 0; |
563 | } else | 569 | } else |
564 | err = rhltable_insert(&rhlt, | 570 | err = rhltable_insert(rhlt, |
565 | &rhl_test_objects[i].list_node, | 571 | &rhl_test_objects[i].list_node, |
566 | test_rht_params_dup); | 572 | test_rht_params_dup); |
567 | if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast")) | 573 | if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast")) |
568 | goto skip_print; | 574 | goto skip_print; |
569 | } | 575 | } |
570 | 576 | ||
571 | ret = print_ht(&rhlt); | 577 | ret = print_ht(rhlt); |
572 | WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast"); | 578 | WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast"); |
573 | 579 | ||
574 | skip_print: | 580 | skip_print: |
575 | rhltable_destroy(&rhlt); | 581 | rhltable_destroy(rhlt); |
582 | kfree(rhlt); | ||
576 | 583 | ||
577 | return 0; | 584 | return 0; |
578 | } | 585 | } |
diff --git a/lib/test_xarray.c b/lib/test_xarray.c index 4676c0a1eeca..c596a957f764 100644 --- a/lib/test_xarray.c +++ b/lib/test_xarray.c | |||
@@ -199,7 +199,7 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index) | |||
199 | XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL)); | 199 | XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL)); |
200 | xa_set_mark(xa, index + 1, XA_MARK_0); | 200 | xa_set_mark(xa, index + 1, XA_MARK_0); |
201 | XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL)); | 201 | XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL)); |
202 | xa_set_mark(xa, index + 2, XA_MARK_1); | 202 | xa_set_mark(xa, index + 2, XA_MARK_2); |
203 | XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL)); | 203 | XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL)); |
204 | xa_store_order(xa, index, order, xa_mk_index(index), | 204 | xa_store_order(xa, index, order, xa_mk_index(index), |
205 | GFP_KERNEL); | 205 | GFP_KERNEL); |
@@ -209,8 +209,8 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index) | |||
209 | void *entry; | 209 | void *entry; |
210 | 210 | ||
211 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0)); | 211 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0)); |
212 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1)); | 212 | XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_1)); |
213 | XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2)); | 213 | XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_2)); |
214 | 214 | ||
215 | /* We should see two elements in the array */ | 215 | /* We should see two elements in the array */ |
216 | rcu_read_lock(); | 216 | rcu_read_lock(); |
@@ -357,7 +357,7 @@ static noinline void check_cmpxchg(struct xarray *xa) | |||
357 | static noinline void check_reserve(struct xarray *xa) | 357 | static noinline void check_reserve(struct xarray *xa) |
358 | { | 358 | { |
359 | void *entry; | 359 | void *entry; |
360 | unsigned long index = 0; | 360 | unsigned long index; |
361 | 361 | ||
362 | /* An array with a reserved entry is not empty */ | 362 | /* An array with a reserved entry is not empty */ |
363 | XA_BUG_ON(xa, !xa_empty(xa)); | 363 | XA_BUG_ON(xa, !xa_empty(xa)); |
@@ -382,10 +382,12 @@ static noinline void check_reserve(struct xarray *xa) | |||
382 | xa_erase_index(xa, 12345678); | 382 | xa_erase_index(xa, 12345678); |
383 | XA_BUG_ON(xa, !xa_empty(xa)); | 383 | XA_BUG_ON(xa, !xa_empty(xa)); |
384 | 384 | ||
385 | /* And so does xa_insert */ | 385 | /* But xa_insert does not */ |
386 | xa_reserve(xa, 12345678, GFP_KERNEL); | 386 | xa_reserve(xa, 12345678, GFP_KERNEL); |
387 | XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != 0); | 387 | XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != |
388 | xa_erase_index(xa, 12345678); | 388 | -EEXIST); |
389 | XA_BUG_ON(xa, xa_empty(xa)); | ||
390 | XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL); | ||
389 | XA_BUG_ON(xa, !xa_empty(xa)); | 391 | XA_BUG_ON(xa, !xa_empty(xa)); |
390 | 392 | ||
391 | /* Can iterate through a reserved entry */ | 393 | /* Can iterate through a reserved entry */ |
@@ -393,7 +395,7 @@ static noinline void check_reserve(struct xarray *xa) | |||
393 | xa_reserve(xa, 6, GFP_KERNEL); | 395 | xa_reserve(xa, 6, GFP_KERNEL); |
394 | xa_store_index(xa, 7, GFP_KERNEL); | 396 | xa_store_index(xa, 7, GFP_KERNEL); |
395 | 397 | ||
396 | xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) { | 398 | xa_for_each(xa, index, entry) { |
397 | XA_BUG_ON(xa, index != 5 && index != 7); | 399 | XA_BUG_ON(xa, index != 5 && index != 7); |
398 | } | 400 | } |
399 | xa_destroy(xa); | 401 | xa_destroy(xa); |
@@ -812,17 +814,16 @@ static noinline void check_find_1(struct xarray *xa) | |||
812 | static noinline void check_find_2(struct xarray *xa) | 814 | static noinline void check_find_2(struct xarray *xa) |
813 | { | 815 | { |
814 | void *entry; | 816 | void *entry; |
815 | unsigned long i, j, index = 0; | 817 | unsigned long i, j, index; |
816 | 818 | ||
817 | xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) { | 819 | xa_for_each(xa, index, entry) { |
818 | XA_BUG_ON(xa, true); | 820 | XA_BUG_ON(xa, true); |
819 | } | 821 | } |
820 | 822 | ||
821 | for (i = 0; i < 1024; i++) { | 823 | for (i = 0; i < 1024; i++) { |
822 | xa_store_index(xa, index, GFP_KERNEL); | 824 | xa_store_index(xa, index, GFP_KERNEL); |
823 | j = 0; | 825 | j = 0; |
824 | index = 0; | 826 | xa_for_each(xa, index, entry) { |
825 | xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) { | ||
826 | XA_BUG_ON(xa, xa_mk_index(index) != entry); | 827 | XA_BUG_ON(xa, xa_mk_index(index) != entry); |
827 | XA_BUG_ON(xa, index != j++); | 828 | XA_BUG_ON(xa, index != j++); |
828 | } | 829 | } |
@@ -839,6 +840,7 @@ static noinline void check_find_3(struct xarray *xa) | |||
839 | 840 | ||
840 | for (i = 0; i < 100; i++) { | 841 | for (i = 0; i < 100; i++) { |
841 | for (j = 0; j < 100; j++) { | 842 | for (j = 0; j < 100; j++) { |
843 | rcu_read_lock(); | ||
842 | for (k = 0; k < 100; k++) { | 844 | for (k = 0; k < 100; k++) { |
843 | xas_set(&xas, j); | 845 | xas_set(&xas, j); |
844 | xas_for_each_marked(&xas, entry, k, XA_MARK_0) | 846 | xas_for_each_marked(&xas, entry, k, XA_MARK_0) |
@@ -847,6 +849,7 @@ static noinline void check_find_3(struct xarray *xa) | |||
847 | XA_BUG_ON(xa, | 849 | XA_BUG_ON(xa, |
848 | xas.xa_node != XAS_RESTART); | 850 | xas.xa_node != XAS_RESTART); |
849 | } | 851 | } |
852 | rcu_read_unlock(); | ||
850 | } | 853 | } |
851 | xa_store_index(xa, i, GFP_KERNEL); | 854 | xa_store_index(xa, i, GFP_KERNEL); |
852 | xa_set_mark(xa, i, XA_MARK_0); | 855 | xa_set_mark(xa, i, XA_MARK_0); |
@@ -1183,6 +1186,35 @@ static noinline void check_store_range(struct xarray *xa) | |||
1183 | } | 1186 | } |
1184 | } | 1187 | } |
1185 | 1188 | ||
1189 | static void check_align_1(struct xarray *xa, char *name) | ||
1190 | { | ||
1191 | int i; | ||
1192 | unsigned int id; | ||
1193 | unsigned long index; | ||
1194 | void *entry; | ||
1195 | |||
1196 | for (i = 0; i < 8; i++) { | ||
1197 | id = 0; | ||
1198 | XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, name + i, GFP_KERNEL) | ||
1199 | != 0); | ||
1200 | XA_BUG_ON(xa, id != i); | ||
1201 | } | ||
1202 | xa_for_each(xa, index, entry) | ||
1203 | XA_BUG_ON(xa, xa_is_err(entry)); | ||
1204 | xa_destroy(xa); | ||
1205 | } | ||
1206 | |||
1207 | static noinline void check_align(struct xarray *xa) | ||
1208 | { | ||
1209 | char name[] = "Motorola 68000"; | ||
1210 | |||
1211 | check_align_1(xa, name); | ||
1212 | check_align_1(xa, name + 1); | ||
1213 | check_align_1(xa, name + 2); | ||
1214 | check_align_1(xa, name + 3); | ||
1215 | // check_align_2(xa, name); | ||
1216 | } | ||
1217 | |||
1186 | static LIST_HEAD(shadow_nodes); | 1218 | static LIST_HEAD(shadow_nodes); |
1187 | 1219 | ||
1188 | static void test_update_node(struct xa_node *node) | 1220 | static void test_update_node(struct xa_node *node) |
@@ -1332,6 +1364,7 @@ static int xarray_checks(void) | |||
1332 | check_create_range(&array); | 1364 | check_create_range(&array); |
1333 | check_store_range(&array); | 1365 | check_store_range(&array); |
1334 | check_store_iter(&array); | 1366 | check_store_iter(&array); |
1367 | check_align(&xa0); | ||
1335 | 1368 | ||
1336 | check_workingset(&array, 0); | 1369 | check_workingset(&array, 0); |
1337 | check_workingset(&array, 64); | 1370 | check_workingset(&array, 64); |
diff --git a/lib/xarray.c b/lib/xarray.c index 5f3f9311de89..81c3171ddde9 100644 --- a/lib/xarray.c +++ b/lib/xarray.c | |||
@@ -232,6 +232,8 @@ void *xas_load(struct xa_state *xas) | |||
232 | if (xas->xa_shift > node->shift) | 232 | if (xas->xa_shift > node->shift) |
233 | break; | 233 | break; |
234 | entry = xas_descend(xas, node); | 234 | entry = xas_descend(xas, node); |
235 | if (node->shift == 0) | ||
236 | break; | ||
235 | } | 237 | } |
236 | return entry; | 238 | return entry; |
237 | } | 239 | } |
@@ -506,7 +508,7 @@ static void xas_free_nodes(struct xa_state *xas, struct xa_node *top) | |||
506 | for (;;) { | 508 | for (;;) { |
507 | void *entry = xa_entry_locked(xas->xa, node, offset); | 509 | void *entry = xa_entry_locked(xas->xa, node, offset); |
508 | 510 | ||
509 | if (xa_is_node(entry)) { | 511 | if (node->shift && xa_is_node(entry)) { |
510 | node = xa_to_node(entry); | 512 | node = xa_to_node(entry); |
511 | offset = 0; | 513 | offset = 0; |
512 | continue; | 514 | continue; |
@@ -604,6 +606,7 @@ static int xas_expand(struct xa_state *xas, void *head) | |||
604 | /* | 606 | /* |
605 | * xas_create() - Create a slot to store an entry in. | 607 | * xas_create() - Create a slot to store an entry in. |
606 | * @xas: XArray operation state. | 608 | * @xas: XArray operation state. |
609 | * @allow_root: %true if we can store the entry in the root directly | ||
607 | * | 610 | * |
608 | * Most users will not need to call this function directly, as it is called | 611 | * Most users will not need to call this function directly, as it is called |
609 | * by xas_store(). It is useful for doing conditional store operations | 612 | * by xas_store(). It is useful for doing conditional store operations |
@@ -613,7 +616,7 @@ static int xas_expand(struct xa_state *xas, void *head) | |||
613 | * If the slot was newly created, returns %NULL. If it failed to create the | 616 | * If the slot was newly created, returns %NULL. If it failed to create the |
614 | * slot, returns %NULL and indicates the error in @xas. | 617 | * slot, returns %NULL and indicates the error in @xas. |
615 | */ | 618 | */ |
616 | static void *xas_create(struct xa_state *xas) | 619 | static void *xas_create(struct xa_state *xas, bool allow_root) |
617 | { | 620 | { |
618 | struct xarray *xa = xas->xa; | 621 | struct xarray *xa = xas->xa; |
619 | void *entry; | 622 | void *entry; |
@@ -628,6 +631,8 @@ static void *xas_create(struct xa_state *xas) | |||
628 | shift = xas_expand(xas, entry); | 631 | shift = xas_expand(xas, entry); |
629 | if (shift < 0) | 632 | if (shift < 0) |
630 | return NULL; | 633 | return NULL; |
634 | if (!shift && !allow_root) | ||
635 | shift = XA_CHUNK_SHIFT; | ||
631 | entry = xa_head_locked(xa); | 636 | entry = xa_head_locked(xa); |
632 | slot = &xa->xa_head; | 637 | slot = &xa->xa_head; |
633 | } else if (xas_error(xas)) { | 638 | } else if (xas_error(xas)) { |
@@ -687,7 +692,7 @@ void xas_create_range(struct xa_state *xas) | |||
687 | xas->xa_sibs = 0; | 692 | xas->xa_sibs = 0; |
688 | 693 | ||
689 | for (;;) { | 694 | for (;;) { |
690 | xas_create(xas); | 695 | xas_create(xas, true); |
691 | if (xas_error(xas)) | 696 | if (xas_error(xas)) |
692 | goto restore; | 697 | goto restore; |
693 | if (xas->xa_index <= (index | XA_CHUNK_MASK)) | 698 | if (xas->xa_index <= (index | XA_CHUNK_MASK)) |
@@ -754,7 +759,7 @@ void *xas_store(struct xa_state *xas, void *entry) | |||
754 | bool value = xa_is_value(entry); | 759 | bool value = xa_is_value(entry); |
755 | 760 | ||
756 | if (entry) | 761 | if (entry) |
757 | first = xas_create(xas); | 762 | first = xas_create(xas, !xa_is_node(entry)); |
758 | else | 763 | else |
759 | first = xas_load(xas); | 764 | first = xas_load(xas); |
760 | 765 | ||
@@ -1251,35 +1256,6 @@ void *xas_find_conflict(struct xa_state *xas) | |||
1251 | EXPORT_SYMBOL_GPL(xas_find_conflict); | 1256 | EXPORT_SYMBOL_GPL(xas_find_conflict); |
1252 | 1257 | ||
1253 | /** | 1258 | /** |
1254 | * xa_init_flags() - Initialise an empty XArray with flags. | ||
1255 | * @xa: XArray. | ||
1256 | * @flags: XA_FLAG values. | ||
1257 | * | ||
1258 | * If you need to initialise an XArray with special flags (eg you need | ||
1259 | * to take the lock from interrupt context), use this function instead | ||
1260 | * of xa_init(). | ||
1261 | * | ||
1262 | * Context: Any context. | ||
1263 | */ | ||
1264 | void xa_init_flags(struct xarray *xa, gfp_t flags) | ||
1265 | { | ||
1266 | unsigned int lock_type; | ||
1267 | static struct lock_class_key xa_lock_irq; | ||
1268 | static struct lock_class_key xa_lock_bh; | ||
1269 | |||
1270 | spin_lock_init(&xa->xa_lock); | ||
1271 | xa->xa_flags = flags; | ||
1272 | xa->xa_head = NULL; | ||
1273 | |||
1274 | lock_type = xa_lock_type(xa); | ||
1275 | if (lock_type == XA_LOCK_IRQ) | ||
1276 | lockdep_set_class(&xa->xa_lock, &xa_lock_irq); | ||
1277 | else if (lock_type == XA_LOCK_BH) | ||
1278 | lockdep_set_class(&xa->xa_lock, &xa_lock_bh); | ||
1279 | } | ||
1280 | EXPORT_SYMBOL(xa_init_flags); | ||
1281 | |||
1282 | /** | ||
1283 | * xa_load() - Load an entry from an XArray. | 1259 | * xa_load() - Load an entry from an XArray. |
1284 | * @xa: XArray. | 1260 | * @xa: XArray. |
1285 | * @index: index into array. | 1261 | * @index: index into array. |
@@ -1308,7 +1284,6 @@ static void *xas_result(struct xa_state *xas, void *curr) | |||
1308 | { | 1284 | { |
1309 | if (xa_is_zero(curr)) | 1285 | if (xa_is_zero(curr)) |
1310 | return NULL; | 1286 | return NULL; |
1311 | XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr)); | ||
1312 | if (xas_error(xas)) | 1287 | if (xas_error(xas)) |
1313 | curr = xas->xa_node; | 1288 | curr = xas->xa_node; |
1314 | return curr; | 1289 | return curr; |
@@ -1378,7 +1353,7 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) | |||
1378 | XA_STATE(xas, xa, index); | 1353 | XA_STATE(xas, xa, index); |
1379 | void *curr; | 1354 | void *curr; |
1380 | 1355 | ||
1381 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1356 | if (WARN_ON_ONCE(xa_is_advanced(entry))) |
1382 | return XA_ERROR(-EINVAL); | 1357 | return XA_ERROR(-EINVAL); |
1383 | if (xa_track_free(xa) && !entry) | 1358 | if (xa_track_free(xa) && !entry) |
1384 | entry = XA_ZERO_ENTRY; | 1359 | entry = XA_ZERO_ENTRY; |
@@ -1444,7 +1419,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1444 | XA_STATE(xas, xa, index); | 1419 | XA_STATE(xas, xa, index); |
1445 | void *curr; | 1420 | void *curr; |
1446 | 1421 | ||
1447 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1422 | if (WARN_ON_ONCE(xa_is_advanced(entry))) |
1448 | return XA_ERROR(-EINVAL); | 1423 | return XA_ERROR(-EINVAL); |
1449 | if (xa_track_free(xa) && !entry) | 1424 | if (xa_track_free(xa) && !entry) |
1450 | entry = XA_ZERO_ENTRY; | 1425 | entry = XA_ZERO_ENTRY; |
@@ -1465,6 +1440,47 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1465 | EXPORT_SYMBOL(__xa_cmpxchg); | 1440 | EXPORT_SYMBOL(__xa_cmpxchg); |
1466 | 1441 | ||
1467 | /** | 1442 | /** |
1443 | * __xa_insert() - Store this entry in the XArray if no entry is present. | ||
1444 | * @xa: XArray. | ||
1445 | * @index: Index into array. | ||
1446 | * @entry: New entry. | ||
1447 | * @gfp: Memory allocation flags. | ||
1448 | * | ||
1449 | * Inserting a NULL entry will store a reserved entry (like xa_reserve()) | ||
1450 | * if no entry is present. Inserting will fail if a reserved entry is | ||
1451 | * present, even though loading from this index will return NULL. | ||
1452 | * | ||
1453 | * Context: Any context. Expects xa_lock to be held on entry. May | ||
1454 | * release and reacquire xa_lock if @gfp flags permit. | ||
1455 | * Return: 0 if the store succeeded. -EEXIST if another entry was present. | ||
1456 | * -ENOMEM if memory could not be allocated. | ||
1457 | */ | ||
1458 | int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) | ||
1459 | { | ||
1460 | XA_STATE(xas, xa, index); | ||
1461 | void *curr; | ||
1462 | |||
1463 | if (WARN_ON_ONCE(xa_is_advanced(entry))) | ||
1464 | return -EINVAL; | ||
1465 | if (!entry) | ||
1466 | entry = XA_ZERO_ENTRY; | ||
1467 | |||
1468 | do { | ||
1469 | curr = xas_load(&xas); | ||
1470 | if (!curr) { | ||
1471 | xas_store(&xas, entry); | ||
1472 | if (xa_track_free(xa)) | ||
1473 | xas_clear_mark(&xas, XA_FREE_MARK); | ||
1474 | } else { | ||
1475 | xas_set_err(&xas, -EEXIST); | ||
1476 | } | ||
1477 | } while (__xas_nomem(&xas, gfp)); | ||
1478 | |||
1479 | return xas_error(&xas); | ||
1480 | } | ||
1481 | EXPORT_SYMBOL(__xa_insert); | ||
1482 | |||
1483 | /** | ||
1468 | * __xa_reserve() - Reserve this index in the XArray. | 1484 | * __xa_reserve() - Reserve this index in the XArray. |
1469 | * @xa: XArray. | 1485 | * @xa: XArray. |
1470 | * @index: Index into array. | 1486 | * @index: Index into array. |
@@ -1567,7 +1583,7 @@ void *xa_store_range(struct xarray *xa, unsigned long first, | |||
1567 | if (last + 1) | 1583 | if (last + 1) |
1568 | order = __ffs(last + 1); | 1584 | order = __ffs(last + 1); |
1569 | xas_set_order(&xas, last, order); | 1585 | xas_set_order(&xas, last, order); |
1570 | xas_create(&xas); | 1586 | xas_create(&xas, true); |
1571 | if (xas_error(&xas)) | 1587 | if (xas_error(&xas)) |
1572 | goto unlock; | 1588 | goto unlock; |
1573 | } | 1589 | } |
@@ -1609,7 +1625,7 @@ int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp) | |||
1609 | XA_STATE(xas, xa, 0); | 1625 | XA_STATE(xas, xa, 0); |
1610 | int err; | 1626 | int err; |
1611 | 1627 | ||
1612 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1628 | if (WARN_ON_ONCE(xa_is_advanced(entry))) |
1613 | return -EINVAL; | 1629 | return -EINVAL; |
1614 | if (WARN_ON_ONCE(!xa_track_free(xa))) | 1630 | if (WARN_ON_ONCE(!xa_track_free(xa))) |
1615 | return -EINVAL; | 1631 | return -EINVAL; |