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(path.nodes[0]->leaf.items +
86 btrfs_name_hash(buf, strlen(buf), &myhash);
87 btrfs_name_hash(found, found_len, &foundhash);
88 if (myhash != foundhash)
90 btrfs_release_path(root, &path);
94 btrfs_release_path(root, &path);
96 printf("failed to insert %lu ret %d\n", oid, ret);
100 static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
106 ret = find_num(radix, &oid, 1);
109 sprintf(buf, "str-%lu", oid);
111 ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid,
113 if (ret != -EEXIST) {
114 printf("insert on %s gave us %d\n", buf, ret);
120 static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
125 struct btrfs_path path;
128 ret = find_num(radix, &oid, 1);
131 sprintf(buf, "str-%lu", oid);
132 btrfs_init_path(&path);
133 ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), -1);
136 ret = btrfs_del_item(root, &path);
139 btrfs_release_path(root, &path);
140 ptr = radix_tree_delete(radix, oid);
147 btrfs_release_path(root, &path);
149 printf("failed to delete %lu %d\n", oid, ret);
153 static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
155 struct btrfs_path path;
160 ret = find_num(radix, &oid, 1);
163 sprintf(buf, "str-%lu", oid);
164 btrfs_init_path(&path);
165 ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
166 btrfs_release_path(root, &path);
168 printf("unable to find key %lu\n", oid);
174 static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
176 struct btrfs_path path;
181 ret = find_num(radix, &oid, 0);
184 sprintf(buf, "str-%lu", oid);
185 btrfs_init_path(&path);
186 ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
187 btrfs_release_path(root, &path);
189 printf("able to find key that should not exist %lu\n", oid);
195 static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
198 struct btrfs_path path;
199 struct btrfs_key key;
200 unsigned long found = 0;
207 struct btrfs_dir_item *di;
209 key.offset = (u64)-1;
211 btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
212 key.objectid = dir_oid;
214 btrfs_init_path(&path);
215 ret = btrfs_search_slot(root, &key, &path, -1, 1);
217 btrfs_release_path(root, &path);
221 if (path.slots[0] == 0) {
222 btrfs_release_path(root, &path);
227 slot = path.slots[0];
228 di = btrfs_item_ptr(&path.nodes[0]->leaf, slot,
229 struct btrfs_dir_item);
230 found_len = btrfs_dir_name_len(path.nodes[0]->leaf.items +
232 memcpy(buf, (char *)(di + 1), found_len);
233 BUG_ON(found_len > 128);
234 buf[found_len] = '\0';
235 found = atoi(buf + 4);
236 ret = btrfs_del_item(root, &path);
240 "failed to remove %lu from tree\n",
244 btrfs_release_path(root, &path);
245 ptr = radix_tree_delete(radix, found);
253 fprintf(stderr, "failed to delete from the radix %lu\n", found);
257 static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix,
262 for (i = 0; i < count; i++) {
263 ret = ins_one(root, radix);
265 fprintf(stderr, "fill failed\n");
269 ret = btrfs_commit_transaction(root, &super);
271 fprintf(stderr, "fill commit failed\n");
275 if (i && i % 10000 == 0) {
276 printf("bigfill %d\n", i);
285 static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix)
288 int nr = rand() % 5000;
289 static int run_nr = 0;
291 /* do the bulk op much less frequently */
294 ret = empty_tree(root, radix, nr);
297 ret = fill_tree(root, radix, nr);
304 int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) =
305 { ins_one, insert_dup, del_one, lookup_item,
306 lookup_enoent, bulk_op };
308 void sigstopper(int ignored)
311 fprintf(stderr, "caught exit signal, stopping\n");
314 int print_usage(void)
316 printf("usage: tester [-ih] [-c count] [-f count]\n");
317 printf("\t -c count -- iteration count after filling\n");
318 printf("\t -f count -- run this many random inserts before starting\n");
319 printf("\t -i -- only do initial fill\n");
320 printf("\t -h -- this help text\n");
323 int main(int ac, char **av)
325 RADIX_TREE(radix, GFP_KERNEL);
326 struct btrfs_root *root;
331 int iterations = 20000;
332 int init_fill_count = 800000;
334 int initial_only = 0;
337 printf("removing old tree\n");
339 root = open_ctree("dbfile", &super);
341 signal(SIGTERM, sigstopper);
342 signal(SIGINT, sigstopper);
344 for (i = 1 ; i < ac ; i++) {
345 if (strcmp(av[i], "-i") == 0) {
347 } else if (strcmp(av[i], "-c") == 0) {
348 iterations = atoi(av[i+1]);
350 } else if (strcmp(av[i], "-f") == 0) {
351 init_fill_count = atoi(av[i+1]);
357 printf("initial fill\n");
358 ret = fill_tree(root, &radix, init_fill_count);
359 printf("starting run\n");
364 if (initial_only == 1) {
367 for (i = 0; i < iterations; i++) {
368 op = rand() % ARRAY_SIZE(ops);
369 count = rand() % 128;
374 if (i && i % 5000 == 0) {
375 printf("open & close, root level %d nritems %d\n",
376 btrfs_header_level(&root->node->node.header),
377 btrfs_header_nritems(&root->node->node.header));
378 close_ctree(root, &super);
379 root = open_ctree("dbfile", &super);
382 ret = ops[op](root, &radix);
384 fprintf(stderr, "op %d failed %d:%d\n",
386 btrfs_print_tree(root, root->node);
387 fprintf(stderr, "op %d failed %d:%d\n",
392 if (ops[op] == bulk_op)
394 if (keep_running == 0) {
401 close_ctree(root, &super);