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.

maple_tree: testing update for spanning store

Spanning store had some corner cases which showed up during rcu stress
testing. Add explicit tests for those cases.

At the same time add some locking for easier visibility of the rcu stress
testing. Only a single dump of the tree will happen on the first detected
issue instead of flooding the console with output.

Link: https://lkml.kernel.org/r/20260130205935.2559335-13-Liam.Howlett@oracle.com
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Alice Ryhl <aliceryhl@google.com>
Cc: Andrew Ballance <andrewjballance@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christian Kujau <lists@nerdbynature.de>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: SeongJae Park <sj@kernel.org>
Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Liam R. Howlett and committed by
Andrew Morton
b14ffd2c 9ec1e972

+163 -9
+163 -9
tools/testing/radix-tree/maple.c
··· 38 38 39 39 unsigned long index[RCU_RANGE_COUNT]; 40 40 unsigned long last[RCU_RANGE_COUNT]; 41 + pthread_mutex_t dump; 41 42 }; 42 43 43 44 struct rcu_test_struct3 { ··· 33998 33997 } 33999 33998 } 34000 33999 34001 - RCU_MT_BUG_ON(test, mas.index != r_start); 34002 - RCU_MT_BUG_ON(test, mas.last != r_end); 34000 + if (mas.index != r_start) { 34001 + if (pthread_mutex_trylock(&test->dump) != 0) { 34002 + rcu_read_unlock(); 34003 + goto quit; 34004 + } 34005 + printk("start is wrong: %lx (%lu) vs expected %lx (%lu)\n", 34006 + mas.index, mas.index, r_start, r_start); 34007 + RCU_MT_BUG_ON(test, mas.index != r_start); 34008 + } 34009 + 34010 + if (mas.last != r_end) { 34011 + if (pthread_mutex_trylock(&test->dump) != 0) { 34012 + rcu_read_unlock(); 34013 + goto quit; 34014 + } 34015 + printk("last is wrong: %lx (%lu) vs expected %lx (%lu)\n", 34016 + mas.last, mas.last, r_end, r_end); 34017 + RCU_MT_BUG_ON(test, mas.last != r_end); 34018 + } 34003 34019 34004 34020 if (i == reader->flip) { 34005 34021 alt = xa_mk_value(index + i + RCU_RANGE_COUNT); ··· 34032 34014 else if (entry == alt) 34033 34015 toggled = true; 34034 34016 else { 34035 - printk("!!%lu-%lu -> %p not %p or %p\n", mas.index, mas.last, entry, expected, alt); 34017 + printk("!!%lu-%lu -> %p not %p or %p\n", 34018 + mas.index, mas.last, entry, expected, alt); 34036 34019 RCU_MT_BUG_ON(test, 1); 34037 34020 } 34038 34021 ··· 34066 34047 usleep(test->pause); 34067 34048 } 34068 34049 34050 + quit: 34069 34051 rcu_unregister_thread(); 34070 34052 return NULL; 34071 34053 } 34054 + 34072 34055 /* RCU reader in decreasing index */ 34073 34056 static void *rcu_reader_rev(void *ptr) 34074 34057 { ··· 34140 34119 line = __LINE__; 34141 34120 34142 34121 if (mas.index != r_start) { 34122 + if (pthread_mutex_trylock(&test->dump) != 0) { 34123 + rcu_read_unlock(); 34124 + goto quit; 34125 + } 34126 + 34143 34127 alt = xa_mk_value(index + i * 2 + 1 + 34144 34128 RCU_RANGE_COUNT); 34145 34129 mt_dump(test->mt, mt_dump_dec); 34146 - printk("Error: %lu-%lu %p != %lu-%lu %p %p line %d i %d\n", 34147 - mas.index, mas.last, entry, 34148 - r_start, r_end, expected, alt, 34149 - line, i); 34130 + printk("Error: %p %lu-%lu %p != %lu-%lu %p %p line %d i %d\n", 34131 + mas.node, mas.index, mas.last, entry, 34132 + r_start, r_end, expected, alt, line, i); 34150 34133 } 34151 34134 RCU_MT_BUG_ON(test, mas.index != r_start); 34152 34135 RCU_MT_BUG_ON(test, mas.last != r_end); ··· 34205 34180 usleep(test->pause); 34206 34181 } 34207 34182 34183 + quit: 34208 34184 rcu_unregister_thread(); 34209 34185 return NULL; 34210 34186 } ··· 34355 34329 test.seen_modified = 0; 34356 34330 test.thread_count = 0; 34357 34331 test.start = test.stop = false; 34332 + pthread_mutex_init(&test.dump, NULL); 34358 34333 seed = time(NULL); 34359 34334 srand(seed); 34360 34335 for (i = 0; i < RCU_RANGE_COUNT; i++) { ··· 34441 34414 unsigned long removed; /* The index of the removed entry */ 34442 34415 unsigned long added; /* The index of the removed entry */ 34443 34416 unsigned long toggle; /* The index of the removed entry */ 34417 + pthread_mutex_t dump; 34444 34418 }; 34445 34419 34446 34420 static inline ··· 34534 34506 /* Out of the interesting range */ 34535 34507 if (mas.index < test->index || mas.index > test->last) { 34536 34508 if (entry != expected) { 34537 - printk("%lx - %lx = %p not %p\n", 34509 + if (pthread_mutex_trylock(&test->dump) != 0) 34510 + break; 34511 + printk("\nERROR: %lx - %lx = %p not %p\n", 34538 34512 mas.index, mas.last, entry, expected); 34539 34513 } 34540 34514 MT_BUG_ON(test->mt, entry != expected); ··· 34884 34854 vals.range_end = ULONG_MAX; 34885 34855 vals.seen_entry2 = 0; 34886 34856 vals.seen_entry3 = 0; 34857 + pthread_mutex_init(&vals.dump, NULL); 34887 34858 34888 34859 run_check_rcu(mt, &vals); 34889 34860 mtree_destroy(mt); ··· 35281 35250 { 35282 35251 unsigned long i, max = 5000; 35283 35252 MA_STATE(mas, mt, 1200, 2380); 35253 + struct maple_enode *enode; 35254 + struct maple_node *pnode; 35284 35255 35285 35256 for (i = 0; i <= max; i++) 35286 35257 mtree_test_store_range(mt, i * 10, i * 10 + 5, &i); ··· 35443 35410 mas_set_range(&mas, 76, 875); 35444 35411 mas_store_gfp(&mas, NULL, GFP_KERNEL); 35445 35412 mtree_unlock(mt); 35413 + mtree_destroy(mt); 35414 + 35415 + mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE); 35416 + for (i = 0; i <= max; i++) 35417 + mtree_test_store_range(mt, i * 10, i * 10 + 5, &i); 35418 + 35419 + if (MAPLE_32BIT) 35420 + i = 49750; /* 0xC25B */ 35421 + else 35422 + i = 49835; /* 0xC2AB */ 35423 + 35424 + mtree_lock(mt); 35425 + /* Store a null across a boundary that ends in a null */ 35426 + mas_set(&mas, i); /* 0xC2AB */ 35427 + MT_BUG_ON(mt, mas_walk(&mas) == NULL); 35428 + MT_BUG_ON(mt, mas.end != mas.offset); 35429 + MT_BUG_ON(mt, mas_next_range(&mas, ULONG_MAX) != NULL); 35430 + mas_set_range(&mas, i, mas.last - 1); 35431 + mas_store_gfp(&mas, NULL, GFP_KERNEL); 35432 + mt_validate(mt); 35433 + 35434 + /* Store a null across a boundary that starts and ends in a null */ 35435 + mas_set(&mas, 49849); 35436 + MT_BUG_ON(mt, mas_walk(&mas) != NULL); 35437 + MT_BUG_ON(mt, mas.index != 49846); 35438 + mas_set(&mas, 49876); 35439 + MT_BUG_ON(mt, mas_walk(&mas) != NULL); 35440 + MT_BUG_ON(mt, mas.last != 49879); 35441 + mas_set_range(&mas, 49849, 49876); 35442 + mas_store_gfp(&mas, NULL, GFP_KERNEL); 35443 + /* Results in 49846-49879: (nil) */ 35444 + MT_BUG_ON(mt, mas.index != 49846); 35445 + MT_BUG_ON(mt, mas.last != 49879); 35446 + mt_validate(mt); 35447 + 35448 + /* Store a null across a boundary that starts and ends next to nulls */ 35449 + mas_set(&mas, 49800); 35450 + MT_BUG_ON(mt, mas_walk(&mas) == NULL); 35451 + MT_BUG_ON(mt, mas.index != 49800); 35452 + mas_set(&mas, 49815); 35453 + MT_BUG_ON(mt, mas_walk(&mas) == NULL); 35454 + MT_BUG_ON(mt, mas.last != 49815); 35455 + mas_set_range(&mas, 49800, 49815); 35456 + mas_store_gfp(&mas, NULL, GFP_KERNEL); 35457 + /* Results in 49846-49879: (nil) */ 35458 + MT_BUG_ON(mt, mas.index != 49796); 35459 + MT_BUG_ON(mt, mas.last != 49819); 35460 + mt_validate(mt); 35461 + 35462 + /* Store a value across a boundary that starts and ends in a null */ 35463 + mas_set(&mas, 49907); 35464 + MT_BUG_ON(mt, mas_walk(&mas) != NULL); 35465 + MT_BUG_ON(mt, mas.index != 49906); 35466 + mas_set(&mas, 49928); 35467 + MT_BUG_ON(mt, mas_walk(&mas) != NULL); 35468 + MT_BUG_ON(mt, mas.last != 49929); 35469 + mas_set_range(&mas, 49907, 49928); 35470 + mas_store_gfp(&mas, check_spanning_write, GFP_KERNEL); 35471 + MT_BUG_ON(mt, mas.index != 49907); 35472 + MT_BUG_ON(mt, mas.last != 49928); 35473 + mt_validate(mt); 35474 + 35475 + /* Store a value across a node boundary that causes a 3 way split */ 35476 + 35477 + if (MAPLE_32BIT) 35478 + i = 49590; /* 0xc1b6 */ 35479 + else 35480 + i = 49670; /* 0xC206 */ 35481 + 35482 + mas_set(&mas, i); 35483 + MT_BUG_ON(mt, mas_walk(&mas) == NULL); 35484 + MT_BUG_ON(mt, mas.index != i); 35485 + MT_BUG_ON(mt, mas.end != mt_slot_count(mas.node) - 1); 35486 + enode = mas.node; 35487 + MT_BUG_ON(mt, mas_next_range(&mas, ULONG_MAX) != NULL); 35488 + MT_BUG_ON(mt, mas.index != i + 6); 35489 + MT_BUG_ON(mt, mas.end != mt_slot_count(mas.node) - 1); 35490 + MT_BUG_ON(mt, enode == mas.node); 35491 + mas_set_range(&mas, i + 2, i + 7); 35492 + mas_store_gfp(&mas, check_spanning_write, GFP_KERNEL); 35493 + MT_BUG_ON(mt, mas.index != i + 2); 35494 + MT_BUG_ON(mt, mas.last != i + 7); 35495 + mt_validate(mt); 35496 + 35497 + /* 2 levels of basically the same testing */ 35498 + 35499 + if (MAPLE_32BIT) { 35500 + /* 32bit needs a bit more work to fill the nodes. 35501 + * The two parent nodes need to be filled (they have one space 35502 + * vacant) without causing a split at the store locations (or 35503 + * the siblings). 35504 + */ 35505 + i = 44426; 35506 + mas_set(&mas, i); 35507 + mas_store_gfp(&mas, check_spanning_write, GFP_KERNEL); 35508 + i = 45126; 35509 + mas_set(&mas, i); 35510 + mas_store_gfp(&mas, check_spanning_write, GFP_KERNEL); 35511 + i = 44790; 35512 + } else { 35513 + /* 48950 - 48955 => ptr, 48956 - 48959 => NULL */ 35514 + i = 48950; 35515 + 35516 + } 35517 + mas_set(&mas, i); 35518 + MT_BUG_ON(mt, mas_walk(&mas) == NULL); 35519 + MT_BUG_ON(mt, mas.index != i); 35520 + MT_BUG_ON(mt, mas.end != mt_slot_count(mas.node) - 1); 35521 + enode = mas.node; 35522 + pnode = mte_parent(enode); 35523 + MT_BUG_ON(mt, mas_next_range(&mas, ULONG_MAX) != NULL); 35524 + MT_BUG_ON(mt, mas.index != i + 6); 35525 + MT_BUG_ON(mt, mas.end != mt_slot_count(mas.node) - 1); 35526 + MT_BUG_ON(mt, enode == mas.node); 35527 + MT_BUG_ON(mt, pnode == mte_parent(mas.node)); 35528 + mas_set_range(&mas, i + 2, i + 8); 35529 + mas_store_gfp(&mas, NULL, GFP_KERNEL); 35530 + mt_validate(mt); 35531 + 35532 + mtree_unlock(mt); 35533 + mtree_destroy(mt); 35534 + rcu_barrier(); 35446 35535 } 35447 35536 /* End of spanning write testing */ 35448 35537 ··· 36183 36028 36184 36029 return 0; 36185 36030 } 36186 - 36187 36031 36188 36032 void farmer_tests(void) 36189 36033 {