aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-03-02 16:08:05 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-03-02 16:08:05 -0500
commit02217ed299c6340a35696e0610047eb96826de2d (patch)
tree4a92c16ce2a51f701c829d96f644486fb7b29517 /fs/btrfs/ctree.c
parent77ce6846c40e83193df01295e5af437f8b6c7a2d (diff)
Btrfs: early reference counting
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c153
1 files changed, 88 insertions, 65 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 3c5f4c2dd525..1118986d7569 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -34,6 +34,37 @@ void release_path(struct ctree_root *root, struct ctree_path *p)
34 memset(p, 0, sizeof(*p)); 34 memset(p, 0, sizeof(*p));
35} 35}
36 36
37int btrfs_cow_block(struct ctree_root *root,
38 struct tree_buffer *buf,
39 struct tree_buffer *parent,
40 int parent_slot,
41 struct tree_buffer **cow_ret)
42{
43 struct tree_buffer *cow;
44
45 if (!list_empty(&buf->dirty)) {
46 *cow_ret = buf;
47 return 0;
48 }
49 cow = alloc_free_block(root);
50 memcpy(&cow->node, &buf->node, sizeof(buf->node));
51 cow->node.header.blocknr = cow->blocknr;
52 *cow_ret = cow;
53 if (buf == root->node) {
54 root->node = cow;
55 cow->count++;
56 tree_block_release(root, buf);
57 } else {
58 parent->node.blockptrs[parent_slot] = cow->blocknr;
59 BUG_ON(list_empty(&parent->dirty));
60 }
61 if (0 && root != root->extent_root && !is_leaf(cow->node.header.flags)) {
62 btrfs_inc_ref(root, cow);
63 }
64 tree_block_release(root, buf);
65 return 0;
66}
67
37/* 68/*
38 * The leaf data grows from end-to-front in the node. 69 * The leaf data grows from end-to-front in the node.
39 * this returns the address of the start of the last item, 70 * this returns the address of the start of the last item,
@@ -263,6 +294,8 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path,
263 294
264 /* first, try to make some room in the middle buffer */ 295 /* first, try to make some room in the middle buffer */
265 if (left_buf) { 296 if (left_buf) {
297 btrfs_cow_block(root, left_buf, parent_buf,
298 pslot - 1, &left_buf);
266 left = &left_buf->node; 299 left = &left_buf->node;
267 orig_slot += left->header.nritems; 300 orig_slot += left->header.nritems;
268 wret = push_node_left(root, left_buf, mid_buf); 301 wret = push_node_left(root, left_buf, mid_buf);
@@ -274,6 +307,8 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path,
274 * then try to empty the right most buffer into the middle 307 * then try to empty the right most buffer into the middle
275 */ 308 */
276 if (right_buf) { 309 if (right_buf) {
310 btrfs_cow_block(root, right_buf, parent_buf,
311 pslot + 1, &right_buf);
277 right = &right_buf->node; 312 right = &right_buf->node;
278 wret = push_node_left(root, mid_buf, right_buf); 313 wret = push_node_left(root, mid_buf, right_buf);
279 if (wret < 0) 314 if (wret < 0)
@@ -293,9 +328,7 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path,
293 } else { 328 } else {
294 memcpy(parent->keys + pslot + 1, right->keys, 329 memcpy(parent->keys + pslot + 1, right->keys,
295 sizeof(struct key)); 330 sizeof(struct key));
296 wret = dirty_tree_block(root, parent_buf); 331 BUG_ON(list_empty(&parent_buf->dirty));
297 if (wret)
298 ret = wret;
299 } 332 }
300 } 333 }
301 if (mid->header.nritems == 1) { 334 if (mid->header.nritems == 1) {
@@ -330,9 +363,7 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path,
330 } else { 363 } else {
331 /* update the parent key to reflect our changes */ 364 /* update the parent key to reflect our changes */
332 memcpy(parent->keys + pslot, mid->keys, sizeof(struct key)); 365 memcpy(parent->keys + pslot, mid->keys, sizeof(struct key));
333 wret = dirty_tree_block(root, parent_buf); 366 BUG_ON(list_empty(&parent_buf->dirty));
334 if (wret)
335 ret = wret;
336 } 367 }
337 368
338 /* update the path */ 369 /* update the path */
@@ -375,9 +406,10 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path,
375 * possible) 406 * possible)
376 */ 407 */
377int search_slot(struct ctree_root *root, struct key *key, 408int search_slot(struct ctree_root *root, struct key *key,
378 struct ctree_path *p, int ins_len) 409 struct ctree_path *p, int ins_len, int cow)
379{ 410{
380 struct tree_buffer *b; 411 struct tree_buffer *b;
412 struct tree_buffer *cow_buf;
381 struct node *c; 413 struct node *c;
382 int slot; 414 int slot;
383 int ret; 415 int ret;
@@ -387,8 +419,15 @@ again:
387 b = root->node; 419 b = root->node;
388 b->count++; 420 b->count++;
389 while (b) { 421 while (b) {
422 level = node_level(b->node.header.flags);
423 if (cow) {
424 int wret;
425 wret = btrfs_cow_block(root, b, p->nodes[level + 1],
426 p->slots[level + 1], &cow_buf);
427 b = cow_buf;
428 }
429 BUG_ON(!cow && ins_len);
390 c = &b->node; 430 c = &b->node;
391 level = node_level(c->header.flags);
392 p->nodes[level] = b; 431 p->nodes[level] = b;
393 ret = check_block(p, level); 432 ret = check_block(p, level);
394 if (ret) 433 if (ret)
@@ -453,7 +492,6 @@ static int fixup_low_keys(struct ctree_root *root,
453{ 492{
454 int i; 493 int i;
455 int ret = 0; 494 int ret = 0;
456 int wret;
457 for (i = level; i < MAX_LEVEL; i++) { 495 for (i = level; i < MAX_LEVEL; i++) {
458 struct node *t; 496 struct node *t;
459 int tslot = path->slots[i]; 497 int tslot = path->slots[i];
@@ -461,9 +499,7 @@ static int fixup_low_keys(struct ctree_root *root,
461 break; 499 break;
462 t = &path->nodes[i]->node; 500 t = &path->nodes[i]->node;
463 memcpy(t->keys + tslot, key, sizeof(*key)); 501 memcpy(t->keys + tslot, key, sizeof(*key));
464 wret = dirty_tree_block(root, path->nodes[i]); 502 BUG_ON(list_empty(&path->nodes[i]->dirty));
465 if (wret)
466 ret = wret;
467 if (tslot != 0) 503 if (tslot != 0)
468 break; 504 break;
469 } 505 }
@@ -486,7 +522,6 @@ static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf,
486 int src_nritems; 522 int src_nritems;
487 int dst_nritems; 523 int dst_nritems;
488 int ret = 0; 524 int ret = 0;
489 int wret;
490 525
491 src_nritems = src->header.nritems; 526 src_nritems = src->header.nritems;
492 dst_nritems = dst->header.nritems; 527 dst_nritems = dst->header.nritems;
@@ -511,13 +546,8 @@ static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf,
511 src->header.nritems -= push_items; 546 src->header.nritems -= push_items;
512 dst->header.nritems += push_items; 547 dst->header.nritems += push_items;
513 548
514 wret = dirty_tree_block(root, src_buf); 549 BUG_ON(list_empty(&src_buf->dirty));
515 if (wret < 0) 550 BUG_ON(list_empty(&dst_buf->dirty));
516 ret = wret;
517
518 wret = dirty_tree_block(root, dst_buf);
519 if (wret < 0)
520 ret = wret;
521 return ret; 551 return ret;
522} 552}
523 553
@@ -541,7 +571,6 @@ static int balance_node_right(struct ctree_root *root,
541 int src_nritems; 571 int src_nritems;
542 int dst_nritems; 572 int dst_nritems;
543 int ret = 0; 573 int ret = 0;
544 int wret;
545 574
546 src_nritems = src->header.nritems; 575 src_nritems = src->header.nritems;
547 dst_nritems = dst->header.nritems; 576 dst_nritems = dst->header.nritems;
@@ -569,13 +598,8 @@ static int balance_node_right(struct ctree_root *root,
569 src->header.nritems -= push_items; 598 src->header.nritems -= push_items;
570 dst->header.nritems += push_items; 599 dst->header.nritems += push_items;
571 600
572 wret = dirty_tree_block(root, src_buf); 601 BUG_ON(list_empty(&src_buf->dirty));
573 if (wret < 0) 602 BUG_ON(list_empty(&dst_buf->dirty));
574 ret = wret;
575
576 wret = dirty_tree_block(root, dst_buf);
577 if (wret < 0)
578 ret = wret;
579 return ret; 603 return ret;
580} 604}
581 605
@@ -615,7 +639,6 @@ static int insert_new_root(struct ctree_root *root,
615 tree_block_release(root, root->node); 639 tree_block_release(root, root->node);
616 root->node = t; 640 root->node = t;
617 t->count++; 641 t->count++;
618 dirty_tree_block(root, t);
619 path->nodes[level] = t; 642 path->nodes[level] = t;
620 path->slots[level] = 0; 643 path->slots[level] = 0;
621 return 0; 644 return 0;
@@ -655,7 +678,7 @@ static int insert_ptr(struct ctree_root *root,
655 lower->header.nritems++; 678 lower->header.nritems++;
656 if (lower->keys[1].objectid == 0) 679 if (lower->keys[1].objectid == 0)
657 BUG(); 680 BUG();
658 dirty_tree_block(root, path->nodes[level]); 681 BUG_ON(list_empty(&path->nodes[level]->dirty));
659 return 0; 682 return 0;
660} 683}
661 684
@@ -701,12 +724,7 @@ static int split_node(struct ctree_root *root, struct ctree_path *path,
701 c->header.nritems = mid; 724 c->header.nritems = mid;
702 ret = 0; 725 ret = 0;
703 726
704 wret = dirty_tree_block(root, t); 727 BUG_ON(list_empty(&t->dirty));
705 if (wret)
706 ret = wret;
707 wret = dirty_tree_block(root, split_buffer);
708 if (wret)
709 ret = wret;
710 wret = insert_ptr(root, path, split->keys, split_buffer->blocknr, 728 wret = insert_ptr(root, path, split->keys, split_buffer->blocknr,
711 path->slots[level + 1] + 1, level + 1); 729 path->slots[level + 1] + 1, level + 1);
712 if (wret) 730 if (wret)
@@ -778,6 +796,15 @@ static int push_leaf_right(struct ctree_root *root, struct ctree_path *path,
778 tree_block_release(root, right_buf); 796 tree_block_release(root, right_buf);
779 return 1; 797 return 1;
780 } 798 }
799 /* cow and double check */
800 btrfs_cow_block(root, right_buf, upper, slot + 1, &right_buf);
801 right = &right_buf->leaf;
802 free_space = leaf_free_space(right);
803 if (free_space < data_size + sizeof(struct item)) {
804 tree_block_release(root, right_buf);
805 return 1;
806 }
807
781 for (i = left->header.nritems - 1; i >= 0; i--) { 808 for (i = left->header.nritems - 1; i >= 0; i--) {
782 item = left->items + i; 809 item = left->items + i;
783 if (path->slots[0] == i) 810 if (path->slots[0] == i)
@@ -818,11 +845,12 @@ static int push_leaf_right(struct ctree_root *root, struct ctree_path *path,
818 } 845 }
819 left->header.nritems -= push_items; 846 left->header.nritems -= push_items;
820 847
821 dirty_tree_block(root, left_buf); 848 BUG_ON(list_empty(&left_buf->dirty));
822 dirty_tree_block(root, right_buf); 849 BUG_ON(list_empty(&right_buf->dirty));
823 memcpy(upper->node.keys + slot + 1, 850 memcpy(upper->node.keys + slot + 1,
824 &right->items[0].key, sizeof(struct key)); 851 &right->items[0].key, sizeof(struct key));
825 dirty_tree_block(root, upper); 852 BUG_ON(list_empty(&upper->dirty));
853
826 /* then fixup the leaf pointer in the path */ 854 /* then fixup the leaf pointer in the path */
827 if (path->slots[0] >= left->header.nritems) { 855 if (path->slots[0] >= left->header.nritems) {
828 path->slots[0] -= left->header.nritems; 856 path->slots[0] -= left->header.nritems;
@@ -869,6 +897,16 @@ static int push_leaf_left(struct ctree_root *root, struct ctree_path *path,
869 tree_block_release(root, t); 897 tree_block_release(root, t);
870 return 1; 898 return 1;
871 } 899 }
900
901 /* cow and double check */
902 btrfs_cow_block(root, t, path->nodes[1], slot - 1, &t);
903 left = &t->leaf;
904 free_space = leaf_free_space(left);
905 if (free_space < data_size + sizeof(struct item)) {
906 tree_block_release(root, t);
907 return 1;
908 }
909
872 for (i = 0; i < right->header.nritems; i++) { 910 for (i = 0; i < right->header.nritems; i++) {
873 item = right->items + i; 911 item = right->items + i;
874 if (path->slots[0] == i) 912 if (path->slots[0] == i)
@@ -912,12 +950,8 @@ static int push_leaf_left(struct ctree_root *root, struct ctree_path *path,
912 push_space = right->items[i].offset; 950 push_space = right->items[i].offset;
913 } 951 }
914 952
915 wret = dirty_tree_block(root, t); 953 BUG_ON(list_empty(&t->dirty));
916 if (wret) 954 BUG_ON(list_empty(&right_buf->dirty));
917 ret = wret;
918 wret = dirty_tree_block(root, right_buf);
919 if (wret)
920 ret = wret;
921 955
922 wret = fixup_low_keys(root, path, &right->items[0].key, 1); 956 wret = fixup_low_keys(root, path, &right->items[0].key, 1);
923 if (wret) 957 if (wret)
@@ -968,6 +1002,7 @@ static int split_leaf(struct ctree_root *root, struct ctree_path *path,
968 if (wret < 0) 1002 if (wret < 0)
969 return wret; 1003 return wret;
970 } 1004 }
1005
971 l_buf = path->nodes[0]; 1006 l_buf = path->nodes[0];
972 l = &l_buf->leaf; 1007 l = &l_buf->leaf;
973 1008
@@ -1022,13 +1057,8 @@ static int split_leaf(struct ctree_root *root, struct ctree_path *path,
1022 right_buffer->blocknr, path->slots[1] + 1, 1); 1057 right_buffer->blocknr, path->slots[1] + 1, 1);
1023 if (wret) 1058 if (wret)
1024 ret = wret; 1059 ret = wret;
1025 wret = dirty_tree_block(root, right_buffer); 1060 BUG_ON(list_empty(&right_buffer->dirty));
1026 if (wret) 1061 BUG_ON(list_empty(&l_buf->dirty));
1027 ret = wret;
1028 wret = dirty_tree_block(root, l_buf);
1029 if (wret)
1030 ret = wret;
1031
1032 BUG_ON(path->slots[0] != slot); 1062 BUG_ON(path->slots[0] != slot);
1033 if (mid <= slot) { 1063 if (mid <= slot) {
1034 tree_block_release(root, path->nodes[0]); 1064 tree_block_release(root, path->nodes[0]);
@@ -1049,7 +1079,6 @@ int insert_item(struct ctree_root *root, struct key *key,
1049 void *data, int data_size) 1079 void *data, int data_size)
1050{ 1080{
1051 int ret = 0; 1081 int ret = 0;
1052 int wret;
1053 int slot; 1082 int slot;
1054 int slot_orig; 1083 int slot_orig;
1055 struct leaf *leaf; 1084 struct leaf *leaf;
@@ -1062,7 +1091,7 @@ int insert_item(struct ctree_root *root, struct key *key,
1062 if (!root->node) 1091 if (!root->node)
1063 BUG(); 1092 BUG();
1064 init_path(&path); 1093 init_path(&path);
1065 ret = search_slot(root, key, &path, data_size); 1094 ret = search_slot(root, key, &path, data_size, 1);
1066 if (ret == 0) { 1095 if (ret == 0) {
1067 release_path(root, &path); 1096 release_path(root, &path);
1068 return -EEXIST; 1097 return -EEXIST;
@@ -1114,10 +1143,7 @@ int insert_item(struct ctree_root *root, struct key *key,
1114 if (slot == 0) 1143 if (slot == 0)
1115 ret = fixup_low_keys(root, &path, key, 1); 1144 ret = fixup_low_keys(root, &path, key, 1);
1116 1145
1117 wret = dirty_tree_block(root, leaf_buf); 1146 BUG_ON(list_empty(&leaf_buf->dirty));
1118 if (wret)
1119 ret = wret;
1120
1121 if (leaf_free_space(leaf) < 0) 1147 if (leaf_free_space(leaf) < 0)
1122 BUG(); 1148 BUG();
1123 check_leaf(&path, 0); 1149 check_leaf(&path, 0);
@@ -1162,9 +1188,7 @@ static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
1162 if (wret) 1188 if (wret)
1163 ret = wret; 1189 ret = wret;
1164 } 1190 }
1165 wret = dirty_tree_block(root, parent); 1191 BUG_ON(list_empty(&parent->dirty));
1166 if (wret)
1167 ret = wret;
1168 return ret; 1192 return ret;
1169} 1193}
1170 1194
@@ -1205,7 +1229,7 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
1205 if (leaf->header.nritems == 0) { 1229 if (leaf->header.nritems == 0) {
1206 if (leaf_buf == root->node) { 1230 if (leaf_buf == root->node) {
1207 leaf->header.flags = node_level(0); 1231 leaf->header.flags = node_level(0);
1208 dirty_tree_block(root, leaf_buf); 1232 BUG_ON(list_empty(&leaf_buf->dirty));
1209 } else { 1233 } else {
1210 clean_tree_block(root, leaf_buf); 1234 clean_tree_block(root, leaf_buf);
1211 wret = del_ptr(root, path, 1, path->slots[1]); 1235 wret = del_ptr(root, path, 1, path->slots[1]);
@@ -1223,9 +1247,7 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
1223 if (wret) 1247 if (wret)
1224 ret = wret; 1248 ret = wret;
1225 } 1249 }
1226 wret = dirty_tree_block(root, leaf_buf); 1250 BUG_ON(list_empty(&leaf_buf->dirty));
1227 if (wret)
1228 ret = wret;
1229 1251
1230 /* delete the leaf if it is mostly empty */ 1252 /* delete the leaf if it is mostly empty */
1231 if (used < LEAF_DATA_SIZE / 3) { 1253 if (used < LEAF_DATA_SIZE / 3) {
@@ -1304,3 +1326,4 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path)
1304 return 0; 1326 return 0;
1305} 1327}
1306 1328
1329