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
;
264 unsigned long found
= 0;
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
);