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; |
