]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Increase spanning store testing and rcu cleanup
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Tue, 26 Aug 2025 18:30:51 +0000 (14:30 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Tue, 26 Aug 2025 18:32:23 +0000 (14:32 -0400)
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 <Liam.Howlett@oracle.com>
tools/testing/radix-tree/maple.c

index 132352c72722ca98c3f629385448219278b2506b..b3ce89fc6d1a4450c7d5fb9c11a32547963237fe 100644 (file)
@@ -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);
 }