aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-02-28 16:35:06 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-02-28 16:35:06 -0500
commitaa5d6bed255d7f8c655a8f10d760f4247bc8385c (patch)
treeddd4ad69b490fc49e23097f5d783ef90ea81cf5f /fs/btrfs/ctree.c
parentaf86d07efe83e2f2da3658702a720bc48b1a6d78 (diff)
Btrfs: return code checking
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c480
1 files changed, 254 insertions, 226 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 0aea94224ba3..be2be0272513 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -6,12 +6,15 @@
6#include "disk-io.h" 6#include "disk-io.h"
7#include "print-tree.h" 7#include "print-tree.h"
8 8
9int split_node(struct ctree_root *root, struct ctree_path *path, int level); 9static int split_node(struct ctree_root *root, struct ctree_path *path,
10int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size); 10 int level);
11int push_node_left(struct ctree_root *root, struct ctree_path *path, int level); 11static int split_leaf(struct ctree_root *root, struct ctree_path *path,
12int push_node_right(struct ctree_root *root, 12 int data_size);
13static int push_node_left(struct ctree_root *root, struct ctree_path *path,
14 int level);
15static int push_node_right(struct ctree_root *root,
13 struct ctree_path *path, int level); 16 struct ctree_path *path, int level);
14int del_ptr(struct ctree_root *root, struct ctree_path *path, int level); 17static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level);
15 18
16inline void init_path(struct ctree_path *p) 19inline void init_path(struct ctree_path *p)
17{ 20{
@@ -26,6 +29,7 @@ void release_path(struct ctree_root *root, struct ctree_path *p)
26 break; 29 break;
27 tree_block_release(root, p->nodes[i]); 30 tree_block_release(root, p->nodes[i]);
28 } 31 }
32 memset(p, 0, sizeof(*p));
29} 33}
30 34
31/* 35/*
@@ -74,6 +78,67 @@ int comp_keys(struct key *k1, struct key *k2)
74 return 0; 78 return 0;
75} 79}
76 80
81int check_node(struct ctree_path *path, int level)
82{
83 int i;
84 struct node *parent = NULL;
85 struct node *node = &path->nodes[level]->node;
86 int parent_slot;
87
88 if (path->nodes[level + 1])
89 parent = &path->nodes[level + 1]->node;
90 parent_slot = path->slots[level + 1];
91 if (parent && node->header.nritems > 0) {
92 struct key *parent_key;
93 parent_key = &parent->keys[parent_slot];
94 BUG_ON(memcmp(parent_key, node->keys, sizeof(struct key)));
95 BUG_ON(parent->blockptrs[parent_slot] != node->header.blocknr);
96 }
97 BUG_ON(node->header.nritems > NODEPTRS_PER_BLOCK);
98 for (i = 0; i < node->header.nritems - 2; i++) {
99 BUG_ON(comp_keys(&node->keys[i], &node->keys[i+1]) >= 0);
100 }
101 return 0;
102}
103
104int check_leaf(struct ctree_path *path, int level)
105{
106 int i;
107 struct leaf *leaf = &path->nodes[level]->leaf;
108 struct node *parent = NULL;
109 int parent_slot;
110
111 if (path->nodes[level + 1])
112 parent = &path->nodes[level + 1]->node;
113 parent_slot = path->slots[level + 1];
114 if (parent && leaf->header.nritems > 0) {
115 struct key *parent_key;
116 parent_key = &parent->keys[parent_slot];
117 BUG_ON(memcmp(parent_key, &leaf->items[0].key,
118 sizeof(struct key)));
119 BUG_ON(parent->blockptrs[parent_slot] != leaf->header.blocknr);
120 }
121 for (i = 0; i < leaf->header.nritems - 2; i++) {
122 BUG_ON(comp_keys(&leaf->items[i].key,
123 &leaf->items[i+1].key) >= 0);
124 BUG_ON(leaf->items[i].offset != leaf->items[i + 1].offset +
125 leaf->items[i + 1].size);
126 if (i == 0) {
127 BUG_ON(leaf->items[i].offset + leaf->items[i].size !=
128 LEAF_DATA_SIZE);
129 }
130 }
131 BUG_ON(leaf_free_space(leaf) < 0);
132 return 0;
133}
134
135int check_block(struct ctree_path *path, int level)
136{
137 if (level == 0)
138 return check_leaf(path, level);
139 return check_node(path, level);
140}
141
77/* 142/*
78 * search for key in the array p. items p are item_size apart 143 * search for key in the array p. items p are item_size apart
79 * and there are 'max' items in p 144 * and there are 'max' items in p
@@ -133,7 +198,8 @@ int bin_search(struct node *c, struct key *key, int *slot)
133 * level of the path (level 0) 198 * level of the path (level 0)
134 * 199 *
135 * If the key isn't found, the path points to the slot where it should 200 * If the key isn't found, the path points to the slot where it should
136 * be inserted. 201 * be inserted, and 1 is returned. If there are other errors during the
202 * search a negative error number is returned.
137 * 203 *
138 * if ins_len > 0, nodes and leaves will be split as we walk down the 204 * if ins_len > 0, nodes and leaves will be split as we walk down the
139 * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if 205 * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if
@@ -153,6 +219,9 @@ int search_slot(struct ctree_root *root, struct key *key,
153 c = &b->node; 219 c = &b->node;
154 level = node_level(c->header.flags); 220 level = node_level(c->header.flags);
155 p->nodes[level] = b; 221 p->nodes[level] = b;
222 ret = check_block(p, level);
223 if (ret)
224 return -1;
156 ret = bin_search(c, key, &slot); 225 ret = bin_search(c, key, &slot);
157 if (!is_leaf(c->header.flags)) { 226 if (!is_leaf(c->header.flags)) {
158 if (ret && slot > 0) 227 if (ret && slot > 0)
@@ -183,7 +252,7 @@ int search_slot(struct ctree_root *root, struct key *key,
183 return ret; 252 return ret;
184 } 253 }
185 } 254 }
186 return -1; 255 return 1;
187} 256}
188 257
189/* 258/*
@@ -192,12 +261,17 @@ int search_slot(struct ctree_root *root, struct key *key,
192 * This is used after shifting pointers to the left, so it stops 261 * This is used after shifting pointers to the left, so it stops
193 * fixing up pointers when a given leaf/node is not in slot 0 of the 262 * fixing up pointers when a given leaf/node is not in slot 0 of the
194 * higher levels 263 * higher levels
264 *
265 * If this fails to write a tree block, it returns -1, but continues
266 * fixing up the blocks in ram so the tree is consistent.
195 */ 267 */
196static void fixup_low_keys(struct ctree_root *root, 268static int fixup_low_keys(struct ctree_root *root,
197 struct ctree_path *path, struct key *key, 269 struct ctree_path *path, struct key *key,
198 int level) 270 int level)
199{ 271{
200 int i; 272 int i;
273 int ret = 0;
274 int wret;
201 for (i = level; i < MAX_LEVEL; i++) { 275 for (i = level; i < MAX_LEVEL; i++) {
202 struct node *t; 276 struct node *t;
203 int tslot = path->slots[i]; 277 int tslot = path->slots[i];
@@ -205,10 +279,13 @@ static void fixup_low_keys(struct ctree_root *root,
205 break; 279 break;
206 t = &path->nodes[i]->node; 280 t = &path->nodes[i]->node;
207 memcpy(t->keys + tslot, key, sizeof(*key)); 281 memcpy(t->keys + tslot, key, sizeof(*key));
208 write_tree_block(root, path->nodes[i]); 282 wret = write_tree_block(root, path->nodes[i]);
283 if (wret)
284 ret = wret;
209 if (tslot != 0) 285 if (tslot != 0)
210 break; 286 break;
211 } 287 }
288 return ret;
212} 289}
213 290
214/* 291/*
@@ -220,8 +297,12 @@ static void fixup_low_keys(struct ctree_root *root,
220 * be modified to reflect the push. 297 * be modified to reflect the push.
221 * 298 *
222 * The path is altered to reflect the push. 299 * The path is altered to reflect the push.
300 *
301 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
302 * error, and > 0 if there was no room in the left hand block.
223 */ 303 */
224int push_node_left(struct ctree_root *root, struct ctree_path *path, int level) 304static int push_node_left(struct ctree_root *root, struct ctree_path *path,
305 int level)
225{ 306{
226 int slot; 307 int slot;
227 struct node *left; 308 struct node *left;
@@ -231,6 +312,8 @@ int push_node_left(struct ctree_root *root, struct ctree_path *path, int level)
231 int right_nritems; 312 int right_nritems;
232 struct tree_buffer *t; 313 struct tree_buffer *t;
233 struct tree_buffer *right_buf; 314 struct tree_buffer *right_buf;
315 int ret = 0;
316 int wret;
234 317
235 if (level == MAX_LEVEL - 1 || path->nodes[level + 1] == 0) 318 if (level == MAX_LEVEL - 1 || path->nodes[level + 1] == 0)
236 return 1; 319 return 1;
@@ -265,10 +348,17 @@ int push_node_left(struct ctree_root *root, struct ctree_path *path, int level)
265 left->header.nritems += push_items; 348 left->header.nritems += push_items;
266 349
267 /* adjust the pointers going up the tree */ 350 /* adjust the pointers going up the tree */
268 fixup_low_keys(root, path, right->keys, level + 1); 351 wret = fixup_low_keys(root, path, right->keys, level + 1);
352 if (wret < 0)
353 ret = wret;
269 354
270 write_tree_block(root, t); 355 wret = write_tree_block(root, t);
271 write_tree_block(root, right_buf); 356 if (wret < 0)
357 ret = wret;
358
359 wret = write_tree_block(root, right_buf);
360 if (wret < 0)
361 ret = wret;
272 362
273 /* then fixup the leaf pointer in the path */ 363 /* then fixup the leaf pointer in the path */
274 if (path->slots[level] < push_items) { 364 if (path->slots[level] < push_items) {
@@ -280,7 +370,7 @@ int push_node_left(struct ctree_root *root, struct ctree_path *path, int level)
280 path->slots[level] -= push_items; 370 path->slots[level] -= push_items;
281 tree_block_release(root, t); 371 tree_block_release(root, t);
282 } 372 }
283 return 0; 373 return ret;
284} 374}
285 375
286/* 376/*
@@ -292,8 +382,12 @@ int push_node_left(struct ctree_root *root, struct ctree_path *path, int level)
292 * be modified to reflect the push. 382 * be modified to reflect the push.
293 * 383 *
294 * The path is altered to reflect the push. 384 * The path is altered to reflect the push.
385 *
386 * returns 0 if some ptrs were pushed, < 0 if there was some horrible
387 * error, and > 0 if there was no room in the right hand block.
295 */ 388 */
296int push_node_right(struct ctree_root *root, struct ctree_path *path, int level) 389static int push_node_right(struct ctree_root *root, struct ctree_path *path,
390 int level)
297{ 391{
298 int slot; 392 int slot;
299 struct tree_buffer *t; 393 struct tree_buffer *t;
@@ -368,6 +462,8 @@ int push_node_right(struct ctree_root *root, struct ctree_path *path, int level)
368 * helper function to insert a new root level in the tree. 462 * helper function to insert a new root level in the tree.
369 * A new node is allocated, and a single item is inserted to 463 * A new node is allocated, and a single item is inserted to
370 * point to the existing root 464 * point to the existing root
465 *
466 * returns zero on success or < 0 on failure.
371 */ 467 */
372static int insert_new_root(struct ctree_root *root, 468static int insert_new_root(struct ctree_root *root,
373 struct ctree_path *path, int level) 469 struct ctree_path *path, int level)
@@ -410,8 +506,10 @@ static int insert_new_root(struct ctree_root *root,
410 * 506 *
411 * slot and level indicate where you want the key to go, and 507 * slot and level indicate where you want the key to go, and
412 * blocknr is the block the key points to. 508 * blocknr is the block the key points to.
509 *
510 * returns zero on success and < 0 on any error
413 */ 511 */
414int insert_ptr(struct ctree_root *root, 512static int insert_ptr(struct ctree_root *root,
415 struct ctree_path *path, struct key *key, 513 struct ctree_path *path, struct key *key,
416 u64 blocknr, int slot, int level) 514 u64 blocknr, int slot, int level)
417{ 515{
@@ -446,8 +544,11 @@ int insert_ptr(struct ctree_root *root,
446 * 544 *
447 * Before splitting this tries to make some room in the node by pushing 545 * Before splitting this tries to make some room in the node by pushing
448 * left and right, if either one works, it returns right away. 546 * left and right, if either one works, it returns right away.
547 *
548 * returns 0 on success and < 0 on failure
449 */ 549 */
450int split_node(struct ctree_root *root, struct ctree_path *path, int level) 550static int split_node(struct ctree_root *root, struct ctree_path *path,
551 int level)
451{ 552{
452 struct tree_buffer *t; 553 struct tree_buffer *t;
453 struct node *c; 554 struct node *c;
@@ -455,13 +556,18 @@ int split_node(struct ctree_root *root, struct ctree_path *path, int level)
455 struct node *split; 556 struct node *split;
456 int mid; 557 int mid;
457 int ret; 558 int ret;
559 int wret;
458 560
459 ret = push_node_left(root, path, level); 561 ret = push_node_left(root, path, level);
460 if (!ret) 562 if (!ret)
461 return 0; 563 return 0;
564 if (ret < 0)
565 return ret;
462 ret = push_node_right(root, path, level); 566 ret = push_node_right(root, path, level);
463 if (!ret) 567 if (!ret)
464 return 0; 568 return 0;
569 if (ret < 0)
570 return ret;
465 t = path->nodes[level]; 571 t = path->nodes[level];
466 c = &t->node; 572 c = &t->node;
467 if (t == root->node) { 573 if (t == root->node) {
@@ -482,10 +588,19 @@ int split_node(struct ctree_root *root, struct ctree_path *path, int level)
482 (c->header.nritems - mid) * sizeof(u64)); 588 (c->header.nritems - mid) * sizeof(u64));
483 split->header.nritems = c->header.nritems - mid; 589 split->header.nritems = c->header.nritems - mid;
484 c->header.nritems = mid; 590 c->header.nritems = mid;
485 write_tree_block(root, t); 591 ret = 0;
486 write_tree_block(root, split_buffer); 592
487 insert_ptr(root, path, split->keys, split_buffer->blocknr, 593 wret = write_tree_block(root, t);
488 path->slots[level + 1] + 1, level + 1); 594 if (wret)
595 ret = wret;
596 wret = write_tree_block(root, split_buffer);
597 if (wret)
598 ret = wret;
599 wret = insert_ptr(root, path, split->keys, split_buffer->blocknr,
600 path->slots[level + 1] + 1, level + 1);
601 if (wret)
602 ret = wret;
603
489 if (path->slots[level] >= mid) { 604 if (path->slots[level] >= mid) {
490 path->slots[level] -= mid; 605 path->slots[level] -= mid;
491 tree_block_release(root, t); 606 tree_block_release(root, t);
@@ -494,7 +609,7 @@ int split_node(struct ctree_root *root, struct ctree_path *path, int level)
494 } else { 609 } else {
495 tree_block_release(root, split_buffer); 610 tree_block_release(root, split_buffer);
496 } 611 }
497 return 0; 612 return ret;
498} 613}
499 614
500/* 615/*
@@ -502,7 +617,7 @@ int split_node(struct ctree_root *root, struct ctree_path *path, int level)
502 * and nr indicate which items in the leaf to check. This totals up the 617 * and nr indicate which items in the leaf to check. This totals up the
503 * space used both by the item structs and the item data 618 * space used both by the item structs and the item data
504 */ 619 */
505int leaf_space_used(struct leaf *l, int start, int nr) 620static int leaf_space_used(struct leaf *l, int start, int nr)
506{ 621{
507 int data_len; 622 int data_len;
508 int end = start + nr - 1; 623 int end = start + nr - 1;
@@ -518,9 +633,12 @@ int leaf_space_used(struct leaf *l, int start, int nr)
518/* 633/*
519 * push some data in the path leaf to the right, trying to free up at 634 * push some data in the path leaf to the right, trying to free up at
520 * least data_size bytes. returns zero if the push worked, nonzero otherwise 635 * least data_size bytes. returns zero if the push worked, nonzero otherwise
636 *
637 * returns 1 if the push failed because the other node didn't have enough
638 * room, 0 if everything worked out and < 0 if there were major errors.
521 */ 639 */
522int push_leaf_right(struct ctree_root *root, struct ctree_path *path, 640static int push_leaf_right(struct ctree_root *root, struct ctree_path *path,
523 int data_size) 641 int data_size)
524{ 642{
525 struct tree_buffer *left_buf = path->nodes[0]; 643 struct tree_buffer *left_buf = path->nodes[0];
526 struct leaf *left = &left_buf->leaf; 644 struct leaf *left = &left_buf->leaf;
@@ -609,8 +727,8 @@ int push_leaf_right(struct ctree_root *root, struct ctree_path *path,
609 * push some data in the path leaf to the left, trying to free up at 727 * push some data in the path leaf to the left, trying to free up at
610 * least data_size bytes. returns zero if the push worked, nonzero otherwise 728 * least data_size bytes. returns zero if the push worked, nonzero otherwise
611 */ 729 */
612int push_leaf_left(struct ctree_root *root, struct ctree_path *path, 730static int push_leaf_left(struct ctree_root *root, struct ctree_path *path,
613 int data_size) 731 int data_size)
614{ 732{
615 struct tree_buffer *right_buf = path->nodes[0]; 733 struct tree_buffer *right_buf = path->nodes[0];
616 struct leaf *right = &right_buf->leaf; 734 struct leaf *right = &right_buf->leaf;
@@ -623,6 +741,8 @@ int push_leaf_left(struct ctree_root *root, struct ctree_path *path,
623 int push_items = 0; 741 int push_items = 0;
624 struct item *item; 742 struct item *item;
625 int old_left_nritems; 743 int old_left_nritems;
744 int ret = 0;
745 int wret;
626 746
627 slot = path->slots[1]; 747 slot = path->slots[1];
628 if (slot == 0) { 748 if (slot == 0) {
@@ -681,10 +801,16 @@ int push_leaf_left(struct ctree_root *root, struct ctree_path *path,
681 push_space = right->items[i].offset; 801 push_space = right->items[i].offset;
682 } 802 }
683 803
684 write_tree_block(root, t); 804 wret = write_tree_block(root, t);
685 write_tree_block(root, right_buf); 805 if (wret)
806 ret = wret;
807 wret = write_tree_block(root, right_buf);
808 if (wret)
809 ret = wret;
686 810
687 fixup_low_keys(root, path, &right->items[0].key, 1); 811 wret = fixup_low_keys(root, path, &right->items[0].key, 1);
812 if (wret)
813 ret = wret;
688 814
689 /* then fixup the leaf pointer in the path */ 815 /* then fixup the leaf pointer in the path */
690 if (path->slots[0] < push_items) { 816 if (path->slots[0] < push_items) {
@@ -697,17 +823,20 @@ int push_leaf_left(struct ctree_root *root, struct ctree_path *path,
697 path->slots[0] -= push_items; 823 path->slots[0] -= push_items;
698 } 824 }
699 BUG_ON(path->slots[0] < 0); 825 BUG_ON(path->slots[0] < 0);
700 return 0; 826 return ret;
701} 827}
702 828
703/* 829/*
704 * split the path's leaf in two, making sure there is at least data_size 830 * split the path's leaf in two, making sure there is at least data_size
705 * available for the resulting leaf level of the path. 831 * available for the resulting leaf level of the path.
832 *
833 * returns 0 if all went well and < 0 on failure.
706 */ 834 */
707int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size) 835static int split_leaf(struct ctree_root *root, struct ctree_path *path,
836 int data_size)
708{ 837{
709 struct tree_buffer *l_buf = path->nodes[0]; 838 struct tree_buffer *l_buf;
710 struct leaf *l = &l_buf->leaf; 839 struct leaf *l;
711 int nritems; 840 int nritems;
712 int mid; 841 int mid;
713 int slot; 842 int slot;
@@ -718,14 +847,23 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size)
718 int rt_data_off; 847 int rt_data_off;
719 int i; 848 int i;
720 int ret; 849 int ret;
721 850 int wret;
722 if (push_leaf_left(root, path, data_size) == 0 || 851
723 push_leaf_right(root, path, data_size) == 0) { 852 wret = push_leaf_left(root, path, data_size);
724 l_buf = path->nodes[0]; 853 if (wret < 0)
725 l = &l_buf->leaf; 854 return wret;
726 if (leaf_free_space(l) >= sizeof(struct item) + data_size) 855 if (wret) {
727 return 0; 856 wret = push_leaf_right(root, path, data_size);
857 if (wret < 0)
858 return wret;
728 } 859 }
860 l_buf = path->nodes[0];
861 l = &l_buf->leaf;
862
863 /* did the pushes work? */
864 if (leaf_free_space(l) >= sizeof(struct item) + data_size)
865 return 0;
866
729 if (!path->nodes[1]) { 867 if (!path->nodes[1]) {
730 ret = insert_new_root(root, path, 1); 868 ret = insert_new_root(root, path, 1);
731 if (ret) 869 if (ret)
@@ -768,10 +906,17 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size)
768 right->items[i].offset += rt_data_off; 906 right->items[i].offset += rt_data_off;
769 907
770 l->header.nritems = mid; 908 l->header.nritems = mid;
771 ret = insert_ptr(root, path, &right->items[0].key, 909 ret = 0;
910 wret = insert_ptr(root, path, &right->items[0].key,
772 right_buffer->blocknr, path->slots[1] + 1, 1); 911 right_buffer->blocknr, path->slots[1] + 1, 1);
773 write_tree_block(root, right_buffer); 912 if (wret)
774 write_tree_block(root, l_buf); 913 ret = wret;
914 wret = write_tree_block(root, right_buffer);
915 if (wret)
916 ret = wret;
917 wret = write_tree_block(root, l_buf);
918 if (wret)
919 ret = wret;
775 920
776 BUG_ON(path->slots[0] != slot); 921 BUG_ON(path->slots[0] != slot);
777 if (mid <= slot) { 922 if (mid <= slot) {
@@ -792,7 +937,8 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size)
792int insert_item(struct ctree_root *root, struct key *key, 937int insert_item(struct ctree_root *root, struct key *key,
793 void *data, int data_size) 938 void *data, int data_size)
794{ 939{
795 int ret; 940 int ret = 0;
941 int wret;
796 int slot; 942 int slot;
797 int slot_orig; 943 int slot_orig;
798 struct leaf *leaf; 944 struct leaf *leaf;
@@ -810,6 +956,10 @@ int insert_item(struct ctree_root *root, struct key *key,
810 release_path(root, &path); 956 release_path(root, &path);
811 return -EEXIST; 957 return -EEXIST;
812 } 958 }
959 if (ret < 0) {
960 release_path(root, &path);
961 return ret;
962 }
813 963
814 slot_orig = path.slots[0]; 964 slot_orig = path.slots[0];
815 leaf_buf = path.nodes[0]; 965 leaf_buf = path.nodes[0];
@@ -850,13 +1000,19 @@ int insert_item(struct ctree_root *root, struct key *key,
850 leaf->items[slot].size = data_size; 1000 leaf->items[slot].size = data_size;
851 memcpy(leaf->data + data_end - data_size, data, data_size); 1001 memcpy(leaf->data + data_end - data_size, data, data_size);
852 leaf->header.nritems += 1; 1002 leaf->header.nritems += 1;
853 write_tree_block(root, leaf_buf); 1003
1004 ret = 0;
854 if (slot == 0) 1005 if (slot == 0)
855 fixup_low_keys(root, &path, key, 1); 1006 ret = fixup_low_keys(root, &path, key, 1);
1007
1008 wret = write_tree_block(root, leaf_buf);
1009 if (wret)
1010 ret = wret;
1011
856 if (leaf_free_space(leaf) < 0) 1012 if (leaf_free_space(leaf) < 0)
857 BUG(); 1013 BUG();
858 release_path(root, &path); 1014 release_path(root, &path);
859 return 0; 1015 return ret;
860} 1016}
861 1017
862/* 1018/*
@@ -866,13 +1022,15 @@ int insert_item(struct ctree_root *root, struct key *key,
866 * continuing all the way the root if required. The root is converted into 1022 * continuing all the way the root if required. The root is converted into
867 * a leaf if all the nodes are emptied. 1023 * a leaf if all the nodes are emptied.
868 */ 1024 */
869int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) 1025static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level)
870{ 1026{
871 int slot; 1027 int slot;
872 struct tree_buffer *t; 1028 struct tree_buffer *t;
873 struct node *node; 1029 struct node *node;
874 int nritems; 1030 int nritems;
875 u64 blocknr; 1031 u64 blocknr;
1032 int wret;
1033 int ret = 0;
876 1034
877 while(1) { 1035 while(1) {
878 t = path->nodes[level]; 1036 t = path->nodes[level];
@@ -894,13 +1052,27 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level)
894 write_tree_block(root, t); 1052 write_tree_block(root, t);
895 if (node->header.nritems != 0) { 1053 if (node->header.nritems != 0) {
896 int tslot; 1054 int tslot;
897 if (slot == 0) 1055 if (slot == 0) {
898 fixup_low_keys(root, path, node->keys, 1056 wret = fixup_low_keys(root, path,
899 level + 1); 1057 node->keys,
1058 level + 1);
1059 if (wret)
1060 ret = wret;
1061 }
900 tslot = path->slots[level + 1]; 1062 tslot = path->slots[level + 1];
901 t->count++; 1063 t->count++;
902 if (push_node_left(root, path, level)) 1064 wret = push_node_left(root, path, level);
903 push_node_right(root, path, level); 1065 if (wret < 0) {
1066 ret = wret;
1067 break;
1068 }
1069 if (node->header.nritems != 0) {
1070 wret = push_node_right(root, path, level);
1071 if (wret < 0) {
1072 ret = wret;
1073 break;
1074 }
1075 }
904 path->slots[level + 1] = tslot; 1076 path->slots[level + 1] = tslot;
905 if (node->header.nritems != 0) { 1077 if (node->header.nritems != 0) {
906 tree_block_release(root, t); 1078 tree_block_release(root, t);
@@ -919,7 +1091,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level)
919 if (!path->nodes[level]) 1091 if (!path->nodes[level])
920 BUG(); 1092 BUG();
921 } 1093 }
922 return 0; 1094 return ret;
923} 1095}
924 1096
925/* 1097/*
@@ -933,6 +1105,8 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
933 struct tree_buffer *leaf_buf; 1105 struct tree_buffer *leaf_buf;
934 int doff; 1106 int doff;
935 int dsize; 1107 int dsize;
1108 int ret = 0;
1109 int wret;
936 1110
937 leaf_buf = path->nodes[0]; 1111 leaf_buf = path->nodes[0];
938 leaf = &leaf_buf->leaf; 1112 leaf = &leaf_buf->leaf;
@@ -959,14 +1133,23 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
959 leaf->header.flags = node_level(0); 1133 leaf->header.flags = node_level(0);
960 write_tree_block(root, leaf_buf); 1134 write_tree_block(root, leaf_buf);
961 } else { 1135 } else {
962 del_ptr(root, path, 1); 1136 wret = del_ptr(root, path, 1);
1137 if (wret)
1138 ret = wret;
963 free_extent(root, leaf_buf->blocknr, 1); 1139 free_extent(root, leaf_buf->blocknr, 1);
964 } 1140 }
965 } else { 1141 } else {
966 int used = leaf_space_used(leaf, 0, leaf->header.nritems); 1142 int used = leaf_space_used(leaf, 0, leaf->header.nritems);
967 if (slot == 0) 1143 if (slot == 0) {
968 fixup_low_keys(root, path, &leaf->items[0].key, 1); 1144 wret = fixup_low_keys(root, path,
969 write_tree_block(root, leaf_buf); 1145 &leaf->items[0].key, 1);
1146 if (wret)
1147 ret = wret;
1148 }
1149 wret = write_tree_block(root, leaf_buf);
1150 if (wret)
1151 ret = wret;
1152
970 /* delete the leaf if it is mostly empty */ 1153 /* delete the leaf if it is mostly empty */
971 if (used < LEAF_DATA_SIZE / 3) { 1154 if (used < LEAF_DATA_SIZE / 3) {
972 /* push_leaf_left fixes the path. 1155 /* push_leaf_left fixes the path.
@@ -975,13 +1158,20 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
975 */ 1158 */
976 slot = path->slots[1]; 1159 slot = path->slots[1];
977 leaf_buf->count++; 1160 leaf_buf->count++;
978 push_leaf_left(root, path, 1); 1161 wret = push_leaf_left(root, path, 1);
979 if (leaf->header.nritems) 1162 if (wret < 0)
980 push_leaf_right(root, path, 1); 1163 ret = wret;
1164 if (leaf->header.nritems) {
1165 wret = push_leaf_right(root, path, 1);
1166 if (wret < 0)
1167 ret = wret;
1168 }
981 if (leaf->header.nritems == 0) { 1169 if (leaf->header.nritems == 0) {
982 u64 blocknr = leaf_buf->blocknr; 1170 u64 blocknr = leaf_buf->blocknr;
983 path->slots[1] = slot; 1171 path->slots[1] = slot;
984 del_ptr(root, path, 1); 1172 wret = del_ptr(root, path, 1);
1173 if (wret)
1174 ret = wret;
985 tree_block_release(root, leaf_buf); 1175 tree_block_release(root, leaf_buf);
986 free_extent(root, blocknr, 1); 1176 free_extent(root, blocknr, 1);
987 } else { 1177 } else {
@@ -989,7 +1179,7 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
989 } 1179 }
990 } 1180 }
991 } 1181 }
992 return 0; 1182 return ret;
993} 1183}
994 1184
995/* 1185/*
@@ -1033,165 +1223,3 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path)
1033 return 0; 1223 return 0;
1034} 1224}
1035 1225
1036/* some sample code to insert,search & delete items */
1037#if 0
1038/* for testing only */
1039int next_key(int i, int max_key) {
1040 return rand() % max_key;
1041 //return i;
1042}
1043int main() {
1044 struct key ins;
1045 struct key last = { (u64)-1, 0, 0};
1046 char *buf;
1047 int i;
1048 int num;
1049 int ret;
1050 int run_size = 20000000;
1051 int max_key = 100000000;
1052 int tree_size = 0;
1053 struct ctree_path path;
1054 struct ctree_super_block super;
1055 struct ctree_root *root;
1056
1057 radix_tree_init();
1058
1059
1060 root = open_ctree("dbfile", &super);
1061 srand(55);
1062 for (i = 0; i < run_size; i++) {
1063 buf = malloc(64);
1064 num = next_key(i, max_key);
1065 // num = i;
1066 sprintf(buf, "string-%d", num);
1067 if (i % 10000 == 0)
1068 fprintf(stderr, "insert %d:%d\n", num, i);
1069 ins.objectid = num;
1070 ins.offset = 0;
1071 ins.flags = 0;
1072 ret = insert_item(root, &ins, buf, strlen(buf));
1073 if (!ret)
1074 tree_size++;
1075 free(buf);
1076 }
1077 write_ctree_super(root, &super);
1078 close_ctree(root);
1079
1080 root = open_ctree("dbfile", &super);
1081 printf("starting search\n");
1082 srand(55);
1083 for (i = 0; i < run_size; i++) {
1084 num = next_key(i, max_key);
1085 ins.objectid = num;
1086 init_path(&path);
1087 if (i % 10000 == 0)
1088 fprintf(stderr, "search %d:%d\n", num, i);
1089 ret = search_slot(root, &ins, &path, 0);
1090 if (ret) {
1091 print_tree(root, root->node);
1092 printf("unable to find %d\n", num);
1093 exit(1);
1094 }
1095 release_path(root, &path);
1096 }
1097 write_ctree_super(root, &super);
1098 close_ctree(root);
1099 root = open_ctree("dbfile", &super);
1100 printf("node %p level %d total ptrs %d free spc %lu\n", root->node,
1101 node_level(root->node->node.header.flags),
1102 root->node->node.header.nritems,
1103 NODEPTRS_PER_BLOCK - root->node->node.header.nritems);
1104 printf("all searches good, deleting some items\n");
1105 i = 0;
1106 srand(55);
1107 for (i = 0 ; i < run_size/4; i++) {
1108 num = next_key(i, max_key);
1109 ins.objectid = num;
1110 init_path(&path);
1111 ret = search_slot(root, &ins, &path, -1);
1112 if (!ret) {
1113 if (i % 10000 == 0)
1114 fprintf(stderr, "del %d:%d\n", num, i);
1115 ret = del_item(root, &path);
1116 if (ret != 0)
1117 BUG();
1118 tree_size--;
1119 }
1120 release_path(root, &path);
1121 }
1122 write_ctree_super(root, &super);
1123 close_ctree(root);
1124 root = open_ctree("dbfile", &super);
1125 srand(128);
1126 for (i = 0; i < run_size; i++) {
1127 buf = malloc(64);
1128 num = next_key(i, max_key);
1129 sprintf(buf, "string-%d", num);
1130 ins.objectid = num;
1131 if (i % 10000 == 0)
1132 fprintf(stderr, "insert %d:%d\n", num, i);
1133 ret = insert_item(root, &ins, buf, strlen(buf));
1134 if (!ret)
1135 tree_size++;
1136 free(buf);
1137 }
1138 write_ctree_super(root, &super);
1139 close_ctree(root);
1140 root = open_ctree("dbfile", &super);
1141 srand(128);
1142 printf("starting search2\n");
1143 for (i = 0; i < run_size; i++) {
1144 num = next_key(i, max_key);
1145 ins.objectid = num;
1146 init_path(&path);
1147 if (i % 10000 == 0)
1148 fprintf(stderr, "search %d:%d\n", num, i);
1149 ret = search_slot(root, &ins, &path, 0);
1150 if (ret) {
1151 print_tree(root, root->node);
1152 printf("unable to find %d\n", num);
1153 exit(1);
1154 }
1155 release_path(root, &path);
1156 }
1157 printf("starting big long delete run\n");
1158 while(root->node && root->node->node.header.nritems > 0) {
1159 struct leaf *leaf;
1160 int slot;
1161 ins.objectid = (u64)-1;
1162 init_path(&path);
1163 ret = search_slot(root, &ins, &path, -1);
1164 if (ret == 0)
1165 BUG();
1166
1167 leaf = &path.nodes[0]->leaf;
1168 slot = path.slots[0];
1169 if (slot != leaf->header.nritems)
1170 BUG();
1171 while(path.slots[0] > 0) {
1172 path.slots[0] -= 1;
1173 slot = path.slots[0];
1174 leaf = &path.nodes[0]->leaf;
1175
1176 if (comp_keys(&last, &leaf->items[slot].key) <= 0)
1177 BUG();
1178 memcpy(&last, &leaf->items[slot].key, sizeof(last));
1179 if (tree_size % 10000 == 0)
1180 printf("big del %d:%d\n", tree_size, i);
1181 ret = del_item(root, &path);
1182 if (ret != 0) {
1183 printf("del_item returned %d\n", ret);
1184 BUG();
1185 }
1186 tree_size--;
1187 }
1188 release_path(root, &path);
1189 }
1190 printf("tree size is now %d\n", tree_size);
1191 printf("map tree\n");
1192 print_tree(root->extent_root, root->extent_root->node);
1193 write_ctree_super(root, &super);
1194 close_ctree(root);
1195 return 0;
1196}
1197#endif