maple_tree: add test for expanding range in RCU mode

Add test for expanding range in RCU mode. If we use the fast path of the
slot store to expand range in RCU mode, this test will fail.

Link: https://lkml.kernel.org/r/20230628073657.75314-3-zhangpeng.00@bytedance.com
Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com>
Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Peng Zhang 2023-06-28 15:36:55 +08:00 committed by Andrew Morton
parent d6e8d0dc19
commit c38d9ff2cc
1 changed files with 75 additions and 0 deletions

View File

@ -45,6 +45,13 @@ struct rcu_test_struct2 {
unsigned long last[RCU_RANGE_COUNT];
};
struct rcu_test_struct3 {
struct maple_tree *mt;
unsigned long index;
unsigned long last;
bool stop;
};
struct rcu_reader_struct {
unsigned int id;
int mod;
@ -34954,6 +34961,70 @@ void run_check_rcu(struct maple_tree *mt, struct rcu_test_struct *vals)
MT_BUG_ON(mt, !vals->seen_entry2);
}
static void *rcu_slot_store_reader(void *ptr)
{
struct rcu_test_struct3 *test = ptr;
MA_STATE(mas, test->mt, test->index, test->index);
rcu_register_thread();
rcu_read_lock();
while (!test->stop) {
mas_walk(&mas);
/* The length of growth to both sides must be equal. */
RCU_MT_BUG_ON(test, (test->index - mas.index) !=
(mas.last - test->last));
}
rcu_read_unlock();
rcu_unregister_thread();
return NULL;
}
static noinline void run_check_rcu_slot_store(struct maple_tree *mt)
{
pthread_t readers[20];
int range_cnt = 200, i, limit = 10000;
unsigned long len = ULONG_MAX / range_cnt, start, end;
struct rcu_test_struct3 test = {.stop = false, .mt = mt};
start = range_cnt / 2 * len;
end = start + len - 1;
test.index = start;
test.last = end;
for (i = 0; i < range_cnt; i++) {
mtree_store_range(mt, i * len, i * len + len - 1,
xa_mk_value(i * 100), GFP_KERNEL);
}
mt_set_in_rcu(mt);
MT_BUG_ON(mt, !mt_in_rcu(mt));
for (i = 0; i < ARRAY_SIZE(readers); i++) {
if (pthread_create(&readers[i], NULL, rcu_slot_store_reader,
&test)) {
perror("creating reader thread");
exit(1);
}
}
usleep(5);
while (limit--) {
/* Step by step, expand the most middle range to both sides. */
mtree_store_range(mt, --start, ++end, xa_mk_value(100),
GFP_KERNEL);
}
test.stop = true;
while (i--)
pthread_join(readers[i], NULL);
mt_validate(mt);
}
static noinline
void run_check_rcu_slowread(struct maple_tree *mt, struct rcu_test_struct *vals)
{
@ -35206,6 +35277,10 @@ static noinline void __init check_rcu_threaded(struct maple_tree *mt)
run_check_rcu(mt, &vals);
mtree_destroy(mt);
/* Check expanding range in RCU mode */
mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
run_check_rcu_slot_store(mt);
mtree_destroy(mt);
/* Forward writer for rcu stress */
mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);