summaryrefslogtreecommitdiffstats
path: root/tools/testing/radix-tree
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2018-12-06 08:19:13 -0500
committerMatthew Wilcox <willy@infradead.org>2018-12-06 08:26:16 -0500
commiteff3860bbfedbac6edac57fb0d7f3a60e860c1c3 (patch)
tree99b3f3e6321a16cfba84319c4a94a1aa653e68d9 /tools/testing/radix-tree
parentcf76c364a1e1e5224af80edf70a1e3023e1fcf8c (diff)
radix tree: Don't return retry entries from lookup
Commit 66ee620f06f9 ("idr: Permit any valid kernel pointer to be stored") changed the radix tree lookup so that it stops when reaching the bottom of the tree. However, the condition was added in the wrong place, making it possible to return retry entries to the caller. Reorder the tests to check for the retry entry before checking whether we're at the bottom of the tree. The retry entry should never be found in the tree root, so it's safe to defer the check until the end of the loop. Add a regression test to the test-suite to be sure this doesn't come back. Fixes: 66ee620f06f9 ("idr: Permit any valid kernel pointer to be stored") Reported-by: Greg Kurz <groug@kaod.org> Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'tools/testing/radix-tree')
-rw-r--r--tools/testing/radix-tree/Makefile1
-rw-r--r--tools/testing/radix-tree/main.c1
-rw-r--r--tools/testing/radix-tree/regression.h1
-rw-r--r--tools/testing/radix-tree/regression4.c79
4 files changed, 82 insertions, 0 deletions
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index acf1afa01c5b..397d6b612502 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -7,6 +7,7 @@ LDLIBS+= -lpthread -lurcu
7TARGETS = main idr-test multiorder xarray 7TARGETS = main idr-test multiorder xarray
8CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o bitmap.o 8CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o bitmap.o
9OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ 9OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \
10 regression4.o \
10 tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o 11 tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o
11 12
12ifndef SHIFT 13ifndef SHIFT
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index 77a44c54998f..7a22d6e3732e 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -308,6 +308,7 @@ int main(int argc, char **argv)
308 regression1_test(); 308 regression1_test();
309 regression2_test(); 309 regression2_test();
310 regression3_test(); 310 regression3_test();
311 regression4_test();
311 iteration_test(0, 10 + 90 * long_run); 312 iteration_test(0, 10 + 90 * long_run);
312 iteration_test(7, 10 + 90 * long_run); 313 iteration_test(7, 10 + 90 * long_run);
313 single_thread_tests(long_run); 314 single_thread_tests(long_run);
diff --git a/tools/testing/radix-tree/regression.h b/tools/testing/radix-tree/regression.h
index 3c8a1584e9ee..135145af18b7 100644
--- a/tools/testing/radix-tree/regression.h
+++ b/tools/testing/radix-tree/regression.h
@@ -5,5 +5,6 @@
5void regression1_test(void); 5void regression1_test(void);
6void regression2_test(void); 6void regression2_test(void);
7void regression3_test(void); 7void regression3_test(void);
8void regression4_test(void);
8 9
9#endif 10#endif
diff --git a/tools/testing/radix-tree/regression4.c b/tools/testing/radix-tree/regression4.c
new file mode 100644
index 000000000000..cf4e5aba6b08
--- /dev/null
+++ b/tools/testing/radix-tree/regression4.c
@@ -0,0 +1,79 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/kernel.h>
3#include <linux/gfp.h>
4#include <linux/slab.h>
5#include <linux/radix-tree.h>
6#include <linux/rcupdate.h>
7#include <stdlib.h>
8#include <pthread.h>
9#include <stdio.h>
10#include <assert.h>
11
12#include "regression.h"
13
14static pthread_barrier_t worker_barrier;
15static int obj0, obj1;
16static RADIX_TREE(mt_tree, GFP_KERNEL);
17
18static void *reader_fn(void *arg)
19{
20 int i;
21 void *entry;
22
23 rcu_register_thread();
24 pthread_barrier_wait(&worker_barrier);
25
26 for (i = 0; i < 1000000; i++) {
27 rcu_read_lock();
28 entry = radix_tree_lookup(&mt_tree, 0);
29 rcu_read_unlock();
30 if (entry != &obj0) {
31 printf("iteration %d bad entry = %p\n", i, entry);
32 abort();
33 }
34 }
35
36 rcu_unregister_thread();
37
38 return NULL;
39}
40
41static void *writer_fn(void *arg)
42{
43 int i;
44
45 rcu_register_thread();
46 pthread_barrier_wait(&worker_barrier);
47
48 for (i = 0; i < 1000000; i++) {
49 radix_tree_insert(&mt_tree, 1, &obj1);
50 radix_tree_delete(&mt_tree, 1);
51 }
52
53 rcu_unregister_thread();
54
55 return NULL;
56}
57
58void regression4_test(void)
59{
60 pthread_t reader, writer;
61
62 printv(1, "regression test 4 starting\n");
63
64 radix_tree_insert(&mt_tree, 0, &obj0);
65 pthread_barrier_init(&worker_barrier, NULL, 2);
66
67 if (pthread_create(&reader, NULL, reader_fn, NULL) ||
68 pthread_create(&writer, NULL, writer_fn, NULL)) {
69 perror("pthread_create");
70 exit(1);
71 }
72
73 if (pthread_join(reader, NULL) || pthread_join(writer, NULL)) {
74 perror("pthread_join");
75 exit(1);
76 }
77
78 printv(1, "regression test 4 passed\n");
79}