Skip to content

Commit ccaf3ef

Browse files
RichardWeiYangakpm00
authored andcommitted
lib/interval_tree: add test case for span iteration
Verify interval_tree_span_iter_xxx() helpers works as expected. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Wei Yang <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Michel Lespinasse <[email protected]> Cc: Jason Gunthorpe <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 82114e4 commit ccaf3ef

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

lib/interval_tree_test.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/slab.h>
77
#include <asm/timex.h>
88
#include <linux/bitmap.h>
9+
#include <linux/maple_tree.h>
910

1011
#define __param(type, name, init, msg) \
1112
static type name = init; \
@@ -193,6 +194,121 @@ static int intersection_range_check(void)
193194
return 0;
194195
}
195196

197+
#ifdef CONFIG_INTERVAL_TREE_SPAN_ITER
198+
/*
199+
* Helper function to get span of current position from maple tree point of
200+
* view.
201+
*/
202+
static void mas_cur_span(struct ma_state *mas, struct interval_tree_span_iter *state)
203+
{
204+
unsigned long cur_start;
205+
unsigned long cur_last;
206+
int is_hole;
207+
208+
if (mas->status == ma_overflow)
209+
return;
210+
211+
/* walk to current position */
212+
state->is_hole = mas_walk(mas) ? 0 : 1;
213+
214+
cur_start = mas->index < state->first_index ?
215+
state->first_index : mas->index;
216+
217+
/* whether we have followers */
218+
do {
219+
220+
cur_last = mas->last > state->last_index ?
221+
state->last_index : mas->last;
222+
223+
is_hole = mas_next_range(mas, state->last_index) ? 0 : 1;
224+
225+
} while (mas->status != ma_overflow && is_hole == state->is_hole);
226+
227+
if (state->is_hole) {
228+
state->start_hole = cur_start;
229+
state->last_hole = cur_last;
230+
} else {
231+
state->start_used = cur_start;
232+
state->last_used = cur_last;
233+
}
234+
235+
/* advance position for next round */
236+
if (mas->status != ma_overflow)
237+
mas_set(mas, cur_last + 1);
238+
}
239+
240+
static int span_iteration_check(void)
241+
{
242+
int i, j, k;
243+
unsigned long start, last;
244+
struct interval_tree_span_iter span, mas_span;
245+
246+
DEFINE_MTREE(tree);
247+
248+
MA_STATE(mas, &tree, 0, 0);
249+
250+
printk(KERN_ALERT "interval tree span iteration\n");
251+
252+
for (i = 0; i < search_loops; i++) {
253+
/* Initialize interval tree for each round */
254+
init();
255+
for (j = 0; j < nnodes; j++)
256+
interval_tree_insert(nodes + j, &root);
257+
258+
/* Put all the range into maple tree */
259+
mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
260+
mt_set_in_rcu(&tree);
261+
262+
for (j = 0; j < nnodes; j++)
263+
WARN_ON_ONCE(mtree_store_range(&tree, nodes[j].start,
264+
nodes[j].last, nodes + j, GFP_KERNEL));
265+
266+
/* Let's try nsearches different ranges */
267+
for (k = 0; k < nsearches; k++) {
268+
/* Try whole range once */
269+
if (!k) {
270+
start = 0UL;
271+
last = ULONG_MAX;
272+
} else {
273+
last = (prandom_u32_state(&rnd) >> 4) % max_endpoint;
274+
start = (prandom_u32_state(&rnd) >> 4) % last;
275+
}
276+
277+
mas_span.first_index = start;
278+
mas_span.last_index = last;
279+
mas_span.is_hole = -1;
280+
mas_set(&mas, start);
281+
282+
interval_tree_for_each_span(&span, &root, start, last) {
283+
mas_cur_span(&mas, &mas_span);
284+
285+
WARN_ON_ONCE(span.is_hole != mas_span.is_hole);
286+
287+
if (span.is_hole) {
288+
WARN_ON_ONCE(span.start_hole != mas_span.start_hole);
289+
WARN_ON_ONCE(span.last_hole != mas_span.last_hole);
290+
} else {
291+
WARN_ON_ONCE(span.start_used != mas_span.start_used);
292+
WARN_ON_ONCE(span.last_used != mas_span.last_used);
293+
}
294+
}
295+
296+
}
297+
298+
WARN_ON_ONCE(mas.status != ma_overflow);
299+
300+
/* Cleanup maple tree for each round */
301+
mtree_destroy(&tree);
302+
/* Cleanup interval tree for each round */
303+
for (j = 0; j < nnodes; j++)
304+
interval_tree_remove(nodes + j, &root);
305+
}
306+
return 0;
307+
}
308+
#else
309+
static inline int span_iteration_check(void) {return 0; }
310+
#endif
311+
196312
static int interval_tree_test_init(void)
197313
{
198314
nodes = kmalloc_array(nnodes, sizeof(struct interval_tree_node),
@@ -211,6 +327,7 @@ static int interval_tree_test_init(void)
211327
basic_check();
212328
search_check();
213329
intersection_range_check();
330+
span_iteration_check();
214331

215332
kfree(queries);
216333
kfree(nodes);

tools/testing/rbtree/Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
.PHONY: clean
44

55
TARGETS = rbtree_test interval_tree_test
6-
OFILES = $(LIBS) rbtree-shim.o interval_tree-shim.o
6+
OFILES = $(SHARED_OFILES) rbtree-shim.o interval_tree-shim.o maple-shim.o
77
DEPS = ../../../include/linux/rbtree.h \
88
../../../include/linux/rbtree_types.h \
99
../../../include/linux/rbtree_augmented.h \
@@ -25,7 +25,9 @@ $(TARGETS): $(OFILES)
2525
rbtree-shim.o: $(DEPS)
2626
rbtree_test.o: ../../../lib/rbtree_test.c
2727
interval_tree-shim.o: $(DEPS)
28+
interval_tree-shim.o: CFLAGS += -DCONFIG_INTERVAL_TREE_SPAN_ITER
2829
interval_tree_test.o: ../../../lib/interval_tree_test.c
30+
interval_tree_test.o: CFLAGS += -DCONFIG_INTERVAL_TREE_SPAN_ITER
2931

3032
clean:
31-
$(RM) $(TARGETS) *.o generated/*
33+
$(RM) $(TARGETS) *.o radix-tree.c idr.c generated/*

tools/testing/rbtree/interval_tree_test.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/math64.h>
77
#include <linux/kern_levels.h>
88
#include "shared.h"
9+
#include "maple-shared.h"
910

1011
#include "../../../lib/interval_tree_test.c"
1112

@@ -51,6 +52,7 @@ int main(int argc, char **argv)
5152
usage();
5253
}
5354

55+
maple_tree_init();
5456
interval_tree_tests();
5557
return 0;
5658
}

0 commit comments

Comments
 (0)