4 #include "kerncompat.h"
5 #include "radix-tree.h"
8 #include "print-tree.h"
9 #include "transaction.h"
12 struct btrfs_super_block super;
14 static int setup_key(struct radix_tree_root *root, struct btrfs_key *key,
22 btrfs_set_key_type(key, BTRFS_STRING_ITEM_KEY);
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_trans_handle *trans, struct btrfs_root *root,
42 struct radix_tree_root *radix)
44 struct btrfs_path path;
49 btrfs_init_path(&path);
50 ret = setup_key(radix, &key, 0);
51 sprintf(buf, "str-%Lu\n", key.objectid);
52 ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf));
55 oid = (unsigned long)key.objectid;
56 radix_tree_preload(GFP_KERNEL);
57 ret = radix_tree_insert(radix, oid, (void *)oid);
58 radix_tree_preload_end();
63 printf("failed to insert %Lu\n", key.objectid);
67 static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root
68 *root, struct radix_tree_root *radix)
70 struct btrfs_path path;
74 btrfs_init_path(&path);
75 ret = setup_key(radix, &key, 1);
78 sprintf(buf, "str-%Lu\n", key.objectid);
79 ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf));
81 printf("insert on %Lu gave us %d\n", key.objectid, ret);
87 static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root,
88 struct radix_tree_root *radix)
90 struct btrfs_path path;
94 btrfs_init_path(&path);
95 ret = setup_key(radix, &key, 1);
98 ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
101 ret = btrfs_del_item(trans, root, &path);
102 btrfs_release_path(root, &path);
105 ptr = radix_tree_delete(radix, key.objectid);
110 printf("failed to delete %Lu\n", key.objectid);
114 static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root
115 *root, struct radix_tree_root *radix)
117 struct btrfs_path path;
118 struct btrfs_key key;
120 btrfs_init_path(&path);
121 ret = setup_key(radix, &key, 1);
124 ret = btrfs_search_slot(trans, root, &key, &path, 0, 1);
125 btrfs_release_path(root, &path);
130 printf("unable to find key %Lu\n", key.objectid);
134 static int lookup_enoent(struct btrfs_trans_handle *trans, struct btrfs_root
135 *root, struct radix_tree_root *radix)
137 struct btrfs_path path;
138 struct btrfs_key key;
140 btrfs_init_path(&path);
141 ret = setup_key(radix, &key, 0);
144 ret = btrfs_search_slot(trans, root, &key, &path, 0, 0);
145 btrfs_release_path(root, &path);
150 printf("able to find key that should not exist %Lu\n", key.objectid);
154 static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root
155 *root, struct radix_tree_root *radix, int nr)
157 struct btrfs_path path;
158 struct btrfs_key key;
159 unsigned long found = 0;
167 btrfs_set_key_type(&key, BTRFS_STRING_ITEM_KEY);
168 key.objectid = (unsigned long)-1;
170 btrfs_init_path(&path);
171 ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
173 btrfs_release_path(root, &path);
177 if (path.slots[0] == 0) {
178 btrfs_release_path(root, &path);
183 slot = path.slots[0];
184 found = btrfs_disk_key_objectid(
185 &path.nodes[0]->leaf.items[slot].key);
186 ret = btrfs_del_item(trans, root, &path);
190 "failed to remove %lu from tree\n",
194 btrfs_release_path(root, &path);
195 ptr = radix_tree_delete(radix, found);
203 fprintf(stderr, "failed to delete from the radix %lu\n", found);
207 static int fill_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root,
208 struct radix_tree_root *radix, int count)
212 for (i = 0; i < count; i++) {
213 ret = ins_one(trans, root, radix);
215 fprintf(stderr, "fill failed\n");
219 ret = btrfs_commit_transaction(trans, root, &super);
221 fprintf(stderr, "fill commit failed\n");
225 if (i && i % 10000 == 0) {
226 printf("bigfill %d\n", i);
235 static int bulk_op(struct btrfs_trans_handle *trans, struct btrfs_root *root,
236 struct radix_tree_root *radix)
239 int nr = rand() % 5000;
240 static int run_nr = 0;
242 /* do the bulk op much less frequently */
245 ret = empty_tree(trans, root, radix, nr);
248 ret = fill_tree(trans, root, radix, nr);
255 int (*ops[])(struct btrfs_trans_handle *,
256 struct btrfs_root *root, struct radix_tree_root *radix) =
257 { ins_one, insert_dup, del_one, lookup_item,
258 lookup_enoent, bulk_op };
260 static int fill_radix(struct btrfs_root *root, struct radix_tree_root *radix)
262 struct btrfs_path path;
263 struct btrfs_key key;
271 btrfs_set_key_type(&key, BTRFS_STRING_ITEM_KEY);
272 key.objectid = (unsigned long)-1;
274 btrfs_init_path(&path);
275 ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
277 btrfs_release_path(root, &path);
280 slot = path.slots[0];
283 btrfs_release_path(root, &path);
288 for (i = slot; i >= 0; i--) {
289 found = btrfs_disk_key_objectid(&path.nodes[0]->
291 radix_tree_preload(GFP_KERNEL);
292 ret = radix_tree_insert(radix, found, (void *)found);
295 "failed to insert %lu into radix\n",
300 radix_tree_preload_end();
302 btrfs_release_path(root, &path);
303 key.objectid = found - 1;
304 if (key.objectid > found)
309 void sigstopper(int ignored)
312 fprintf(stderr, "caught exit signal, stopping\n");
315 int print_usage(void)
317 printf("usage: tester [-ih] [-c count] [-f count]\n");
318 printf("\t -c count -- iteration count after filling\n");
319 printf("\t -f count -- run this many random inserts before starting\n");
320 printf("\t -i -- only do initial fill\n");
321 printf("\t -h -- this help text\n");
324 int main(int ac, char **av)
326 RADIX_TREE(radix, GFP_KERNEL);
327 struct btrfs_root *root;
332 int iterations = 20000;
333 int init_fill_count = 800000;
335 int initial_only = 0;
336 struct btrfs_trans_handle *trans;
338 root = open_ctree("dbfile", &super);
339 fill_radix(root, &radix);
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 trans = btrfs_start_transaction(root, 1);
359 ret = fill_tree(trans, root, &radix, init_fill_count);
360 printf("starting run\n");
365 if (initial_only == 1) {
368 for (i = 0; i < iterations; i++) {
369 op = rand() % ARRAY_SIZE(ops);
370 count = rand() % 128;
375 if (i && i % 5000 == 0) {
376 printf("open & close, root level %d nritems %d\n",
377 btrfs_header_level(&root->node->node.header),
378 btrfs_header_nritems(&root->node->node.header));
379 close_ctree(root, &super);
380 root = open_ctree("dbfile", &super);
383 ret = ops[op](trans, root, &radix);
385 fprintf(stderr, "op %d failed %d:%d\n",
387 btrfs_print_tree(root, root->node);
388 fprintf(stderr, "op %d failed %d:%d\n",
393 if (ops[op] == bulk_op)
395 if (keep_running == 0) {
402 close_ctree(root, &super);