diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-07 13:52:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-07 13:52:26 -0500 |
commit | 9e91c144e689bb780b412c2c7908b9cf7b96f31f (patch) | |
tree | 8fe573a54384a1ff54fc0022fa6285ac9f557779 | |
parent | f7d6a7283aa1de430c6323a9714d1a787bc2d1ea (diff) | |
parent | f0f3f2d0a3e0f7c48163fd8b45f5909d46e7f371 (diff) |
Merge branch 'idr-4.11' of git://git.infradead.org/users/willy/linux-dax
Pull idr fix (and new tests) from Matthew Wilcox:
"One urgent patch in here; freeing the correct IDA bitmap.
Everything else is changes to the test suite"
* 'idr-4.11' of git://git.infradead.org/users/willy/linux-dax:
radix tree test suite: Specify -m32 in LDFLAGS too
ida: Free correct IDA bitmap
radix tree test suite: Depend on Makefile and quieten grep
radix tree test suite: Fix build with --as-needed
radix tree test suite: Build 32 bit binaries
radix tree test suite: Add performance test for radix_tree_join()
radix tree test suite: Add performance test for radix_tree_split()
radix tree test suite: Add performance benchmarks
radix tree test suite: Add test for radix_tree_clear_tags()
radix tree test suite: Add tests for ida_simple_get() and ida_simple_remove()
radix tree test suite: Add test for idr_get_next()
-rw-r--r-- | lib/radix-tree.c | 4 | ||||
-rw-r--r-- | tools/testing/radix-tree/Makefile | 15 | ||||
-rw-r--r-- | tools/testing/radix-tree/benchmark.c | 173 | ||||
-rw-r--r-- | tools/testing/radix-tree/idr-test.c | 78 | ||||
-rw-r--r-- | tools/testing/radix-tree/main.c | 1 | ||||
-rw-r--r-- | tools/testing/radix-tree/tag_check.c | 29 | ||||
-rw-r--r-- | tools/testing/radix-tree/test.h | 1 |
7 files changed, 283 insertions, 18 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 5ed506d648c4..691a9ad48497 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -2129,8 +2129,8 @@ int ida_pre_get(struct ida *ida, gfp_t gfp) | |||
2129 | struct ida_bitmap *bitmap = kmalloc(sizeof(*bitmap), gfp); | 2129 | struct ida_bitmap *bitmap = kmalloc(sizeof(*bitmap), gfp); |
2130 | if (!bitmap) | 2130 | if (!bitmap) |
2131 | return 0; | 2131 | return 0; |
2132 | bitmap = this_cpu_cmpxchg(ida_bitmap, NULL, bitmap); | 2132 | if (this_cpu_cmpxchg(ida_bitmap, NULL, bitmap)) |
2133 | kfree(bitmap); | 2133 | kfree(bitmap); |
2134 | } | 2134 | } |
2135 | 2135 | ||
2136 | return 1; | 2136 | return 1; |
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile index f11315bedefc..6a9480c03cbd 100644 --- a/tools/testing/radix-tree/Makefile +++ b/tools/testing/radix-tree/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | 1 | ||
2 | CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE -fsanitize=address | 2 | CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE -fsanitize=address |
3 | LDFLAGS += -lpthread -lurcu | 3 | LDFLAGS += -fsanitize=address |
4 | LDLIBS+= -lpthread -lurcu | ||
4 | TARGETS = main idr-test multiorder | 5 | TARGETS = main idr-test multiorder |
5 | CORE_OFILES := radix-tree.o idr.o linux.o test.o find_bit.o | 6 | CORE_OFILES := radix-tree.o idr.o linux.o test.o find_bit.o |
6 | OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ | 7 | OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ |
@@ -10,23 +11,25 @@ ifndef SHIFT | |||
10 | SHIFT=3 | 11 | SHIFT=3 |
11 | endif | 12 | endif |
12 | 13 | ||
14 | ifeq ($(BUILD), 32) | ||
15 | CFLAGS += -m32 | ||
16 | LDFLAGS += -m32 | ||
17 | endif | ||
18 | |||
13 | targets: mapshift $(TARGETS) | 19 | targets: mapshift $(TARGETS) |
14 | 20 | ||
15 | main: $(OFILES) | 21 | main: $(OFILES) |
16 | $(CC) $(CFLAGS) $(LDFLAGS) $^ -o main | ||
17 | 22 | ||
18 | idr-test: idr-test.o $(CORE_OFILES) | 23 | idr-test: idr-test.o $(CORE_OFILES) |
19 | $(CC) $(CFLAGS) $(LDFLAGS) $^ -o idr-test | ||
20 | 24 | ||
21 | multiorder: multiorder.o $(CORE_OFILES) | 25 | multiorder: multiorder.o $(CORE_OFILES) |
22 | $(CC) $(CFLAGS) $(LDFLAGS) $^ -o multiorder | ||
23 | 26 | ||
24 | clean: | 27 | clean: |
25 | $(RM) $(TARGETS) *.o radix-tree.c idr.c generated/map-shift.h | 28 | $(RM) $(TARGETS) *.o radix-tree.c idr.c generated/map-shift.h |
26 | 29 | ||
27 | vpath %.c ../../lib | 30 | vpath %.c ../../lib |
28 | 31 | ||
29 | $(OFILES): *.h */*.h generated/map-shift.h \ | 32 | $(OFILES): Makefile *.h */*.h generated/map-shift.h \ |
30 | ../../include/linux/*.h \ | 33 | ../../include/linux/*.h \ |
31 | ../../include/asm/*.h \ | 34 | ../../include/asm/*.h \ |
32 | ../../../include/linux/radix-tree.h \ | 35 | ../../../include/linux/radix-tree.h \ |
@@ -41,7 +44,7 @@ idr.c: ../../../lib/idr.c | |||
41 | .PHONY: mapshift | 44 | .PHONY: mapshift |
42 | 45 | ||
43 | mapshift: | 46 | mapshift: |
44 | @if ! grep -qw $(SHIFT) generated/map-shift.h; then \ | 47 | @if ! grep -qws $(SHIFT) generated/map-shift.h; then \ |
45 | echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \ | 48 | echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \ |
46 | generated/map-shift.h; \ | 49 | generated/map-shift.h; \ |
47 | fi | 50 | fi |
diff --git a/tools/testing/radix-tree/benchmark.c b/tools/testing/radix-tree/benchmark.c index 9b09ddfe462f..99c40f3ed133 100644 --- a/tools/testing/radix-tree/benchmark.c +++ b/tools/testing/radix-tree/benchmark.c | |||
@@ -17,6 +17,9 @@ | |||
17 | #include <time.h> | 17 | #include <time.h> |
18 | #include "test.h" | 18 | #include "test.h" |
19 | 19 | ||
20 | #define for_each_index(i, base, order) \ | ||
21 | for (i = base; i < base + (1 << order); i++) | ||
22 | |||
20 | #define NSEC_PER_SEC 1000000000L | 23 | #define NSEC_PER_SEC 1000000000L |
21 | 24 | ||
22 | static long long benchmark_iter(struct radix_tree_root *root, bool tagged) | 25 | static long long benchmark_iter(struct radix_tree_root *root, bool tagged) |
@@ -57,27 +60,176 @@ again: | |||
57 | return nsec; | 60 | return nsec; |
58 | } | 61 | } |
59 | 62 | ||
63 | static void benchmark_insert(struct radix_tree_root *root, | ||
64 | unsigned long size, unsigned long step, int order) | ||
65 | { | ||
66 | struct timespec start, finish; | ||
67 | unsigned long index; | ||
68 | long long nsec; | ||
69 | |||
70 | clock_gettime(CLOCK_MONOTONIC, &start); | ||
71 | |||
72 | for (index = 0 ; index < size ; index += step) | ||
73 | item_insert_order(root, index, order); | ||
74 | |||
75 | clock_gettime(CLOCK_MONOTONIC, &finish); | ||
76 | |||
77 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + | ||
78 | (finish.tv_nsec - start.tv_nsec); | ||
79 | |||
80 | printv(2, "Size: %8ld, step: %8ld, order: %d, insertion: %15lld ns\n", | ||
81 | size, step, order, nsec); | ||
82 | } | ||
83 | |||
84 | static void benchmark_tagging(struct radix_tree_root *root, | ||
85 | unsigned long size, unsigned long step, int order) | ||
86 | { | ||
87 | struct timespec start, finish; | ||
88 | unsigned long index; | ||
89 | long long nsec; | ||
90 | |||
91 | clock_gettime(CLOCK_MONOTONIC, &start); | ||
92 | |||
93 | for (index = 0 ; index < size ; index += step) | ||
94 | radix_tree_tag_set(root, index, 0); | ||
95 | |||
96 | clock_gettime(CLOCK_MONOTONIC, &finish); | ||
97 | |||
98 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + | ||
99 | (finish.tv_nsec - start.tv_nsec); | ||
100 | |||
101 | printv(2, "Size: %8ld, step: %8ld, order: %d, tagging: %17lld ns\n", | ||
102 | size, step, order, nsec); | ||
103 | } | ||
104 | |||
105 | static void benchmark_delete(struct radix_tree_root *root, | ||
106 | unsigned long size, unsigned long step, int order) | ||
107 | { | ||
108 | struct timespec start, finish; | ||
109 | unsigned long index, i; | ||
110 | long long nsec; | ||
111 | |||
112 | clock_gettime(CLOCK_MONOTONIC, &start); | ||
113 | |||
114 | for (index = 0 ; index < size ; index += step) | ||
115 | for_each_index(i, index, order) | ||
116 | item_delete(root, i); | ||
117 | |||
118 | clock_gettime(CLOCK_MONOTONIC, &finish); | ||
119 | |||
120 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + | ||
121 | (finish.tv_nsec - start.tv_nsec); | ||
122 | |||
123 | printv(2, "Size: %8ld, step: %8ld, order: %d, deletion: %16lld ns\n", | ||
124 | size, step, order, nsec); | ||
125 | } | ||
126 | |||
60 | static void benchmark_size(unsigned long size, unsigned long step, int order) | 127 | static void benchmark_size(unsigned long size, unsigned long step, int order) |
61 | { | 128 | { |
62 | RADIX_TREE(tree, GFP_KERNEL); | 129 | RADIX_TREE(tree, GFP_KERNEL); |
63 | long long normal, tagged; | 130 | long long normal, tagged; |
64 | unsigned long index; | ||
65 | 131 | ||
66 | for (index = 0 ; index < size ; index += step) { | 132 | benchmark_insert(&tree, size, step, order); |
67 | item_insert_order(&tree, index, order); | 133 | benchmark_tagging(&tree, size, step, order); |
68 | radix_tree_tag_set(&tree, index, 0); | ||
69 | } | ||
70 | 134 | ||
71 | tagged = benchmark_iter(&tree, true); | 135 | tagged = benchmark_iter(&tree, true); |
72 | normal = benchmark_iter(&tree, false); | 136 | normal = benchmark_iter(&tree, false); |
73 | 137 | ||
74 | printv(2, "Size %ld, step %6ld, order %d tagged %10lld ns, normal %10lld ns\n", | 138 | printv(2, "Size: %8ld, step: %8ld, order: %d, tagged iteration: %8lld ns\n", |
75 | size, step, order, tagged, normal); | 139 | size, step, order, tagged); |
140 | printv(2, "Size: %8ld, step: %8ld, order: %d, normal iteration: %8lld ns\n", | ||
141 | size, step, order, normal); | ||
142 | |||
143 | benchmark_delete(&tree, size, step, order); | ||
76 | 144 | ||
77 | item_kill_tree(&tree); | 145 | item_kill_tree(&tree); |
78 | rcu_barrier(); | 146 | rcu_barrier(); |
79 | } | 147 | } |
80 | 148 | ||
149 | static long long __benchmark_split(unsigned long index, | ||
150 | int old_order, int new_order) | ||
151 | { | ||
152 | struct timespec start, finish; | ||
153 | long long nsec; | ||
154 | RADIX_TREE(tree, GFP_ATOMIC); | ||
155 | |||
156 | item_insert_order(&tree, index, old_order); | ||
157 | |||
158 | clock_gettime(CLOCK_MONOTONIC, &start); | ||
159 | radix_tree_split(&tree, index, new_order); | ||
160 | clock_gettime(CLOCK_MONOTONIC, &finish); | ||
161 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + | ||
162 | (finish.tv_nsec - start.tv_nsec); | ||
163 | |||
164 | item_kill_tree(&tree); | ||
165 | |||
166 | return nsec; | ||
167 | |||
168 | } | ||
169 | |||
170 | static void benchmark_split(unsigned long size, unsigned long step) | ||
171 | { | ||
172 | int i, j, idx; | ||
173 | long long nsec = 0; | ||
174 | |||
175 | |||
176 | for (idx = 0; idx < size; idx += step) { | ||
177 | for (i = 3; i < 11; i++) { | ||
178 | for (j = 0; j < i; j++) { | ||
179 | nsec += __benchmark_split(idx, i, j); | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | printv(2, "Size %8ld, step %8ld, split time %10lld ns\n", | ||
185 | size, step, nsec); | ||
186 | |||
187 | } | ||
188 | |||
189 | static long long __benchmark_join(unsigned long index, | ||
190 | unsigned order1, unsigned order2) | ||
191 | { | ||
192 | unsigned long loc; | ||
193 | struct timespec start, finish; | ||
194 | long long nsec; | ||
195 | void *item, *item2 = item_create(index + 1, order1); | ||
196 | RADIX_TREE(tree, GFP_KERNEL); | ||
197 | |||
198 | item_insert_order(&tree, index, order2); | ||
199 | item = radix_tree_lookup(&tree, index); | ||
200 | |||
201 | clock_gettime(CLOCK_MONOTONIC, &start); | ||
202 | radix_tree_join(&tree, index + 1, order1, item2); | ||
203 | clock_gettime(CLOCK_MONOTONIC, &finish); | ||
204 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + | ||
205 | (finish.tv_nsec - start.tv_nsec); | ||
206 | |||
207 | loc = find_item(&tree, item); | ||
208 | if (loc == -1) | ||
209 | free(item); | ||
210 | |||
211 | item_kill_tree(&tree); | ||
212 | |||
213 | return nsec; | ||
214 | } | ||
215 | |||
216 | static void benchmark_join(unsigned long step) | ||
217 | { | ||
218 | int i, j, idx; | ||
219 | long long nsec = 0; | ||
220 | |||
221 | for (idx = 0; idx < 1 << 10; idx += step) { | ||
222 | for (i = 1; i < 15; i++) { | ||
223 | for (j = 0; j < i; j++) { | ||
224 | nsec += __benchmark_join(idx, i, j); | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | |||
229 | printv(2, "Size %8d, step %8ld, join time %10lld ns\n", | ||
230 | 1 << 10, step, nsec); | ||
231 | } | ||
232 | |||
81 | void benchmark(void) | 233 | void benchmark(void) |
82 | { | 234 | { |
83 | unsigned long size[] = {1 << 10, 1 << 20, 0}; | 235 | unsigned long size[] = {1 << 10, 1 << 20, 0}; |
@@ -95,4 +247,11 @@ void benchmark(void) | |||
95 | for (c = 0; size[c]; c++) | 247 | for (c = 0; size[c]; c++) |
96 | for (s = 0; step[s]; s++) | 248 | for (s = 0; step[s]; s++) |
97 | benchmark_size(size[c], step[s] << 9, 9); | 249 | benchmark_size(size[c], step[s] << 9, 9); |
250 | |||
251 | for (c = 0; size[c]; c++) | ||
252 | for (s = 0; step[s]; s++) | ||
253 | benchmark_split(size[c], step[s]); | ||
254 | |||
255 | for (s = 0; step[s]; s++) | ||
256 | benchmark_join(step[s]); | ||
98 | } | 257 | } |
diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index a26098c6123d..30cd0b296f1a 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c | |||
@@ -153,6 +153,30 @@ void idr_nowait_test(void) | |||
153 | idr_destroy(&idr); | 153 | idr_destroy(&idr); |
154 | } | 154 | } |
155 | 155 | ||
156 | void idr_get_next_test(void) | ||
157 | { | ||
158 | unsigned long i; | ||
159 | int nextid; | ||
160 | DEFINE_IDR(idr); | ||
161 | |||
162 | int indices[] = {4, 7, 9, 15, 65, 128, 1000, 99999, 0}; | ||
163 | |||
164 | for(i = 0; indices[i]; i++) { | ||
165 | struct item *item = item_create(indices[i], 0); | ||
166 | assert(idr_alloc(&idr, item, indices[i], indices[i+1], | ||
167 | GFP_KERNEL) == indices[i]); | ||
168 | } | ||
169 | |||
170 | for(i = 0, nextid = 0; indices[i]; i++) { | ||
171 | idr_get_next(&idr, &nextid); | ||
172 | assert(nextid == indices[i]); | ||
173 | nextid++; | ||
174 | } | ||
175 | |||
176 | idr_for_each(&idr, item_idr_free, &idr); | ||
177 | idr_destroy(&idr); | ||
178 | } | ||
179 | |||
156 | void idr_checks(void) | 180 | void idr_checks(void) |
157 | { | 181 | { |
158 | unsigned long i; | 182 | unsigned long i; |
@@ -202,6 +226,7 @@ void idr_checks(void) | |||
202 | idr_alloc_test(); | 226 | idr_alloc_test(); |
203 | idr_null_test(); | 227 | idr_null_test(); |
204 | idr_nowait_test(); | 228 | idr_nowait_test(); |
229 | idr_get_next_test(); | ||
205 | } | 230 | } |
206 | 231 | ||
207 | /* | 232 | /* |
@@ -338,7 +363,7 @@ void ida_check_random(void) | |||
338 | { | 363 | { |
339 | DEFINE_IDA(ida); | 364 | DEFINE_IDA(ida); |
340 | DECLARE_BITMAP(bitmap, 2048); | 365 | DECLARE_BITMAP(bitmap, 2048); |
341 | int id; | 366 | int id, err; |
342 | unsigned int i; | 367 | unsigned int i; |
343 | time_t s = time(NULL); | 368 | time_t s = time(NULL); |
344 | 369 | ||
@@ -352,8 +377,11 @@ void ida_check_random(void) | |||
352 | ida_remove(&ida, bit); | 377 | ida_remove(&ida, bit); |
353 | } else { | 378 | } else { |
354 | __set_bit(bit, bitmap); | 379 | __set_bit(bit, bitmap); |
355 | ida_pre_get(&ida, GFP_KERNEL); | 380 | do { |
356 | assert(!ida_get_new_above(&ida, bit, &id)); | 381 | ida_pre_get(&ida, GFP_KERNEL); |
382 | err = ida_get_new_above(&ida, bit, &id); | ||
383 | } while (err == -ENOMEM); | ||
384 | assert(!err); | ||
357 | assert(id == bit); | 385 | assert(id == bit); |
358 | } | 386 | } |
359 | } | 387 | } |
@@ -362,6 +390,24 @@ void ida_check_random(void) | |||
362 | goto repeat; | 390 | goto repeat; |
363 | } | 391 | } |
364 | 392 | ||
393 | void ida_simple_get_remove_test(void) | ||
394 | { | ||
395 | DEFINE_IDA(ida); | ||
396 | unsigned long i; | ||
397 | |||
398 | for (i = 0; i < 10000; i++) { | ||
399 | assert(ida_simple_get(&ida, 0, 20000, GFP_KERNEL) == i); | ||
400 | } | ||
401 | assert(ida_simple_get(&ida, 5, 30, GFP_KERNEL) < 0); | ||
402 | |||
403 | for (i = 0; i < 10000; i++) { | ||
404 | ida_simple_remove(&ida, i); | ||
405 | } | ||
406 | assert(ida_is_empty(&ida)); | ||
407 | |||
408 | ida_destroy(&ida); | ||
409 | } | ||
410 | |||
365 | void ida_checks(void) | 411 | void ida_checks(void) |
366 | { | 412 | { |
367 | DEFINE_IDA(ida); | 413 | DEFINE_IDA(ida); |
@@ -428,15 +474,41 @@ void ida_checks(void) | |||
428 | ida_check_max(); | 474 | ida_check_max(); |
429 | ida_check_conv(); | 475 | ida_check_conv(); |
430 | ida_check_random(); | 476 | ida_check_random(); |
477 | ida_simple_get_remove_test(); | ||
431 | 478 | ||
432 | radix_tree_cpu_dead(1); | 479 | radix_tree_cpu_dead(1); |
433 | } | 480 | } |
434 | 481 | ||
482 | static void *ida_random_fn(void *arg) | ||
483 | { | ||
484 | rcu_register_thread(); | ||
485 | ida_check_random(); | ||
486 | rcu_unregister_thread(); | ||
487 | return NULL; | ||
488 | } | ||
489 | |||
490 | void ida_thread_tests(void) | ||
491 | { | ||
492 | pthread_t threads[10]; | ||
493 | int i; | ||
494 | |||
495 | for (i = 0; i < ARRAY_SIZE(threads); i++) | ||
496 | if (pthread_create(&threads[i], NULL, ida_random_fn, NULL)) { | ||
497 | perror("creating ida thread"); | ||
498 | exit(1); | ||
499 | } | ||
500 | |||
501 | while (i--) | ||
502 | pthread_join(threads[i], NULL); | ||
503 | } | ||
504 | |||
435 | int __weak main(void) | 505 | int __weak main(void) |
436 | { | 506 | { |
437 | radix_tree_init(); | 507 | radix_tree_init(); |
438 | idr_checks(); | 508 | idr_checks(); |
439 | ida_checks(); | 509 | ida_checks(); |
510 | ida_thread_tests(); | ||
511 | radix_tree_cpu_dead(1); | ||
440 | rcu_barrier(); | 512 | rcu_barrier(); |
441 | if (nr_allocated) | 513 | if (nr_allocated) |
442 | printf("nr_allocated = %d\n", nr_allocated); | 514 | printf("nr_allocated = %d\n", nr_allocated); |
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c index b829127d5670..bc9a78449572 100644 --- a/tools/testing/radix-tree/main.c +++ b/tools/testing/radix-tree/main.c | |||
@@ -368,6 +368,7 @@ int main(int argc, char **argv) | |||
368 | iteration_test(0, 10 + 90 * long_run); | 368 | iteration_test(0, 10 + 90 * long_run); |
369 | iteration_test(7, 10 + 90 * long_run); | 369 | iteration_test(7, 10 + 90 * long_run); |
370 | single_thread_tests(long_run); | 370 | single_thread_tests(long_run); |
371 | ida_thread_tests(); | ||
371 | 372 | ||
372 | /* Free any remaining preallocated nodes */ | 373 | /* Free any remaining preallocated nodes */ |
373 | radix_tree_cpu_dead(0); | 374 | radix_tree_cpu_dead(0); |
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c index d4ff00989245..36dcf7d6945d 100644 --- a/tools/testing/radix-tree/tag_check.c +++ b/tools/testing/radix-tree/tag_check.c | |||
@@ -330,6 +330,34 @@ static void single_check(void) | |||
330 | item_kill_tree(&tree); | 330 | item_kill_tree(&tree); |
331 | } | 331 | } |
332 | 332 | ||
333 | void radix_tree_clear_tags_test(void) | ||
334 | { | ||
335 | unsigned long index; | ||
336 | struct radix_tree_node *node; | ||
337 | struct radix_tree_iter iter; | ||
338 | void **slot; | ||
339 | |||
340 | RADIX_TREE(tree, GFP_KERNEL); | ||
341 | |||
342 | item_insert(&tree, 0); | ||
343 | item_tag_set(&tree, 0, 0); | ||
344 | __radix_tree_lookup(&tree, 0, &node, &slot); | ||
345 | radix_tree_clear_tags(&tree, node, slot); | ||
346 | assert(item_tag_get(&tree, 0, 0) == 0); | ||
347 | |||
348 | for (index = 0; index < 1000; index++) { | ||
349 | item_insert(&tree, index); | ||
350 | item_tag_set(&tree, index, 0); | ||
351 | } | ||
352 | |||
353 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { | ||
354 | radix_tree_clear_tags(&tree, iter.node, slot); | ||
355 | assert(item_tag_get(&tree, iter.index, 0) == 0); | ||
356 | } | ||
357 | |||
358 | item_kill_tree(&tree); | ||
359 | } | ||
360 | |||
333 | void tag_check(void) | 361 | void tag_check(void) |
334 | { | 362 | { |
335 | single_check(); | 363 | single_check(); |
@@ -347,4 +375,5 @@ void tag_check(void) | |||
347 | thrash_tags(); | 375 | thrash_tags(); |
348 | rcu_barrier(); | 376 | rcu_barrier(); |
349 | printv(2, "after thrash_tags: %d allocated\n", nr_allocated); | 377 | printv(2, "after thrash_tags: %d allocated\n", nr_allocated); |
378 | radix_tree_clear_tags_test(); | ||
350 | } | 379 | } |
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h index b30e11d9d271..0f8220cc6166 100644 --- a/tools/testing/radix-tree/test.h +++ b/tools/testing/radix-tree/test.h | |||
@@ -36,6 +36,7 @@ void iteration_test(unsigned order, unsigned duration); | |||
36 | void benchmark(void); | 36 | void benchmark(void); |
37 | void idr_checks(void); | 37 | void idr_checks(void); |
38 | void ida_checks(void); | 38 | void ida_checks(void); |
39 | void ida_thread_tests(void); | ||
39 | 40 | ||
40 | struct item * | 41 | struct item * |
41 | item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); | 42 | item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); |