blob: a8ef0478991b3f3d11cfc82b8ecaf36555c75d72 [file] [log] [blame]
Chris Masonfec577f2007-02-26 10:40:21 -05001#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"
9
10int keep_running = 1;
Chris Mason234b63a2007-03-13 10:46:10 -040011struct btrfs_super_block super;
Chris Masonfec577f2007-02-26 10:40:21 -050012
Chris Masone2fa7222007-03-12 16:22:34 -040013static int setup_key(struct radix_tree_root *root, struct btrfs_key *key,
14 int exists)
Chris Masonfec577f2007-02-26 10:40:21 -050015{
16 int num = rand();
17 unsigned long res[2];
18 int ret;
19
20 key->flags = 0;
21 key->offset = 0;
22again:
23 ret = radix_tree_gang_lookup(root, (void **)res, num, 2);
24 if (exists) {
25 if (ret == 0)
26 return -1;
27 num = res[0];
28 } else if (ret != 0 && num == res[0]) {
29 num++;
30 if (ret > 1 && num == res[1]) {
31 num++;
32 goto again;
33 }
34 }
35 key->objectid = num;
36 return 0;
37}
38
Chris Mason234b63a2007-03-13 10:46:10 -040039static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
Chris Masonfec577f2007-02-26 10:40:21 -050040{
Chris Mason234b63a2007-03-13 10:46:10 -040041 struct btrfs_path path;
Chris Masone2fa7222007-03-12 16:22:34 -040042 struct btrfs_key key;
Chris Masonfec577f2007-02-26 10:40:21 -050043 int ret;
44 char buf[128];
Chris Mason41903fe2007-02-26 10:55:42 -050045 unsigned long oid;
Chris Mason234b63a2007-03-13 10:46:10 -040046 btrfs_init_path(&path);
Chris Masonfec577f2007-02-26 10:40:21 -050047 ret = setup_key(radix, &key, 0);
Chris Mason7cf75962007-02-26 10:55:01 -050048 sprintf(buf, "str-%Lu\n", key.objectid);
Chris Mason234b63a2007-03-13 10:46:10 -040049 ret = btrfs_insert_item(root, &key, buf, strlen(buf));
Chris Masonfec577f2007-02-26 10:40:21 -050050 if (ret)
51 goto error;
Chris Mason41903fe2007-02-26 10:55:42 -050052 oid = (unsigned long)key.objectid;
Chris Masonfec577f2007-02-26 10:40:21 -050053 radix_tree_preload(GFP_KERNEL);
Chris Mason41903fe2007-02-26 10:55:42 -050054 ret = radix_tree_insert(radix, oid, (void *)oid);
Chris Masonfec577f2007-02-26 10:40:21 -050055 radix_tree_preload_end();
56 if (ret)
57 goto error;
58 return ret;
59error:
Chris Mason7cf75962007-02-26 10:55:01 -050060 printf("failed to insert %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -050061 return -1;
62}
63
Chris Mason234b63a2007-03-13 10:46:10 -040064static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
Chris Masonfec577f2007-02-26 10:40:21 -050065{
Chris Mason234b63a2007-03-13 10:46:10 -040066 struct btrfs_path path;
Chris Masone2fa7222007-03-12 16:22:34 -040067 struct btrfs_key key;
Chris Masonfec577f2007-02-26 10:40:21 -050068 int ret;
69 char buf[128];
Chris Mason234b63a2007-03-13 10:46:10 -040070 btrfs_init_path(&path);
Chris Masonfec577f2007-02-26 10:40:21 -050071 ret = setup_key(radix, &key, 1);
72 if (ret < 0)
73 return 0;
Chris Mason7cf75962007-02-26 10:55:01 -050074 sprintf(buf, "str-%Lu\n", key.objectid);
Chris Mason234b63a2007-03-13 10:46:10 -040075 ret = btrfs_insert_item(root, &key, buf, strlen(buf));
Chris Masonfec577f2007-02-26 10:40:21 -050076 if (ret != -EEXIST) {
Chris Mason7cf75962007-02-26 10:55:01 -050077 printf("insert on %Lu gave us %d\n", key.objectid, ret);
Chris Masonfec577f2007-02-26 10:40:21 -050078 return 1;
79 }
80 return 0;
81}
82
Chris Mason234b63a2007-03-13 10:46:10 -040083static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
Chris Masonfec577f2007-02-26 10:40:21 -050084{
Chris Mason234b63a2007-03-13 10:46:10 -040085 struct btrfs_path path;
Chris Masone2fa7222007-03-12 16:22:34 -040086 struct btrfs_key key;
Chris Masonfec577f2007-02-26 10:40:21 -050087 int ret;
88 unsigned long *ptr;
Chris Mason234b63a2007-03-13 10:46:10 -040089 btrfs_init_path(&path);
Chris Masonfec577f2007-02-26 10:40:21 -050090 ret = setup_key(radix, &key, 1);
91 if (ret < 0)
92 return 0;
Chris Mason234b63a2007-03-13 10:46:10 -040093 ret = btrfs_search_slot(root, &key, &path, -1, 1);
Chris Masonfec577f2007-02-26 10:40:21 -050094 if (ret)
95 goto error;
Chris Mason234b63a2007-03-13 10:46:10 -040096 ret = btrfs_del_item(root, &path);
97 btrfs_release_path(root, &path);
Chris Masonfec577f2007-02-26 10:40:21 -050098 if (ret != 0)
99 goto error;
100 ptr = radix_tree_delete(radix, key.objectid);
101 if (!ptr)
102 goto error;
103 return 0;
104error:
Chris Mason7cf75962007-02-26 10:55:01 -0500105 printf("failed to delete %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -0500106 return -1;
107}
108
Chris Mason234b63a2007-03-13 10:46:10 -0400109static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
Chris Masonfec577f2007-02-26 10:40:21 -0500110{
Chris Mason234b63a2007-03-13 10:46:10 -0400111 struct btrfs_path path;
Chris Masone2fa7222007-03-12 16:22:34 -0400112 struct btrfs_key key;
Chris Masonfec577f2007-02-26 10:40:21 -0500113 int ret;
Chris Mason234b63a2007-03-13 10:46:10 -0400114 btrfs_init_path(&path);
Chris Masonfec577f2007-02-26 10:40:21 -0500115 ret = setup_key(radix, &key, 1);
116 if (ret < 0)
117 return 0;
Chris Mason234b63a2007-03-13 10:46:10 -0400118 ret = btrfs_search_slot(root, &key, &path, 0, 1);
119 btrfs_release_path(root, &path);
Chris Masonfec577f2007-02-26 10:40:21 -0500120 if (ret)
121 goto error;
122 return 0;
123error:
Chris Mason7cf75962007-02-26 10:55:01 -0500124 printf("unable to find key %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -0500125 return -1;
126}
127
Chris Mason234b63a2007-03-13 10:46:10 -0400128static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
Chris Masonfec577f2007-02-26 10:40:21 -0500129{
Chris Mason234b63a2007-03-13 10:46:10 -0400130 struct btrfs_path path;
Chris Masone2fa7222007-03-12 16:22:34 -0400131 struct btrfs_key key;
Chris Masonfec577f2007-02-26 10:40:21 -0500132 int ret;
Chris Mason234b63a2007-03-13 10:46:10 -0400133 btrfs_init_path(&path);
Chris Masonfec577f2007-02-26 10:40:21 -0500134 ret = setup_key(radix, &key, 0);
135 if (ret < 0)
136 return ret;
Chris Mason234b63a2007-03-13 10:46:10 -0400137 ret = btrfs_search_slot(root, &key, &path, 0, 0);
138 btrfs_release_path(root, &path);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500139 if (ret <= 0)
Chris Masonfec577f2007-02-26 10:40:21 -0500140 goto error;
141 return 0;
142error:
Chris Mason7cf75962007-02-26 10:55:01 -0500143 printf("able to find key that should not exist %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -0500144 return -1;
145}
146
Chris Mason234b63a2007-03-13 10:46:10 -0400147static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
Chris Mason79f95c82007-03-01 15:16:26 -0500148 int nr)
149{
Chris Mason234b63a2007-03-13 10:46:10 -0400150 struct btrfs_path path;
Chris Masone2fa7222007-03-12 16:22:34 -0400151 struct btrfs_key key;
Chris Mason79f95c82007-03-01 15:16:26 -0500152 unsigned long found = 0;
153 int ret;
154 int slot;
155 int *ptr;
156 int count = 0;
157
158 key.offset = 0;
159 key.flags = 0;
160 key.objectid = (unsigned long)-1;
161 while(nr-- >= 0) {
Chris Mason234b63a2007-03-13 10:46:10 -0400162 btrfs_init_path(&path);
163 ret = btrfs_search_slot(root, &key, &path, -1, 1);
Chris Mason79f95c82007-03-01 15:16:26 -0500164 if (ret < 0) {
Chris Mason234b63a2007-03-13 10:46:10 -0400165 btrfs_release_path(root, &path);
Chris Mason79f95c82007-03-01 15:16:26 -0500166 return ret;
167 }
168 if (ret != 0) {
169 if (path.slots[0] == 0) {
Chris Mason234b63a2007-03-13 10:46:10 -0400170 btrfs_release_path(root, &path);
Chris Mason79f95c82007-03-01 15:16:26 -0500171 break;
172 }
173 path.slots[0] -= 1;
174 }
175 slot = path.slots[0];
Chris Mason0783fcf2007-03-12 20:12:07 -0400176 found=btrfs_key_objectid(&path.nodes[0]->leaf.items[slot].key);
Chris Mason234b63a2007-03-13 10:46:10 -0400177 ret = btrfs_del_item(root, &path);
Chris Mason79f95c82007-03-01 15:16:26 -0500178 count++;
179 if (ret) {
180 fprintf(stderr,
181 "failed to remove %lu from tree\n",
182 found);
183 return -1;
184 }
Chris Mason234b63a2007-03-13 10:46:10 -0400185 btrfs_release_path(root, &path);
Chris Mason79f95c82007-03-01 15:16:26 -0500186 ptr = radix_tree_delete(radix, found);
187 if (!ptr)
188 goto error;
189 if (!keep_running)
190 break;
191 }
192 return 0;
193error:
194 fprintf(stderr, "failed to delete from the radix %lu\n", found);
195 return -1;
196}
197
Chris Mason234b63a2007-03-13 10:46:10 -0400198static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix,
Chris Mason79f95c82007-03-01 15:16:26 -0500199 int count)
200{
201 int i;
Chris Mason79f95c82007-03-01 15:16:26 -0500202 int ret = 0;
203 for (i = 0; i < count; i++) {
204 ret = ins_one(root, radix);
205 if (ret) {
Chris Mason77ce6842007-03-02 10:06:43 -0500206 fprintf(stderr, "fill failed\n");
Chris Mason79f95c82007-03-01 15:16:26 -0500207 goto out;
208 }
Chris Mason77ce6842007-03-02 10:06:43 -0500209 if (i % 1000 == 0) {
Chris Mason234b63a2007-03-13 10:46:10 -0400210 ret = btrfs_commit_transaction(root, &super);
Chris Mason77ce6842007-03-02 10:06:43 -0500211 if (ret) {
212 fprintf(stderr, "fill commit failed\n");
213 return ret;
214 }
215 }
Chris Mason02217ed2007-03-02 16:08:05 -0500216 if (i && i % 10000 == 0) {
Chris Mason77ce6842007-03-02 10:06:43 -0500217 printf("bigfill %d\n", i);
218 }
Chris Mason79f95c82007-03-01 15:16:26 -0500219 if (!keep_running)
220 break;
221 }
222out:
223 return ret;
224}
225
Chris Mason234b63a2007-03-13 10:46:10 -0400226static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix)
Chris Mason79f95c82007-03-01 15:16:26 -0500227{
228 int ret;
Chris Masona28ec192007-03-06 20:08:01 -0500229 int nr = rand() % 5000;
Chris Mason79f95c82007-03-01 15:16:26 -0500230 static int run_nr = 0;
231
232 /* do the bulk op much less frequently */
233 if (run_nr++ % 100)
234 return 0;
235 ret = empty_tree(root, radix, nr);
236 if (ret)
237 return ret;
238 ret = fill_tree(root, radix, nr);
239 if (ret)
240 return ret;
241 return 0;
242}
243
244
Chris Mason234b63a2007-03-13 10:46:10 -0400245int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) =
Chris Masonf0930a32007-03-02 09:47:58 -0500246 { ins_one, insert_dup, del_one, lookup_item,
Chris Masona28ec192007-03-06 20:08:01 -0500247 lookup_enoent, bulk_op };
Chris Masonfec577f2007-02-26 10:40:21 -0500248
Chris Mason234b63a2007-03-13 10:46:10 -0400249static int fill_radix(struct btrfs_root *root, struct radix_tree_root *radix)
Chris Masonfec577f2007-02-26 10:40:21 -0500250{
Chris Mason234b63a2007-03-13 10:46:10 -0400251 struct btrfs_path path;
Chris Masone2fa7222007-03-12 16:22:34 -0400252 struct btrfs_key key;
Chris Mason7cf75962007-02-26 10:55:01 -0500253 unsigned long found;
Chris Masonfec577f2007-02-26 10:40:21 -0500254 int ret;
255 int slot;
256 int i;
Chris Masonaa5d6be2007-02-28 16:35:06 -0500257
Chris Masonfec577f2007-02-26 10:40:21 -0500258 key.offset = 0;
259 key.flags = 0;
260 key.objectid = (unsigned long)-1;
261 while(1) {
Chris Mason234b63a2007-03-13 10:46:10 -0400262 btrfs_init_path(&path);
263 ret = btrfs_search_slot(root, &key, &path, 0, 0);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500264 if (ret < 0) {
Chris Mason234b63a2007-03-13 10:46:10 -0400265 btrfs_release_path(root, &path);
Chris Masonaa5d6be2007-02-28 16:35:06 -0500266 return ret;
267 }
Chris Masonfec577f2007-02-26 10:40:21 -0500268 slot = path.slots[0];
269 if (ret != 0) {
270 if (slot == 0) {
Chris Mason234b63a2007-03-13 10:46:10 -0400271 btrfs_release_path(root, &path);
Chris Masonfec577f2007-02-26 10:40:21 -0500272 break;
273 }
274 slot -= 1;
275 }
276 for (i = slot; i >= 0; i--) {
Chris Mason0783fcf2007-03-12 20:12:07 -0400277 found = btrfs_key_objectid(&path.nodes[0]->
278 leaf.items[i].key);
Chris Masonfec577f2007-02-26 10:40:21 -0500279 radix_tree_preload(GFP_KERNEL);
280 ret = radix_tree_insert(radix, found, (void *)found);
281 if (ret) {
282 fprintf(stderr,
283 "failed to insert %lu into radix\n",
284 found);
285 exit(1);
286 }
287
288 radix_tree_preload_end();
289 }
Chris Mason234b63a2007-03-13 10:46:10 -0400290 btrfs_release_path(root, &path);
Chris Masonfec577f2007-02-26 10:40:21 -0500291 key.objectid = found - 1;
292 if (key.objectid > found)
293 break;
294 }
295 return 0;
296}
Chris Masonfec577f2007-02-26 10:40:21 -0500297void sigstopper(int ignored)
298{
299 keep_running = 0;
300 fprintf(stderr, "caught exit signal, stopping\n");
301}
302
303int print_usage(void)
304{
305 printf("usage: tester [-ih] [-c count] [-f count]\n");
306 printf("\t -c count -- iteration count after filling\n");
307 printf("\t -f count -- run this many random inserts before starting\n");
308 printf("\t -i -- only do initial fill\n");
309 printf("\t -h -- this help text\n");
310 exit(1);
311}
312int main(int ac, char **av)
313{
314 RADIX_TREE(radix, GFP_KERNEL);
Chris Mason234b63a2007-03-13 10:46:10 -0400315 struct btrfs_root *root;
Chris Masonfec577f2007-02-26 10:40:21 -0500316 int i;
317 int ret;
318 int count;
319 int op;
320 int iterations = 20000;
321 int init_fill_count = 800000;
322 int err = 0;
323 int initial_only = 0;
324 radix_tree_init();
325 root = open_ctree("dbfile", &super);
326 fill_radix(root, &radix);
327
328 signal(SIGTERM, sigstopper);
329 signal(SIGINT, sigstopper);
330
331 for (i = 1 ; i < ac ; i++) {
332 if (strcmp(av[i], "-i") == 0) {
333 initial_only = 1;
334 } else if (strcmp(av[i], "-c") == 0) {
335 iterations = atoi(av[i+1]);
336 i++;
337 } else if (strcmp(av[i], "-f") == 0) {
338 init_fill_count = atoi(av[i+1]);
339 i++;
340 } else {
341 print_usage();
342 }
343 }
Chris Mason79f95c82007-03-01 15:16:26 -0500344 printf("initial fill\n");
345 ret = fill_tree(root, &radix, init_fill_count);
346 printf("starting run\n");
347 if (ret) {
348 err = ret;
349 goto out;
Chris Masonfec577f2007-02-26 10:40:21 -0500350 }
351 if (initial_only == 1) {
352 goto out;
353 }
354 for (i = 0; i < iterations; i++) {
355 op = rand() % ARRAY_SIZE(ops);
356 count = rand() % 128;
357 if (i % 2000 == 0) {
358 printf("%d\n", i);
359 fflush(stdout);
360 }
361 if (i && i % 5000 == 0) {
362 printf("open & close, root level %d nritems %d\n",
Chris Mason7518a232007-03-12 12:01:18 -0400363 btrfs_header_level(&root->node->node.header),
364 btrfs_header_nritems(&root->node->node.header));
Chris Masona28ec192007-03-06 20:08:01 -0500365 close_ctree(root, &super);
Chris Masonfec577f2007-02-26 10:40:21 -0500366 root = open_ctree("dbfile", &super);
367 }
368 while(count--) {
369 ret = ops[op](root, &radix);
370 if (ret) {
371 fprintf(stderr, "op %d failed %d:%d\n",
372 op, i, iterations);
Chris Mason234b63a2007-03-13 10:46:10 -0400373 btrfs_print_tree(root, root->node);
Chris Masonfec577f2007-02-26 10:40:21 -0500374 fprintf(stderr, "op %d failed %d:%d\n",
375 op, i, iterations);
376 err = ret;
377 goto out;
378 }
Chris Masona28ec192007-03-06 20:08:01 -0500379 if (ops[op] == bulk_op)
Chris Mason79f95c82007-03-01 15:16:26 -0500380 break;
Chris Masonfec577f2007-02-26 10:40:21 -0500381 if (keep_running == 0) {
382 err = 0;
383 goto out;
384 }
385 }
386 }
387out:
Chris Masona28ec192007-03-06 20:08:01 -0500388 close_ctree(root, &super);
Chris Masonfec577f2007-02-26 10:40:21 -0500389 return err;
390}
391