Add sparse checking to Makefile
[btrfs-progs-unstable.git] / random-test.c
blob7078263acc3dfc6a83eed6ee4620e975aa958455
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include "kerncompat.h"
5 #include "radix-tree.h"
6 #include "ctree.h"
7 #include "disk-io.h"
8 #include "print-tree.h"
10 int keep_running = 1;
12 static int setup_key(struct radix_tree_root *root, struct key *key, int exists)
14 int num = rand();
15 unsigned long res[2];
16 int ret;
18 key->flags = 0;
19 key->offset = 0;
20 again:
21 ret = radix_tree_gang_lookup(root, (void **)res, num, 2);
22 if (exists) {
23 if (ret == 0)
24 return -1;
25 num = res[0];
26 } else if (ret != 0 && num == res[0]) {
27 num++;
28 if (ret > 1 && num == res[1]) {
29 num++;
30 goto again;
33 key->objectid = num;
34 return 0;
37 static int ins_one(struct ctree_root *root, struct radix_tree_root *radix)
39 struct ctree_path path;
40 struct key key;
41 int ret;
42 char buf[128];
43 unsigned long oid;
44 init_path(&path);
45 ret = setup_key(radix, &key, 0);
46 sprintf(buf, "str-%Lu\n", key.objectid);
47 ret = insert_item(root, &key, buf, strlen(buf));
48 if (ret)
49 goto error;
50 oid = (unsigned long)key.objectid;
51 radix_tree_preload(GFP_KERNEL);
52 ret = radix_tree_insert(radix, oid, (void *)oid);
53 radix_tree_preload_end();
54 if (ret)
55 goto error;
56 return ret;
57 error:
58 printf("failed to insert %Lu\n", key.objectid);
59 return -1;
62 static int insert_dup(struct ctree_root *root, struct radix_tree_root *radix)
64 struct ctree_path path;
65 struct key key;
66 int ret;
67 char buf[128];
68 init_path(&path);
69 ret = setup_key(radix, &key, 1);
70 if (ret < 0)
71 return 0;
72 sprintf(buf, "str-%Lu\n", key.objectid);
73 ret = insert_item(root, &key, buf, strlen(buf));
74 if (ret != -EEXIST) {
75 printf("insert on %Lu gave us %d\n", key.objectid, ret);
76 return 1;
78 return 0;
81 static int del_one(struct ctree_root *root, struct radix_tree_root *radix)
83 struct ctree_path path;
84 struct key key;
85 int ret;
86 unsigned long *ptr;
87 init_path(&path);
88 ret = setup_key(radix, &key, 1);
89 if (ret < 0)
90 return 0;
91 ret = search_slot(root, &key, &path, -1);
92 if (ret)
93 goto error;
94 ret = del_item(root, &path);
95 release_path(root, &path);
96 if (ret != 0)
97 goto error;
98 ptr = radix_tree_delete(radix, key.objectid);
99 if (!ptr)
100 goto error;
101 return 0;
102 error:
103 printf("failed to delete %Lu\n", key.objectid);
104 return -1;
107 static int lookup_item(struct ctree_root *root, struct radix_tree_root *radix)
109 struct ctree_path path;
110 struct key key;
111 int ret;
112 init_path(&path);
113 ret = setup_key(radix, &key, 1);
114 if (ret < 0)
115 return 0;
116 ret = search_slot(root, &key, &path, 0);
117 release_path(root, &path);
118 if (ret)
119 goto error;
120 return 0;
121 error:
122 printf("unable to find key %Lu\n", key.objectid);
123 return -1;
126 static int lookup_enoent(struct ctree_root *root, struct radix_tree_root *radix)
128 struct ctree_path path;
129 struct key key;
130 int ret;
131 init_path(&path);
132 ret = setup_key(radix, &key, 0);
133 if (ret < 0)
134 return ret;
135 ret = search_slot(root, &key, &path, 0);
136 release_path(root, &path);
137 if (ret == 0)
138 goto error;
139 return 0;
140 error:
141 printf("able to find key that should not exist %Lu\n", key.objectid);
142 return -1;
145 int (*ops[])(struct ctree_root *root, struct radix_tree_root *radix) =
146 { ins_one, insert_dup, del_one, lookup_item, lookup_enoent };
148 static int fill_radix(struct ctree_root *root, struct radix_tree_root *radix)
150 struct ctree_path path;
151 struct key key;
152 unsigned long found;
153 int ret;
154 int slot;
155 int i;
156 key.offset = 0;
157 key.flags = 0;
158 key.objectid = (unsigned long)-1;
159 while(1) {
160 init_path(&path);
161 ret = search_slot(root, &key, &path, 0);
162 slot = path.slots[0];
163 if (ret != 0) {
164 if (slot == 0) {
165 release_path(root, &path);
166 break;
168 slot -= 1;
170 for (i = slot; i >= 0; i--) {
171 found = path.nodes[0]->leaf.items[i].key.objectid;
172 radix_tree_preload(GFP_KERNEL);
173 ret = radix_tree_insert(radix, found, (void *)found);
174 if (ret) {
175 fprintf(stderr,
176 "failed to insert %lu into radix\n",
177 found);
178 exit(1);
181 radix_tree_preload_end();
183 release_path(root, &path);
184 key.objectid = found - 1;
185 if (key.objectid > found)
186 break;
188 return 0;
191 void sigstopper(int ignored)
193 keep_running = 0;
194 fprintf(stderr, "caught exit signal, stopping\n");
197 int print_usage(void)
199 printf("usage: tester [-ih] [-c count] [-f count]\n");
200 printf("\t -c count -- iteration count after filling\n");
201 printf("\t -f count -- run this many random inserts before starting\n");
202 printf("\t -i -- only do initial fill\n");
203 printf("\t -h -- this help text\n");
204 exit(1);
206 int main(int ac, char **av)
208 RADIX_TREE(radix, GFP_KERNEL);
209 struct ctree_super_block super;
210 struct ctree_root *root;
211 int i;
212 int ret;
213 int count;
214 int op;
215 int iterations = 20000;
216 int init_fill_count = 800000;
217 int err = 0;
218 int initial_only = 0;
219 radix_tree_init();
220 root = open_ctree("dbfile", &super);
221 fill_radix(root, &radix);
223 signal(SIGTERM, sigstopper);
224 signal(SIGINT, sigstopper);
226 for (i = 1 ; i < ac ; i++) {
227 if (strcmp(av[i], "-i") == 0) {
228 initial_only = 1;
229 } else if (strcmp(av[i], "-c") == 0) {
230 iterations = atoi(av[i+1]);
231 i++;
232 } else if (strcmp(av[i], "-f") == 0) {
233 init_fill_count = atoi(av[i+1]);
234 i++;
235 } else {
236 print_usage();
239 for (i = 0; i < init_fill_count; i++) {
240 ret = ins_one(root, &radix);
241 if (ret) {
242 printf("initial fill failed\n");
243 err = ret;
244 goto out;
246 if (i % 10000 == 0) {
247 printf("initial fill %d level %d count %d\n", i,
248 node_level(root->node->node.header.flags),
249 root->node->node.header.nritems);
251 if (keep_running == 0) {
252 err = 0;
253 goto out;
256 if (initial_only == 1) {
257 goto out;
259 for (i = 0; i < iterations; i++) {
260 op = rand() % ARRAY_SIZE(ops);
261 count = rand() % 128;
262 if (i % 2000 == 0) {
263 printf("%d\n", i);
264 fflush(stdout);
266 if (i && i % 5000 == 0) {
267 printf("open & close, root level %d nritems %d\n",
268 node_level(root->node->node.header.flags),
269 root->node->node.header.nritems);
270 write_ctree_super(root, &super);
271 close_ctree(root);
272 root = open_ctree("dbfile", &super);
274 while(count--) {
275 ret = ops[op](root, &radix);
276 if (ret) {
277 fprintf(stderr, "op %d failed %d:%d\n",
278 op, i, iterations);
279 print_tree(root, root->node);
280 fprintf(stderr, "op %d failed %d:%d\n",
281 op, i, iterations);
282 err = ret;
283 goto out;
285 if (keep_running == 0) {
286 err = 0;
287 goto out;
291 out:
292 write_ctree_super(root, &super);
293 close_ctree(root);
294 return err;