diff options
Diffstat (limited to 'tools/testing/radix-tree/maple.c')
| -rw-r--r-- | tools/testing/radix-tree/maple.c | 134 | 
1 files changed, 107 insertions, 27 deletions
diff --git a/tools/testing/radix-tree/maple.c b/tools/testing/radix-tree/maple.c index 75ea2081a317..e5da1cad70ba 100644 --- a/tools/testing/radix-tree/maple.c +++ b/tools/testing/radix-tree/maple.c @@ -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); @@ -35383,7 +35458,9 @@ static noinline void __init check_prealloc(struct maple_tree *mt)  	for (i = 0; i <= max; i++)  		mtree_test_store_range(mt, i * 10, i * 10 + 5, &i); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	/* Spanning store */ +	mas_set_range(&mas, 470, 500); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas);  	MT_BUG_ON(mt, allocated == 0); @@ -35392,105 +35469,108 @@ static noinline void __init check_prealloc(struct maple_tree *mt)  	allocated = mas_allocated(&mas);  	MT_BUG_ON(mt, allocated != 0); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas);  	MT_BUG_ON(mt, allocated == 0);  	MT_BUG_ON(mt, allocated != 1 + height * 3); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	mas_destroy(&mas);  	allocated = mas_allocated(&mas);  	MT_BUG_ON(mt, allocated != 0); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas); -	MT_BUG_ON(mt, allocated == 0);  	MT_BUG_ON(mt, allocated != 1 + height * 3);  	mn = mas_pop_node(&mas);  	MT_BUG_ON(mt, mas_allocated(&mas) != allocated - 1);  	mn->parent = ma_parent_ptr(mn);  	ma_free_rcu(mn); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	mas_destroy(&mas);  	allocated = mas_allocated(&mas);  	MT_BUG_ON(mt, allocated != 0); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas); -	MT_BUG_ON(mt, allocated == 0);  	MT_BUG_ON(mt, allocated != 1 + height * 3);  	mn = mas_pop_node(&mas);  	MT_BUG_ON(mt, mas_allocated(&mas) != allocated - 1); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	mas_destroy(&mas);  	allocated = mas_allocated(&mas);  	MT_BUG_ON(mt, allocated != 0);  	mn->parent = ma_parent_ptr(mn);  	ma_free_rcu(mn); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas); -	MT_BUG_ON(mt, allocated == 0);  	MT_BUG_ON(mt, allocated != 1 + height * 3);  	mn = mas_pop_node(&mas);  	MT_BUG_ON(mt, mas_allocated(&mas) != allocated - 1);  	mas_push_node(&mas, mn);  	MT_BUG_ON(mt, mas_allocated(&mas) != allocated); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	mas_destroy(&mas);  	allocated = mas_allocated(&mas);  	MT_BUG_ON(mt, allocated != 0); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas); -	MT_BUG_ON(mt, allocated == 0);  	MT_BUG_ON(mt, allocated != 1 + height * 3);  	mas_store_prealloc(&mas, ptr);  	MT_BUG_ON(mt, mas_allocated(&mas) != 0); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	/* Slot store does not need allocations */ +	mas_set_range(&mas, 6, 9); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas); -	height = mas_mt_height(&mas); -	MT_BUG_ON(mt, allocated == 0); -	MT_BUG_ON(mt, allocated != 1 + height * 3); +	MT_BUG_ON(mt, allocated != 0);  	mas_store_prealloc(&mas, ptr);  	MT_BUG_ON(mt, mas_allocated(&mas) != 0); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); + +	mas_set_range(&mas, 6, 10); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas); -	MT_BUG_ON(mt, allocated == 0); -	MT_BUG_ON(mt, allocated != 1 + height * 3); +	MT_BUG_ON(mt, allocated != 1);  	mas_store_prealloc(&mas, ptr); +	MT_BUG_ON(mt, mas_allocated(&mas) != 0); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	/* Split */ +	mas_set_range(&mas, 54, 54); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas); -	MT_BUG_ON(mt, allocated == 0); -	MT_BUG_ON(mt, allocated != 1 + height * 3); +	MT_BUG_ON(mt, allocated != 1 + height * 2);  	mas_store_prealloc(&mas, ptr);  	MT_BUG_ON(mt, mas_allocated(&mas) != 0);  	mt_set_non_kernel(1); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL & GFP_NOWAIT) == 0); +	/* Spanning store */ +	mas_set_range(&mas, 1, 100); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL & GFP_NOWAIT) == 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas);  	MT_BUG_ON(mt, allocated != 0);  	mas_destroy(&mas); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0); +	/* Spanning store */ +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL) != 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas);  	MT_BUG_ON(mt, allocated == 0);  	MT_BUG_ON(mt, allocated != 1 + height * 3);  	mas_store_prealloc(&mas, ptr);  	MT_BUG_ON(mt, mas_allocated(&mas) != 0); +	mas_set_range(&mas, 0, 200);  	mt_set_non_kernel(1); -	MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL & GFP_NOWAIT) == 0); +	MT_BUG_ON(mt, mas_preallocate(&mas, ptr, GFP_KERNEL & GFP_NOWAIT) == 0);  	allocated = mas_allocated(&mas);  	height = mas_mt_height(&mas);  	MT_BUG_ON(mt, allocated != 0);  | 
