diff options
author | Matthew Wilcox <mawilcox@microsoft.com> | 2016-12-14 18:09:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 19:04:10 -0500 |
commit | 3e3cdc68bede179a957fcd6be7b833a83df4e5de (patch) | |
tree | 8ae1c50d586265c06d5d7ac58e1df08d0c409740 /tools | |
parent | a90eb3a2a405cf7e96093ed531a285067dfdbc9d (diff) |
radix tree test suite: check multiorder iteration
The random iteration test only inserts order-0 entries currently.
Update it to insert entries of order between 7 and 0. Also make the
maximum index configurable, make some variables static, make the test
duration variable, remove some useless spinning, and add a fifth thread
which calls tag_tagged_items().
Link: http://lkml.kernel.org/r/1480369871-5271-62-git-send-email-mawilcox@linuxonhyperv.com
Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Matthew Wilcox <mawilcox@microsoft.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/radix-tree/iteration_check.c | 80 | ||||
-rw-r--r-- | tools/testing/radix-tree/main.c | 3 | ||||
-rw-r--r-- | tools/testing/radix-tree/multiorder.c | 23 | ||||
-rw-r--r-- | tools/testing/radix-tree/test.h | 2 |
4 files changed, 73 insertions, 35 deletions
diff --git a/tools/testing/radix-tree/iteration_check.c b/tools/testing/radix-tree/iteration_check.c index f328a66899b4..7572b7ed930e 100644 --- a/tools/testing/radix-tree/iteration_check.c +++ b/tools/testing/radix-tree/iteration_check.c | |||
@@ -16,26 +16,36 @@ | |||
16 | #include <pthread.h> | 16 | #include <pthread.h> |
17 | #include "test.h" | 17 | #include "test.h" |
18 | 18 | ||
19 | #define NUM_THREADS 4 | 19 | #define NUM_THREADS 5 |
20 | #define TAG 0 | 20 | #define MAX_IDX 100 |
21 | #define TAG 0 | ||
22 | #define NEW_TAG 1 | ||
23 | |||
21 | static pthread_mutex_t tree_lock = PTHREAD_MUTEX_INITIALIZER; | 24 | static pthread_mutex_t tree_lock = PTHREAD_MUTEX_INITIALIZER; |
22 | static pthread_t threads[NUM_THREADS]; | 25 | static pthread_t threads[NUM_THREADS]; |
23 | static unsigned int seeds[3]; | 26 | static unsigned int seeds[3]; |
24 | RADIX_TREE(tree, GFP_KERNEL); | 27 | static RADIX_TREE(tree, GFP_KERNEL); |
25 | bool test_complete; | 28 | static bool test_complete; |
29 | static int max_order; | ||
26 | 30 | ||
27 | /* relentlessly fill the tree with tagged entries */ | 31 | /* relentlessly fill the tree with tagged entries */ |
28 | static void *add_entries_fn(void *arg) | 32 | static void *add_entries_fn(void *arg) |
29 | { | 33 | { |
30 | int pgoff; | ||
31 | |||
32 | rcu_register_thread(); | 34 | rcu_register_thread(); |
33 | 35 | ||
34 | while (!test_complete) { | 36 | while (!test_complete) { |
35 | for (pgoff = 0; pgoff < 100; pgoff++) { | 37 | unsigned long pgoff; |
38 | int order; | ||
39 | |||
40 | for (pgoff = 0; pgoff < MAX_IDX; pgoff++) { | ||
36 | pthread_mutex_lock(&tree_lock); | 41 | pthread_mutex_lock(&tree_lock); |
37 | if (item_insert(&tree, pgoff) == 0) | 42 | for (order = max_order; order >= 0; order--) { |
38 | item_tag_set(&tree, pgoff, TAG); | 43 | if (item_insert_order(&tree, pgoff, order) |
44 | == 0) { | ||
45 | item_tag_set(&tree, pgoff, TAG); | ||
46 | break; | ||
47 | } | ||
48 | } | ||
39 | pthread_mutex_unlock(&tree_lock); | 49 | pthread_mutex_unlock(&tree_lock); |
40 | } | 50 | } |
41 | } | 51 | } |
@@ -62,14 +72,7 @@ static void *tagged_iteration_fn(void *arg) | |||
62 | while (!test_complete) { | 72 | while (!test_complete) { |
63 | rcu_read_lock(); | 73 | rcu_read_lock(); |
64 | radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) { | 74 | radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) { |
65 | void *entry; | 75 | void *entry = radix_tree_deref_slot(slot); |
66 | int i; | ||
67 | |||
68 | /* busy wait to let removals happen */ | ||
69 | for (i = 0; i < 1000000; i++) | ||
70 | ; | ||
71 | |||
72 | entry = radix_tree_deref_slot(slot); | ||
73 | if (unlikely(!entry)) | 76 | if (unlikely(!entry)) |
74 | continue; | 77 | continue; |
75 | 78 | ||
@@ -110,14 +113,7 @@ static void *untagged_iteration_fn(void *arg) | |||
110 | while (!test_complete) { | 113 | while (!test_complete) { |
111 | rcu_read_lock(); | 114 | rcu_read_lock(); |
112 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { | 115 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { |
113 | void *entry; | 116 | void *entry = radix_tree_deref_slot(slot); |
114 | int i; | ||
115 | |||
116 | /* busy wait to let removals happen */ | ||
117 | for (i = 0; i < 1000000; i++) | ||
118 | ; | ||
119 | |||
120 | entry = radix_tree_deref_slot(slot); | ||
121 | if (unlikely(!entry)) | 117 | if (unlikely(!entry)) |
122 | continue; | 118 | continue; |
123 | 119 | ||
@@ -152,7 +148,7 @@ static void *remove_entries_fn(void *arg) | |||
152 | while (!test_complete) { | 148 | while (!test_complete) { |
153 | int pgoff; | 149 | int pgoff; |
154 | 150 | ||
155 | pgoff = rand_r(&seeds[2]) % 100; | 151 | pgoff = rand_r(&seeds[2]) % MAX_IDX; |
156 | 152 | ||
157 | pthread_mutex_lock(&tree_lock); | 153 | pthread_mutex_lock(&tree_lock); |
158 | item_delete(&tree, pgoff); | 154 | item_delete(&tree, pgoff); |
@@ -164,36 +160,54 @@ static void *remove_entries_fn(void *arg) | |||
164 | return NULL; | 160 | return NULL; |
165 | } | 161 | } |
166 | 162 | ||
163 | static void *tag_entries_fn(void *arg) | ||
164 | { | ||
165 | rcu_register_thread(); | ||
166 | |||
167 | while (!test_complete) { | ||
168 | tag_tagged_items(&tree, &tree_lock, 0, MAX_IDX, 10, TAG, | ||
169 | NEW_TAG); | ||
170 | } | ||
171 | rcu_unregister_thread(); | ||
172 | return NULL; | ||
173 | } | ||
174 | |||
167 | /* This is a unit test for a bug found by the syzkaller tester */ | 175 | /* This is a unit test for a bug found by the syzkaller tester */ |
168 | void iteration_test(void) | 176 | void iteration_test(unsigned order, unsigned test_duration) |
169 | { | 177 | { |
170 | int i; | 178 | int i; |
171 | 179 | ||
172 | printf("Running iteration tests for 10 seconds\n"); | 180 | printf("Running %siteration tests for %d seconds\n", |
181 | order > 0 ? "multiorder " : "", test_duration); | ||
173 | 182 | ||
183 | max_order = order; | ||
174 | test_complete = false; | 184 | test_complete = false; |
175 | 185 | ||
176 | for (i = 0; i < 3; i++) | 186 | for (i = 0; i < 3; i++) |
177 | seeds[i] = rand(); | 187 | seeds[i] = rand(); |
178 | 188 | ||
179 | if (pthread_create(&threads[0], NULL, tagged_iteration_fn, NULL)) { | 189 | if (pthread_create(&threads[0], NULL, tagged_iteration_fn, NULL)) { |
180 | perror("pthread_create"); | 190 | perror("create tagged iteration thread"); |
181 | exit(1); | 191 | exit(1); |
182 | } | 192 | } |
183 | if (pthread_create(&threads[1], NULL, untagged_iteration_fn, NULL)) { | 193 | if (pthread_create(&threads[1], NULL, untagged_iteration_fn, NULL)) { |
184 | perror("pthread_create"); | 194 | perror("create untagged iteration thread"); |
185 | exit(1); | 195 | exit(1); |
186 | } | 196 | } |
187 | if (pthread_create(&threads[2], NULL, add_entries_fn, NULL)) { | 197 | if (pthread_create(&threads[2], NULL, add_entries_fn, NULL)) { |
188 | perror("pthread_create"); | 198 | perror("create add entry thread"); |
189 | exit(1); | 199 | exit(1); |
190 | } | 200 | } |
191 | if (pthread_create(&threads[3], NULL, remove_entries_fn, NULL)) { | 201 | if (pthread_create(&threads[3], NULL, remove_entries_fn, NULL)) { |
192 | perror("pthread_create"); | 202 | perror("create remove entry thread"); |
203 | exit(1); | ||
204 | } | ||
205 | if (pthread_create(&threads[4], NULL, tag_entries_fn, NULL)) { | ||
206 | perror("create tag entry thread"); | ||
193 | exit(1); | 207 | exit(1); |
194 | } | 208 | } |
195 | 209 | ||
196 | sleep(10); | 210 | sleep(test_duration); |
197 | test_complete = true; | 211 | test_complete = true; |
198 | 212 | ||
199 | for (i = 0; i < NUM_THREADS; i++) { | 213 | for (i = 0; i < NUM_THREADS; i++) { |
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c index 170175ca4105..f7e9801a6754 100644 --- a/tools/testing/radix-tree/main.c +++ b/tools/testing/radix-tree/main.c | |||
@@ -350,7 +350,8 @@ int main(int argc, char **argv) | |||
350 | regression1_test(); | 350 | regression1_test(); |
351 | regression2_test(); | 351 | regression2_test(); |
352 | regression3_test(); | 352 | regression3_test(); |
353 | iteration_test(); | 353 | iteration_test(0, 10); |
354 | iteration_test(7, 20); | ||
354 | single_thread_tests(long_run); | 355 | single_thread_tests(long_run); |
355 | 356 | ||
356 | /* Free any remaining preallocated nodes */ | 357 | /* Free any remaining preallocated nodes */ |
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c index 9757b8928bd4..08b4e16dc86f 100644 --- a/tools/testing/radix-tree/multiorder.c +++ b/tools/testing/radix-tree/multiorder.c | |||
@@ -75,8 +75,27 @@ static void __multiorder_tag_test(int index, int order) | |||
75 | item_kill_tree(&tree); | 75 | item_kill_tree(&tree); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void __multiorder_tag_test2(unsigned order, unsigned long index2) | ||
79 | { | ||
80 | RADIX_TREE(tree, GFP_KERNEL); | ||
81 | unsigned long index = (1 << order); | ||
82 | index2 += index; | ||
83 | |||
84 | assert(item_insert_order(&tree, 0, order) == 0); | ||
85 | assert(item_insert(&tree, index2) == 0); | ||
86 | |||
87 | assert(radix_tree_tag_set(&tree, 0, 0)); | ||
88 | assert(radix_tree_tag_set(&tree, index2, 0)); | ||
89 | |||
90 | assert(tag_tagged_items(&tree, NULL, 0, ~0UL, 10, 0, 1) == 2); | ||
91 | |||
92 | item_kill_tree(&tree); | ||
93 | } | ||
94 | |||
78 | static void multiorder_tag_tests(void) | 95 | static void multiorder_tag_tests(void) |
79 | { | 96 | { |
97 | int i, j; | ||
98 | |||
80 | /* test multi-order entry for indices 0-7 with no sibling pointers */ | 99 | /* test multi-order entry for indices 0-7 with no sibling pointers */ |
81 | __multiorder_tag_test(0, 3); | 100 | __multiorder_tag_test(0, 3); |
82 | __multiorder_tag_test(5, 3); | 101 | __multiorder_tag_test(5, 3); |
@@ -116,6 +135,10 @@ static void multiorder_tag_tests(void) | |||
116 | __multiorder_tag_test(300, 8); | 135 | __multiorder_tag_test(300, 8); |
117 | 136 | ||
118 | __multiorder_tag_test(0x12345678UL, 8); | 137 | __multiorder_tag_test(0x12345678UL, 8); |
138 | |||
139 | for (i = 1; i < 10; i++) | ||
140 | for (j = 0; j < (10 << i); j++) | ||
141 | __multiorder_tag_test2(i, j); | ||
119 | } | 142 | } |
120 | 143 | ||
121 | static void multiorder_check(unsigned long index, int order) | 144 | static void multiorder_check(unsigned long index, int order) |
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h index 7c2611caa6d2..056a23b56467 100644 --- a/tools/testing/radix-tree/test.h +++ b/tools/testing/radix-tree/test.h | |||
@@ -32,7 +32,7 @@ unsigned long find_item(struct radix_tree_root *, void *item); | |||
32 | 32 | ||
33 | void tag_check(void); | 33 | void tag_check(void); |
34 | void multiorder_checks(void); | 34 | void multiorder_checks(void); |
35 | void iteration_test(void); | 35 | void iteration_test(unsigned order, unsigned duration); |
36 | void benchmark(void); | 36 | void benchmark(void); |
37 | 37 | ||
38 | struct item * | 38 | struct item * |