diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-01 15:16:26 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-01 15:16:26 -0500 |
commit | 79f95c82dca7665f32bafd68b7cdf4a01fab0840 (patch) | |
tree | 255a204980ad2c6481b36a1d8257d5ee84277d74 /fs | |
parent | bb8039515d7c1b521ea22f095b43618ccc771885 (diff) |
Btrfs: Fixup the code to merge during path walks
Add a bulk insert/remove test to random-test
Add the quick-test code back as another regression test
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/Makefile | 5 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 137 | ||||
-rw-r--r-- | fs/btrfs/quick-test.c | 165 | ||||
-rw-r--r-- | fs/btrfs/random-test.c | 117 |
4 files changed, 381 insertions, 43 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 58d4260a04b2..756b1cd4cf4d 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
@@ -14,7 +14,7 @@ check=sparse $(CHECKFLAGS) | |||
14 | $(check) $< | 14 | $(check) $< |
15 | $(CC) $(CFLAGS) -c $< | 15 | $(CC) $(CFLAGS) -c $< |
16 | 16 | ||
17 | all: tester debug-tree | 17 | all: tester debug-tree quick-test |
18 | 18 | ||
19 | debug-tree: $(objects) debug-tree.o | 19 | debug-tree: $(objects) debug-tree.o |
20 | gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o | 20 | gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o |
@@ -22,6 +22,9 @@ debug-tree: $(objects) debug-tree.o | |||
22 | tester: $(objects) random-test.o | 22 | tester: $(objects) random-test.o |
23 | gcc $(CFLAGS) -o tester $(objects) random-test.o | 23 | gcc $(CFLAGS) -o tester $(objects) random-test.o |
24 | 24 | ||
25 | quick-test: $(objects) quick-test.o | ||
26 | gcc $(CFLAGS) -o quick-test $(objects) quick-test.o | ||
27 | |||
25 | $(objects) : $(headers) | 28 | $(objects) : $(headers) |
26 | 29 | ||
27 | clean : | 30 | clean : |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index df4a19d65206..afa5bc5c7c1a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -12,6 +12,9 @@ static int split_leaf(struct ctree_root *root, struct ctree_path *path, | |||
12 | int data_size); | 12 | int data_size); |
13 | static int push_node_left(struct ctree_root *root, struct tree_buffer *dst, | 13 | static int push_node_left(struct ctree_root *root, struct tree_buffer *dst, |
14 | struct tree_buffer *src); | 14 | struct tree_buffer *src); |
15 | static int balance_node_right(struct ctree_root *root, | ||
16 | struct tree_buffer *dst_buf, | ||
17 | struct tree_buffer *src_buf); | ||
15 | static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level, | 18 | static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level, |
16 | int slot); | 19 | int slot); |
17 | 20 | ||
@@ -217,15 +220,16 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
217 | int ret = 0; | 220 | int ret = 0; |
218 | int wret; | 221 | int wret; |
219 | int pslot; | 222 | int pslot; |
220 | int used = 0; | ||
221 | int count; | ||
222 | int orig_slot = path->slots[level]; | 223 | int orig_slot = path->slots[level]; |
224 | u64 orig_ptr; | ||
223 | 225 | ||
224 | if (level == 0) | 226 | if (level == 0) |
225 | return 0; | 227 | return 0; |
226 | 228 | ||
227 | mid_buf = path->nodes[level]; | 229 | mid_buf = path->nodes[level]; |
228 | mid = &mid_buf->node; | 230 | mid = &mid_buf->node; |
231 | orig_ptr = mid->blockptrs[orig_slot]; | ||
232 | |||
229 | if (level < MAX_LEVEL - 1) | 233 | if (level < MAX_LEVEL - 1) |
230 | parent_buf = path->nodes[level + 1]; | 234 | parent_buf = path->nodes[level + 1]; |
231 | pslot = path->slots[level + 1]; | 235 | pslot = path->slots[level + 1]; |
@@ -253,24 +257,26 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
253 | if (mid->header.nritems > NODEPTRS_PER_BLOCK / 4) | 257 | if (mid->header.nritems > NODEPTRS_PER_BLOCK / 4) |
254 | return 0; | 258 | return 0; |
255 | 259 | ||
256 | // print_tree(root, root->node); | ||
257 | left_buf = read_node_slot(root, parent_buf, pslot - 1); | 260 | left_buf = read_node_slot(root, parent_buf, pslot - 1); |
258 | right_buf = read_node_slot(root, parent_buf, pslot + 1); | 261 | right_buf = read_node_slot(root, parent_buf, pslot + 1); |
259 | if (right_buf) { | 262 | |
260 | right = &right_buf->node; | 263 | /* first, try to make some room in the middle buffer */ |
261 | used = right->header.nritems; | ||
262 | count = 1; | ||
263 | } | ||
264 | if (left_buf) { | 264 | if (left_buf) { |
265 | left = &left_buf->node; | 265 | left = &left_buf->node; |
266 | used += left->header.nritems; | ||
267 | orig_slot += left->header.nritems; | 266 | orig_slot += left->header.nritems; |
268 | count++; | 267 | wret = push_node_left(root, left_buf, mid_buf); |
268 | if (wret < 0) | ||
269 | ret = wret; | ||
269 | } | 270 | } |
270 | if (left_buf) | 271 | |
271 | push_node_left(root, left_buf, mid_buf); | 272 | /* |
273 | * then try to empty the right most buffer into the middle | ||
274 | */ | ||
272 | if (right_buf) { | 275 | if (right_buf) { |
273 | push_node_left(root, mid_buf, right_buf); | 276 | right = &right_buf->node; |
277 | wret = push_node_left(root, mid_buf, right_buf); | ||
278 | if (wret < 0) | ||
279 | ret = wret; | ||
274 | if (right->header.nritems == 0) { | 280 | if (right->header.nritems == 0) { |
275 | u64 blocknr = right_buf->blocknr; | 281 | u64 blocknr = right_buf->blocknr; |
276 | tree_block_release(root, right_buf); | 282 | tree_block_release(root, right_buf); |
@@ -285,9 +291,29 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
285 | } else { | 291 | } else { |
286 | memcpy(parent->keys + pslot + 1, right->keys, | 292 | memcpy(parent->keys + pslot + 1, right->keys, |
287 | sizeof(struct key)); | 293 | sizeof(struct key)); |
294 | wret = write_tree_block(root, parent_buf); | ||
295 | if (wret) | ||
296 | ret = wret; | ||
288 | } | 297 | } |
289 | } | 298 | } |
299 | if (mid->header.nritems == 1) { | ||
300 | /* | ||
301 | * we're not allowed to leave a node with one item in the | ||
302 | * tree during a delete. A deletion from lower in the tree | ||
303 | * could try to delete the only pointer in this node. | ||
304 | * So, pull some keys from the left. | ||
305 | * There has to be a left pointer at this point because | ||
306 | * otherwise we would have pulled some pointers from the | ||
307 | * right | ||
308 | */ | ||
309 | BUG_ON(!left_buf); | ||
310 | wret = balance_node_right(root, mid_buf, left_buf); | ||
311 | if (wret < 0) | ||
312 | ret = wret; | ||
313 | BUG_ON(wret == 1); | ||
314 | } | ||
290 | if (mid->header.nritems == 0) { | 315 | if (mid->header.nritems == 0) { |
316 | /* we've managed to empty the middle node, drop it */ | ||
291 | u64 blocknr = mid_buf->blocknr; | 317 | u64 blocknr = mid_buf->blocknr; |
292 | tree_block_release(root, mid_buf); | 318 | tree_block_release(root, mid_buf); |
293 | mid_buf = NULL; | 319 | mid_buf = NULL; |
@@ -298,11 +324,17 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
298 | wret = free_extent(root, blocknr, 1); | 324 | wret = free_extent(root, blocknr, 1); |
299 | if (wret) | 325 | if (wret) |
300 | ret = wret; | 326 | ret = wret; |
301 | } else | 327 | } else { |
328 | /* update the parent key to reflect our changes */ | ||
302 | memcpy(parent->keys + pslot, mid->keys, sizeof(struct key)); | 329 | memcpy(parent->keys + pslot, mid->keys, sizeof(struct key)); |
330 | wret = write_tree_block(root, parent_buf); | ||
331 | if (wret) | ||
332 | ret = wret; | ||
333 | } | ||
303 | 334 | ||
335 | /* update the path */ | ||
304 | if (left_buf) { | 336 | if (left_buf) { |
305 | if (left->header.nritems >= orig_slot) { | 337 | if (left->header.nritems > orig_slot) { |
306 | left_buf->count++; // released below | 338 | left_buf->count++; // released below |
307 | path->nodes[level] = left_buf; | 339 | path->nodes[level] = left_buf; |
308 | path->slots[level + 1] -= 1; | 340 | path->slots[level + 1] -= 1; |
@@ -314,12 +346,15 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
314 | path->slots[level] = orig_slot; | 346 | path->slots[level] = orig_slot; |
315 | } | 347 | } |
316 | } | 348 | } |
349 | /* double check we haven't messed things up */ | ||
350 | check_block(path, level); | ||
351 | if (orig_ptr != path->nodes[level]->node.blockptrs[path->slots[level]]) | ||
352 | BUG(); | ||
317 | 353 | ||
318 | if (right_buf) | 354 | if (right_buf) |
319 | tree_block_release(root, right_buf); | 355 | tree_block_release(root, right_buf); |
320 | if (left_buf) | 356 | if (left_buf) |
321 | tree_block_release(root, left_buf); | 357 | tree_block_release(root, left_buf); |
322 | |||
323 | return ret; | 358 | return ret; |
324 | } | 359 | } |
325 | 360 | ||
@@ -378,6 +413,7 @@ again: | |||
378 | goto again; | 413 | goto again; |
379 | c = &b->node; | 414 | c = &b->node; |
380 | slot = p->slots[level]; | 415 | slot = p->slots[level]; |
416 | BUG_ON(c->header.nritems == 1); | ||
381 | } | 417 | } |
382 | b = read_tree_block(root, c->blockptrs[slot]); | 418 | b = read_tree_block(root, c->blockptrs[slot]); |
383 | } else { | 419 | } else { |
@@ -433,13 +469,7 @@ static int fixup_low_keys(struct ctree_root *root, | |||
433 | 469 | ||
434 | /* | 470 | /* |
435 | * try to push data from one node into the next node left in the | 471 | * try to push data from one node into the next node left in the |
436 | * tree. The src node is found at specified level in the path. | 472 | * tree. |
437 | * If some bytes were pushed, return 0, otherwise return 1. | ||
438 | * | ||
439 | * Lower nodes/leaves in the path are not touched, higher nodes may | ||
440 | * be modified to reflect the push. | ||
441 | * | ||
442 | * The path is altered to reflect the push. | ||
443 | * | 473 | * |
444 | * returns 0 if some ptrs were pushed left, < 0 if there was some horrible | 474 | * returns 0 if some ptrs were pushed left, < 0 if there was some horrible |
445 | * error, and > 0 if there was no room in the left hand block. | 475 | * error, and > 0 if there was no room in the left hand block. |
@@ -463,7 +493,8 @@ static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf, | |||
463 | } | 493 | } |
464 | 494 | ||
465 | if (src_nritems < push_items) | 495 | if (src_nritems < push_items) |
466 | push_items =src_nritems; | 496 | push_items = src_nritems; |
497 | |||
467 | memcpy(dst->keys + dst_nritems, src->keys, | 498 | memcpy(dst->keys + dst_nritems, src->keys, |
468 | push_items * sizeof(struct key)); | 499 | push_items * sizeof(struct key)); |
469 | memcpy(dst->blockptrs + dst_nritems, src->blockptrs, | 500 | memcpy(dst->blockptrs + dst_nritems, src->blockptrs, |
@@ -488,6 +519,64 @@ static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf, | |||
488 | } | 519 | } |
489 | 520 | ||
490 | /* | 521 | /* |
522 | * try to push data from one node into the next node right in the | ||
523 | * tree. | ||
524 | * | ||
525 | * returns 0 if some ptrs were pushed, < 0 if there was some horrible | ||
526 | * error, and > 0 if there was no room in the right hand block. | ||
527 | * | ||
528 | * this will only push up to 1/2 the contents of the left node over | ||
529 | */ | ||
530 | static int balance_node_right(struct ctree_root *root, | ||
531 | struct tree_buffer *dst_buf, | ||
532 | struct tree_buffer *src_buf) | ||
533 | { | ||
534 | struct node *src = &src_buf->node; | ||
535 | struct node *dst = &dst_buf->node; | ||
536 | int push_items = 0; | ||
537 | int max_push; | ||
538 | int src_nritems; | ||
539 | int dst_nritems; | ||
540 | int ret = 0; | ||
541 | int wret; | ||
542 | |||
543 | src_nritems = src->header.nritems; | ||
544 | dst_nritems = dst->header.nritems; | ||
545 | push_items = NODEPTRS_PER_BLOCK - dst_nritems; | ||
546 | if (push_items <= 0) { | ||
547 | return 1; | ||
548 | } | ||
549 | |||
550 | max_push = src_nritems / 2 + 1; | ||
551 | /* don't try to empty the node */ | ||
552 | if (max_push > src_nritems) | ||
553 | return 1; | ||
554 | if (max_push < push_items) | ||
555 | push_items = max_push; | ||
556 | |||
557 | memmove(dst->keys + push_items, dst->keys, | ||
558 | dst_nritems * sizeof(struct key)); | ||
559 | memmove(dst->blockptrs + push_items, dst->blockptrs, | ||
560 | dst_nritems * sizeof(u64)); | ||
561 | memcpy(dst->keys, src->keys + src_nritems - push_items, | ||
562 | push_items * sizeof(struct key)); | ||
563 | memcpy(dst->blockptrs, src->blockptrs + src_nritems - push_items, | ||
564 | push_items * sizeof(u64)); | ||
565 | |||
566 | src->header.nritems -= push_items; | ||
567 | dst->header.nritems += push_items; | ||
568 | |||
569 | wret = write_tree_block(root, src_buf); | ||
570 | if (wret < 0) | ||
571 | ret = wret; | ||
572 | |||
573 | wret = write_tree_block(root, dst_buf); | ||
574 | if (wret < 0) | ||
575 | ret = wret; | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | /* | ||
491 | * helper function to insert a new root level in the tree. | 580 | * helper function to insert a new root level in the tree. |
492 | * A new node is allocated, and a single item is inserted to | 581 | * A new node is allocated, and a single item is inserted to |
493 | * point to the existing root | 582 | * point to the existing root |
diff --git a/fs/btrfs/quick-test.c b/fs/btrfs/quick-test.c new file mode 100644 index 000000000000..dbd00c3b7ab4 --- /dev/null +++ b/fs/btrfs/quick-test.c | |||
@@ -0,0 +1,165 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "kerncompat.h" | ||
4 | #include "radix-tree.h" | ||
5 | #include "ctree.h" | ||
6 | #include "disk-io.h" | ||
7 | #include "print-tree.h" | ||
8 | |||
9 | /* for testing only */ | ||
10 | int next_key(int i, int max_key) { | ||
11 | return rand() % max_key; | ||
12 | //return i; | ||
13 | } | ||
14 | |||
15 | int main(int ac, char **av) { | ||
16 | struct key ins; | ||
17 | struct key last = { (u64)-1, 0, 0}; | ||
18 | char *buf; | ||
19 | int i; | ||
20 | int num; | ||
21 | int ret; | ||
22 | int run_size = 100000; | ||
23 | int max_key = 100000000; | ||
24 | int tree_size = 0; | ||
25 | struct ctree_path path; | ||
26 | struct ctree_super_block super; | ||
27 | struct ctree_root *root; | ||
28 | |||
29 | radix_tree_init(); | ||
30 | |||
31 | root = open_ctree("dbfile", &super); | ||
32 | srand(55); | ||
33 | for (i = 0; i < run_size; i++) { | ||
34 | buf = malloc(64); | ||
35 | num = next_key(i, max_key); | ||
36 | // num = i; | ||
37 | sprintf(buf, "string-%d", num); | ||
38 | if (i % 10000 == 0) | ||
39 | fprintf(stderr, "insert %d:%d\n", num, i); | ||
40 | ins.objectid = num; | ||
41 | ins.offset = 0; | ||
42 | ins.flags = 0; | ||
43 | ret = insert_item(root, &ins, buf, strlen(buf)); | ||
44 | if (!ret) | ||
45 | tree_size++; | ||
46 | free(buf); | ||
47 | } | ||
48 | write_ctree_super(root, &super); | ||
49 | close_ctree(root); | ||
50 | |||
51 | root = open_ctree("dbfile", &super); | ||
52 | printf("starting search\n"); | ||
53 | srand(55); | ||
54 | for (i = 0; i < run_size; i++) { | ||
55 | num = next_key(i, max_key); | ||
56 | ins.objectid = num; | ||
57 | init_path(&path); | ||
58 | if (i % 10000 == 0) | ||
59 | fprintf(stderr, "search %d:%d\n", num, i); | ||
60 | ret = search_slot(root, &ins, &path, 0); | ||
61 | if (ret) { | ||
62 | print_tree(root, root->node); | ||
63 | printf("unable to find %d\n", num); | ||
64 | exit(1); | ||
65 | } | ||
66 | release_path(root, &path); | ||
67 | } | ||
68 | write_ctree_super(root, &super); | ||
69 | close_ctree(root); | ||
70 | root = open_ctree("dbfile", &super); | ||
71 | printf("node %p level %d total ptrs %d free spc %lu\n", root->node, | ||
72 | node_level(root->node->node.header.flags), | ||
73 | root->node->node.header.nritems, | ||
74 | NODEPTRS_PER_BLOCK - root->node->node.header.nritems); | ||
75 | printf("all searches good, deleting some items\n"); | ||
76 | i = 0; | ||
77 | srand(55); | ||
78 | for (i = 0 ; i < run_size/4; i++) { | ||
79 | num = next_key(i, max_key); | ||
80 | ins.objectid = num; | ||
81 | init_path(&path); | ||
82 | ret = search_slot(root, &ins, &path, -1); | ||
83 | if (!ret) { | ||
84 | if (i % 10000 == 0) | ||
85 | fprintf(stderr, "del %d:%d\n", num, i); | ||
86 | ret = del_item(root, &path); | ||
87 | if (ret != 0) | ||
88 | BUG(); | ||
89 | tree_size--; | ||
90 | } | ||
91 | release_path(root, &path); | ||
92 | } | ||
93 | write_ctree_super(root, &super); | ||
94 | close_ctree(root); | ||
95 | root = open_ctree("dbfile", &super); | ||
96 | srand(128); | ||
97 | for (i = 0; i < run_size; i++) { | ||
98 | buf = malloc(64); | ||
99 | num = next_key(i, max_key); | ||
100 | sprintf(buf, "string-%d", num); | ||
101 | ins.objectid = num; | ||
102 | if (i % 10000 == 0) | ||
103 | fprintf(stderr, "insert %d:%d\n", num, i); | ||
104 | ret = insert_item(root, &ins, buf, strlen(buf)); | ||
105 | if (!ret) | ||
106 | tree_size++; | ||
107 | free(buf); | ||
108 | } | ||
109 | write_ctree_super(root, &super); | ||
110 | close_ctree(root); | ||
111 | root = open_ctree("dbfile", &super); | ||
112 | srand(128); | ||
113 | printf("starting search2\n"); | ||
114 | for (i = 0; i < run_size; i++) { | ||
115 | num = next_key(i, max_key); | ||
116 | ins.objectid = num; | ||
117 | init_path(&path); | ||
118 | if (i % 10000 == 0) | ||
119 | fprintf(stderr, "search %d:%d\n", num, i); | ||
120 | ret = search_slot(root, &ins, &path, 0); | ||
121 | if (ret) { | ||
122 | print_tree(root, root->node); | ||
123 | printf("unable to find %d\n", num); | ||
124 | exit(1); | ||
125 | } | ||
126 | release_path(root, &path); | ||
127 | } | ||
128 | printf("starting big long delete run\n"); | ||
129 | while(root->node && root->node->node.header.nritems > 0) { | ||
130 | struct leaf *leaf; | ||
131 | int slot; | ||
132 | ins.objectid = (u64)-1; | ||
133 | init_path(&path); | ||
134 | ret = search_slot(root, &ins, &path, -1); | ||
135 | if (ret == 0) | ||
136 | BUG(); | ||
137 | |||
138 | leaf = &path.nodes[0]->leaf; | ||
139 | slot = path.slots[0]; | ||
140 | if (slot != leaf->header.nritems) | ||
141 | BUG(); | ||
142 | while(path.slots[0] > 0) { | ||
143 | path.slots[0] -= 1; | ||
144 | slot = path.slots[0]; | ||
145 | leaf = &path.nodes[0]->leaf; | ||
146 | |||
147 | memcpy(&last, &leaf->items[slot].key, sizeof(last)); | ||
148 | if (tree_size % 10000 == 0) | ||
149 | printf("big del %d:%d\n", tree_size, i); | ||
150 | ret = del_item(root, &path); | ||
151 | if (ret != 0) { | ||
152 | printf("del_item returned %d\n", ret); | ||
153 | BUG(); | ||
154 | } | ||
155 | tree_size--; | ||
156 | } | ||
157 | release_path(root, &path); | ||
158 | } | ||
159 | printf("tree size is now %d\n", tree_size); | ||
160 | printf("map tree\n"); | ||
161 | print_tree(root->extent_root, root->extent_root->node); | ||
162 | write_ctree_super(root, &super); | ||
163 | close_ctree(root); | ||
164 | return 0; | ||
165 | } | ||
diff --git a/fs/btrfs/random-test.c b/fs/btrfs/random-test.c index cebaf6483927..bbd554e88db2 100644 --- a/fs/btrfs/random-test.c +++ b/fs/btrfs/random-test.c | |||
@@ -142,8 +142,98 @@ error: | |||
142 | return -1; | 142 | return -1; |
143 | } | 143 | } |
144 | 144 | ||
145 | static int empty_tree(struct ctree_root *root, struct radix_tree_root *radix, | ||
146 | int nr) | ||
147 | { | ||
148 | struct ctree_path path; | ||
149 | struct key key; | ||
150 | unsigned long found = 0; | ||
151 | int ret; | ||
152 | int slot; | ||
153 | int *ptr; | ||
154 | int count = 0; | ||
155 | |||
156 | key.offset = 0; | ||
157 | key.flags = 0; | ||
158 | key.objectid = (unsigned long)-1; | ||
159 | while(nr-- >= 0) { | ||
160 | init_path(&path); | ||
161 | ret = search_slot(root, &key, &path, -1); | ||
162 | if (ret < 0) { | ||
163 | release_path(root, &path); | ||
164 | return ret; | ||
165 | } | ||
166 | if (ret != 0) { | ||
167 | if (path.slots[0] == 0) { | ||
168 | release_path(root, &path); | ||
169 | break; | ||
170 | } | ||
171 | path.slots[0] -= 1; | ||
172 | } | ||
173 | slot = path.slots[0]; | ||
174 | found = path.nodes[0]->leaf.items[slot].key.objectid; | ||
175 | ret = del_item(root, &path); | ||
176 | count++; | ||
177 | if (ret) { | ||
178 | fprintf(stderr, | ||
179 | "failed to remove %lu from tree\n", | ||
180 | found); | ||
181 | return -1; | ||
182 | } | ||
183 | release_path(root, &path); | ||
184 | ptr = radix_tree_delete(radix, found); | ||
185 | if (!ptr) | ||
186 | goto error; | ||
187 | if (!keep_running) | ||
188 | break; | ||
189 | } | ||
190 | return 0; | ||
191 | error: | ||
192 | fprintf(stderr, "failed to delete from the radix %lu\n", found); | ||
193 | return -1; | ||
194 | } | ||
195 | |||
196 | static int fill_tree(struct ctree_root *root, struct radix_tree_root *radix, | ||
197 | int count) | ||
198 | { | ||
199 | int i; | ||
200 | int err; | ||
201 | int ret = 0; | ||
202 | for (i = 0; i < count; i++) { | ||
203 | ret = ins_one(root, radix); | ||
204 | if (ret) { | ||
205 | printf("fill failed\n"); | ||
206 | err = ret; | ||
207 | goto out; | ||
208 | } | ||
209 | if (!keep_running) | ||
210 | break; | ||
211 | } | ||
212 | out: | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static int bulk_op(struct ctree_root *root, struct radix_tree_root *radix) | ||
217 | { | ||
218 | int ret; | ||
219 | int nr = rand() % 20000; | ||
220 | static int run_nr = 0; | ||
221 | |||
222 | /* do the bulk op much less frequently */ | ||
223 | if (run_nr++ % 100) | ||
224 | return 0; | ||
225 | ret = empty_tree(root, radix, nr); | ||
226 | if (ret) | ||
227 | return ret; | ||
228 | ret = fill_tree(root, radix, nr); | ||
229 | if (ret) | ||
230 | return ret; | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | |||
145 | int (*ops[])(struct ctree_root *root, struct radix_tree_root *radix) = | 235 | int (*ops[])(struct ctree_root *root, struct radix_tree_root *radix) = |
146 | { ins_one, insert_dup, del_one, lookup_item, lookup_enoent }; | 236 | { ins_one, insert_dup, del_one, lookup_item, lookup_enoent, bulk_op }; |
147 | 237 | ||
148 | static int fill_radix(struct ctree_root *root, struct radix_tree_root *radix) | 238 | static int fill_radix(struct ctree_root *root, struct radix_tree_root *radix) |
149 | { | 239 | { |
@@ -192,7 +282,6 @@ static int fill_radix(struct ctree_root *root, struct radix_tree_root *radix) | |||
192 | } | 282 | } |
193 | return 0; | 283 | return 0; |
194 | } | 284 | } |
195 | |||
196 | void sigstopper(int ignored) | 285 | void sigstopper(int ignored) |
197 | { | 286 | { |
198 | keep_running = 0; | 287 | keep_running = 0; |
@@ -241,22 +330,12 @@ int main(int ac, char **av) | |||
241 | print_usage(); | 330 | print_usage(); |
242 | } | 331 | } |
243 | } | 332 | } |
244 | for (i = 0; i < init_fill_count; i++) { | 333 | printf("initial fill\n"); |
245 | ret = ins_one(root, &radix); | 334 | ret = fill_tree(root, &radix, init_fill_count); |
246 | if (ret) { | 335 | printf("starting run\n"); |
247 | printf("initial fill failed\n"); | 336 | if (ret) { |
248 | err = ret; | 337 | err = ret; |
249 | goto out; | 338 | goto out; |
250 | } | ||
251 | if (i % 10000 == 0) { | ||
252 | printf("initial fill %d level %d count %d\n", i, | ||
253 | node_level(root->node->node.header.flags), | ||
254 | root->node->node.header.nritems); | ||
255 | } | ||
256 | if (keep_running == 0) { | ||
257 | err = 0; | ||
258 | goto out; | ||
259 | } | ||
260 | } | 339 | } |
261 | if (initial_only == 1) { | 340 | if (initial_only == 1) { |
262 | goto out; | 341 | goto out; |
@@ -287,6 +366,8 @@ int main(int ac, char **av) | |||
287 | err = ret; | 366 | err = ret; |
288 | goto out; | 367 | goto out; |
289 | } | 368 | } |
369 | if (ops[op] == bulk_op) | ||
370 | break; | ||
290 | if (keep_running == 0) { | 371 | if (keep_running == 0) { |
291 | err = 0; | 372 | err = 0; |
292 | goto out; | 373 | goto out; |