Commit c38d9ff2 authored by Peng Zhang's avatar Peng Zhang Committed by Andrew Morton

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.comSigned-off-by: default avatarPeng Zhang <zhangpeng.00@bytedance.com>
Reviewed-by: default avatarLiam R. Howlett <Liam.Howlett@oracle.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent d6e8d0dc
...@@ -45,6 +45,13 @@ struct rcu_test_struct2 { ...@@ -45,6 +45,13 @@ struct rcu_test_struct2 {
unsigned long last[RCU_RANGE_COUNT]; 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 { struct rcu_reader_struct {
unsigned int id; unsigned int id;
int mod; int mod;
...@@ -34954,6 +34961,70 @@ void run_check_rcu(struct maple_tree *mt, struct rcu_test_struct *vals) ...@@ -34954,6 +34961,70 @@ void run_check_rcu(struct maple_tree *mt, struct rcu_test_struct *vals)
MT_BUG_ON(mt, !vals->seen_entry2); 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 static noinline
void run_check_rcu_slowread(struct maple_tree *mt, struct rcu_test_struct *vals) 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) ...@@ -35206,6 +35277,10 @@ static noinline void __init check_rcu_threaded(struct maple_tree *mt)
run_check_rcu(mt, &vals); run_check_rcu(mt, &vals);
mtree_destroy(mt); 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 */ /* Forward writer for rcu stress */
mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE); mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment