summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/assoc_array.c8
-rw-r--r--lib/crc32.c4
-rw-r--r--lib/int_sqrt.c2
-rw-r--r--lib/sbitmap.c13
-rw-r--r--lib/test_kmod.c2
-rw-r--r--lib/test_rhashtable.c23
-rw-r--r--lib/test_xarray.c57
-rw-r--r--lib/xarray.c92
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)
206EXPORT_SYMBOL(crc32_le); 206EXPORT_SYMBOL(crc32_le);
207EXPORT_SYMBOL(__crc32c_le); 207EXPORT_SYMBOL(__crc32c_le);
208 208
209u32 crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le); 209u32 __pure crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le);
210u32 __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le); 210u32 __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 @@
26static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) 26static 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;
56out_unlock: 52out_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
638static void kmod_config_free(struct kmod_test_device *test_dev) 638static 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)
541static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects, 541static 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
574skip_print: 580skip_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)
357static noinline void check_reserve(struct xarray *xa) 357static 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)
812static noinline void check_find_2(struct xarray *xa) 814static 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
1189static 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
1207static 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
1186static LIST_HEAD(shadow_nodes); 1218static LIST_HEAD(shadow_nodes);
1187 1219
1188static void test_update_node(struct xa_node *node) 1220static 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 */
616static void *xas_create(struct xa_state *xas) 619static 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)
1251EXPORT_SYMBOL_GPL(xas_find_conflict); 1256EXPORT_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 */
1264void 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}
1280EXPORT_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,
1465EXPORT_SYMBOL(__xa_cmpxchg); 1440EXPORT_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 */
1458int __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}
1481EXPORT_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;