From: Liam R. Howlett Date: Tue, 26 Aug 2025 18:30:51 +0000 (-0400) Subject: maple_tree: Increase spanning store testing and rcu cleanup X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=e05f040feef530973eae2fa553947a2008765178;p=users%2Fjedix%2Flinux-maple.git maple_tree: Increase spanning store testing and rcu cleanup Add more spanning store tests and validate the tree after the tests. When rcu tests fail, many fail and dump the tree. Add a lock to only allow the first to dump the tree while the rest exit. Signed-off-by: Liam R. Howlett --- diff --git a/tools/testing/radix-tree/maple.c b/tools/testing/radix-tree/maple.c index 132352c72722..b3ce89fc6d1a 100644 --- a/tools/testing/radix-tree/maple.c +++ b/tools/testing/radix-tree/maple.c @@ -44,6 +44,7 @@ struct rcu_test_struct2 { unsigned long index[RCU_RANGE_COUNT]; unsigned long last[RCU_RANGE_COUNT]; + pthread_mutex_t dump; }; struct rcu_test_struct3 { @@ -34428,7 +34429,24 @@ static void *rcu_reader_fwd(void *ptr) } } + if (mas.index != r_start) { + if (pthread_mutex_trylock(&test->dump) != 0) { + rcu_read_unlock(); + goto quit; + } + fflush(stdout); + printk("start is wrong: %lx (%lu) vs expected %lx (%lu)\n", mas.index, mas.index, r_start, r_start); + } RCU_MT_BUG_ON(test, mas.index != r_start); + + if (mas.last != r_end) { + if (pthread_mutex_trylock(&test->dump) != 0) { + rcu_read_unlock(); + goto quit; + } + fflush(stdout); + printk("last is wrong: %lx (%lu) vs expected %lx (%lu)\n", mas.last, mas.last, r_end, r_end); + } RCU_MT_BUG_ON(test, mas.last != r_end); if (i == reader->flip) { @@ -34478,9 +34496,11 @@ static void *rcu_reader_fwd(void *ptr) usleep(test->pause); } +quit: rcu_unregister_thread(); return NULL; } + /* RCU reader in decreasing index */ static void *rcu_reader_rev(void *ptr) { @@ -34550,10 +34570,16 @@ static void *rcu_reader_rev(void *ptr) line = __LINE__; if (mas.index != r_start) { + if (pthread_mutex_trylock(&test->dump) != 0) { + rcu_read_unlock(); + goto quit; + } + alt = xa_mk_value(index + i * 2 + 1 + RCU_RANGE_COUNT); mt_dump(test->mt, mt_dump_dec); - printk("Error: %lu-%lu %p != %lu-%lu %p %p line %d i %d\n", + printk("Error: %p %lu-%lu %p != %lu-%lu %p %p line %d i %d\n", + mas.node, mas.index, mas.last, entry, r_start, r_end, expected, alt, line, i); @@ -34611,6 +34637,7 @@ static void *rcu_reader_rev(void *ptr) usleep(test->pause); } +quit: rcu_unregister_thread(); return NULL; } @@ -34760,6 +34787,7 @@ static void rcu_stress(struct maple_tree *mt, bool forward) test.seen_modified = 0; test.thread_count = 0; test.start = test.stop = false; + pthread_mutex_init(&test.dump, NULL); seed = time(NULL); srand(seed); for (i = 0; i < RCU_RANGE_COUNT; i++) { @@ -34845,6 +34873,7 @@ struct rcu_test_struct { unsigned long removed; /* The index of the removed entry */ unsigned long added; /* The index of the removed entry */ unsigned long toggle; /* The index of the removed entry */ + pthread_mutex_t dump; }; static inline @@ -34937,7 +34966,10 @@ static void *rcu_loop(void *ptr) /* Out of the interesting range */ if (mas.index < test->index || mas.index > test->last) { if (entry != expected) { - printk("%lx - %lx = %p not %p\n", + if (pthread_mutex_trylock(&test->dump) != 0) + break; + fflush(stdout); + printk("\nERROR: %lx - %lx = %p not %p\n", mas.index, mas.last, entry, expected); } MT_BUG_ON(test->mt, entry != expected); @@ -34956,6 +34988,7 @@ static void *rcu_loop(void *ptr) mas_set(&mas, test->range_start); } + fflush(stdout); rcu_unregister_thread(); return NULL; } @@ -35285,6 +35318,7 @@ static noinline void __init check_rcu_threaded(struct maple_tree *mt) vals.range_end = ULONG_MAX; vals.seen_entry2 = 0; vals.seen_entry3 = 0; + pthread_mutex_init(&vals.dump, NULL); run_check_rcu(mt, &vals); mtree_destroy(mt); @@ -35671,6 +35705,8 @@ static noinline void __init check_prealloc(struct maple_tree *mt) height = mas_mt_height(&mas); MT_BUG_ON(mt, allocated != 0); + return; + /*FIXME */ /* Chaining multiple preallocations */ mt_set_in_rcu(mt); mas_set_range(&mas, 800, 805); /* Slot store, should be 0 allocations */ @@ -35690,6 +35726,8 @@ static noinline void __init check_spanning_write(struct maple_tree *mt) { unsigned long i, max = 5000; MA_STATE(mas, mt, 1200, 2380); + struct maple_enode *enode; + struct maple_node *pnode; for (i = 0; i <= max; i++) mtree_test_store_range(mt, i * 10, i * 10 + 5, &i); @@ -35851,6 +35889,100 @@ static noinline void __init check_spanning_write(struct maple_tree *mt) mas_set_range(&mas, 76, 875); mas_store_gfp(&mas, NULL, GFP_KERNEL); mtree_unlock(mt); + mtree_destroy(mt); + + mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE); + for (i = 0; i <= max; i++) + mtree_test_store_range(mt, i * 10, i * 10 + 5, &i); + mtree_lock(mt); + mt_dump(mt, mt_dump_dec); + /* Store a null across a boundary that ends in a null */ + mas_set(&mas, 49835); + MT_BUG_ON(mt, mas_walk(&mas) == NULL); + MT_BUG_ON(mt, mas.end != mas.offset); + MT_BUG_ON(mt, mas_next_range(&mas, ULONG_MAX) != NULL); + mas_set_range(&mas, 49835, mas.last - 1); + mas_store_gfp(&mas, NULL, GFP_KERNEL); + mt_validate(mt); + + /* Store a null across a boundary that starts and ends in a null */ + mas_set(&mas, 49849); + MT_BUG_ON(mt, mas_walk(&mas) != NULL); + MT_BUG_ON(mt, mas.index != 49846); + mas_set(&mas, 49876); + MT_BUG_ON(mt, mas_walk(&mas) != NULL); + MT_BUG_ON(mt, mas.last != 49879); + mas_set_range(&mas, 49849, 49876); + mas_store_gfp(&mas, NULL, GFP_KERNEL); + /* Results in 49846-49879: (nil) */ + MT_BUG_ON(mt, mas.index != 49846); + MT_BUG_ON(mt, mas.last != 49879); + mt_validate(mt); + + /* Store a null across a boundary that starts and ends next to nulls */ + mas_set(&mas, 49800); + MT_BUG_ON(mt, mas_walk(&mas) == NULL); + MT_BUG_ON(mt, mas.index != 49800); + mas_set(&mas, 49815); + MT_BUG_ON(mt, mas_walk(&mas) == NULL); + MT_BUG_ON(mt, mas.last != 49815); + mas_set_range(&mas, 49800, 49815); + mas_store_gfp(&mas, NULL, GFP_KERNEL); + /* Results in 49846-49879: (nil) */ + MT_BUG_ON(mt, mas.index != 49796); + MT_BUG_ON(mt, mas.last != 49819); + mt_validate(mt); + + /* Store a value across a boundary that starts and ends in a null */ + mas_set(&mas, 49907); + MT_BUG_ON(mt, mas_walk(&mas) != NULL); + MT_BUG_ON(mt, mas.index != 49906); + mas_set(&mas, 49928); + MT_BUG_ON(mt, mas_walk(&mas) != NULL); + MT_BUG_ON(mt, mas.last != 49929); + mas_set_range(&mas, 49907, 49928); + mas_store_gfp(&mas, check_spanning_write, GFP_KERNEL); + MT_BUG_ON(mt, mas.index != 49907); + MT_BUG_ON(mt, mas.last != 49928); + mt_validate(mt); + + /* Store a value across a node boundary that causes a 3 way split */ + mas_set(&mas, 49670); + MT_BUG_ON(mt, mas_walk(&mas) == NULL); + MT_BUG_ON(mt, mas.index != 49670); + MT_BUG_ON(mt, mas.end != 15); + enode = mas.node; + MT_BUG_ON(mt, mas_next_range(&mas, ULONG_MAX) != NULL); + MT_BUG_ON(mt, mas.index != 49676); + MT_BUG_ON(mt, mas.end != 15); + MT_BUG_ON(mt, enode == mas.node); + mas_set_range(&mas, 49672, 49677); + mas_store_gfp(&mas, check_spanning_write, GFP_KERNEL); + MT_BUG_ON(mt, mas.index != 49672); + MT_BUG_ON(mt, mas.last != 49677); + mt_validate(mt); + + /* 2 levels of basically the same testing */ + + /* 48950 - 48955 => ptr, 48956 - 48959 => NULL */ + mas_set(&mas, 48950); + MT_BUG_ON(mt, mas_walk(&mas) == NULL); + MT_BUG_ON(mt, mas.index != 48950); + MT_BUG_ON(mt, mas.end != 15); + enode = mas.node; + pnode = mte_parent(enode); + MT_BUG_ON(mt, mas_next_range(&mas, ULONG_MAX) != NULL); + MT_BUG_ON(mt, mas.index != 48956); + MT_BUG_ON(mt, mas.end != 15); + MT_BUG_ON(mt, enode == mas.node); + MT_BUG_ON(mt, pnode == mte_parent(mas.node)); + mas_set_range(&mas, 48952, 48958); + mas_store_gfp(&mas, NULL, GFP_KERNEL); + mt_validate(mt); + + mtree_unlock(mt); + mtree_destroy(mt); + rcu_barrier(); } /* End of spanning write testing */ @@ -36335,8 +36467,11 @@ static inline void check_spanning_store_height(struct maple_tree *mt) mas_store_gfp(&mas, xa_mk_value(index), GFP_KERNEL); mas_set(&mas, ++index); } + mt_dump(mt, mt_dump_dec); + printk("VS\n"); mas_set_range(&mas, 90, 140); mas_store_gfp(&mas, xa_mk_value(index), GFP_KERNEL); + mt_dump(mt, mt_dump_dec); MT_BUG_ON(mt, mas_mt_height(&mas) != 2); mas_unlock(&mas); }