5 #include "kerncompat.h"
6 #include "radix-tree.h"
9 #include "print-tree.h"
13 struct btrfs_super_block super;
14 static u64 dir_oid = 44556;
15 static u64 file_oid = 33778;
17 static int find_num(struct radix_tree_root *root, unsigned long *num_ret,
20 unsigned long num = rand();
25 ret = radix_tree_gang_lookup(root, (void **)res, num, 2);
30 } else if (ret != 0 && num == res[0]) {
32 if (ret > 1 && num == res[1]) {
41 static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
46 struct btrfs_path path;
48 find_num(radix, &oid, 0);
49 sprintf(buf, "str-%lu", oid);
51 ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid,
56 radix_tree_preload(GFP_KERNEL);
57 ret = radix_tree_insert(radix, oid, (void *)oid);
58 radix_tree_preload_end();
67 * if we got an EEXIST, it may be due to hash collision, double
70 btrfs_init_path(&path);
71 ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
74 if (!btrfs_match_dir_item_name(root, &path, buf, strlen(buf))) {
75 struct btrfs_dir_item *di;
81 di = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0],
82 struct btrfs_dir_item);
83 found = (char *)(di + 1);
84 found_len = btrfs_dir_name_len(di);
85 btrfs_name_hash(buf, strlen(buf), &myhash);
86 btrfs_name_hash(found, found_len, &foundhash);
87 if (myhash != foundhash)
89 btrfs_release_path(root, &path);
93 btrfs_release_path(root, &path);
95 printf("failed to insert %lu ret %d\n", oid, ret);
99 static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
105 ret = find_num(radix, &oid, 1);
108 sprintf(buf, "str-%lu", oid);
110 ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid,
112 if (ret != -EEXIST) {
113 printf("insert on %s gave us %d\n", buf, ret);
119 static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
124 struct btrfs_path path;
127 ret = find_num(radix, &oid, 1);
130 sprintf(buf, "str-%lu", oid);
131 btrfs_init_path(&path);
132 ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), -1);
135 ret = btrfs_del_item(root, &path);
138 btrfs_release_path(root, &path);
139 ptr = radix_tree_delete(radix, oid);
146 btrfs_release_path(root, &path);
148 printf("failed to delete %lu %d\n", oid, ret);
152 static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
154 struct btrfs_path path;
159 ret = find_num(radix, &oid, 1);
162 sprintf(buf, "str-%lu", oid);
163 btrfs_init_path(&path);
164 ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
165 btrfs_release_path(root, &path);
167 printf("unable to find key %lu\n", oid);
173 static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
175 struct btrfs_path path;
180 ret = find_num(radix, &oid, 0);
183 sprintf(buf, "str-%lu", oid);
184 btrfs_init_path(&path);
185 ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
186 btrfs_release_path(root, &path);
188 printf("able to find key that should not exist %lu\n", oid);
194 static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
197 struct btrfs_path path;
198 struct btrfs_key key;
199 unsigned long found = 0;
206 struct btrfs_dir_item *di;
208 key.offset = (u64)-1;
210 btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
211 key.objectid = dir_oid;
213 btrfs_init_path(&path);
214 ret = btrfs_search_slot(root, &key, &path, -1, 1);
216 btrfs_release_path(root, &path);
220 if (path.slots[0] == 0) {
221 btrfs_release_path(root, &path);
226 slot = path.slots[0];
227 di = btrfs_item_ptr(&path.nodes[0]->leaf, slot,
228 struct btrfs_dir_item);
229 found_len = btrfs_dir_name_len(di);
230 memcpy(buf, (char *)(di + 1), found_len);
231 BUG_ON(found_len > 128);
232 buf[found_len] = '\0';
233 found = atoi(buf + 4);
234 ret = btrfs_del_item(root, &path);
238 "failed to remove %lu from tree\n",
242 btrfs_release_path(root, &path);
243 ptr = radix_tree_delete(radix, found);
251 fprintf(stderr, "failed to delete from the radix %lu\n", found);
255 static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix,
260 for (i = 0; i < count; i++) {
261 ret = ins_one(root, radix);
263 fprintf(stderr, "fill failed\n");
267 ret = btrfs_commit_transaction(root, &super);
269 fprintf(stderr, "fill commit failed\n");
273 if (i && i % 10000 == 0) {
274 printf("bigfill %d\n", i);
283 static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix)
286 int nr = rand() % 5000;
287 static int run_nr = 0;
289 /* do the bulk op much less frequently */
292 ret = empty_tree(root, radix, nr);
295 ret = fill_tree(root, radix, nr);
302 int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) =
303 { ins_one, insert_dup, del_one, lookup_item,
304 lookup_enoent, bulk_op };
306 void sigstopper(int ignored)
309 fprintf(stderr, "caught exit signal, stopping\n");
312 int print_usage(void)
314 printf("usage: tester [-ih] [-c count] [-f count]\n");
315 printf("\t -c count -- iteration count after filling\n");
316 printf("\t -f count -- run this many random inserts before starting\n");
317 printf("\t -i -- only do initial fill\n");
318 printf("\t -h -- this help text\n");
321 int main(int ac, char **av)
323 RADIX_TREE(radix, GFP_KERNEL);
324 struct btrfs_root *root;
329 int iterations = 20000;
330 int init_fill_count = 800000;
332 int initial_only = 0;
335 printf("removing old tree\n");
337 root = open_ctree("dbfile", &super);
339 signal(SIGTERM, sigstopper);
340 signal(SIGINT, sigstopper);
342 for (i = 1 ; i < ac ; i++) {
343 if (strcmp(av[i], "-i") == 0) {
345 } else if (strcmp(av[i], "-c") == 0) {
346 iterations = atoi(av[i+1]);
348 } else if (strcmp(av[i], "-f") == 0) {
349 init_fill_count = atoi(av[i+1]);
355 printf("initial fill\n");
356 ret = fill_tree(root, &radix, init_fill_count);
357 printf("starting run\n");
362 if (initial_only == 1) {
365 for (i = 0; i < iterations; i++) {
366 op = rand() % ARRAY_SIZE(ops);
367 count = rand() % 128;
372 if (i && i % 5000 == 0) {
373 printf("open & close, root level %d nritems %d\n",
374 btrfs_header_level(&root->node->node.header),
375 btrfs_header_nritems(&root->node->node.header));
376 close_ctree(root, &super);
377 root = open_ctree("dbfile", &super);
380 ret = ops[op](root, &radix);
382 fprintf(stderr, "op %d failed %d:%d\n",
384 btrfs_print_tree(root, root->node);
385 fprintf(stderr, "op %d failed %d:%d\n",
390 if (ops[op] == bulk_op)
392 if (keep_running == 0) {
399 close_ctree(root, &super);