aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2010-05-16 10:46:25 -0400
committerChris Mason <chris.mason@oracle.com>2010-05-25 10:34:50 -0400
commitf0486c68e4bd9a06a5904d3eeb3a0d73a83befb8 (patch)
tree509428ef400ef45e875a3c448b63b86cbea36aea /fs/btrfs/ctree.c
parent2ead6ae770d9f9dec9f4286bf0fd9001b4388c4b (diff)
Btrfs: Introduce contexts for metadata reservation
Introducing metadata reseravtion contexts has two major advantages. First, it makes metadata reseravtion more traceable. Second, it can reclaim freed space and re-add them to the itself after transaction committed. Besides add btrfs_block_rsv structure and related helper functions, This patch contains following changes: Move code that decides if freed tree block should be pinned into btrfs_free_tree_block(). Make space accounting more accurate, mainly for handling read only block groups. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c104
1 files changed, 63 insertions, 41 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 6795a713b205..6bee8e5204fb 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -280,7 +280,8 @@ int btrfs_block_can_be_shared(struct btrfs_root *root,
280static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, 280static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
281 struct btrfs_root *root, 281 struct btrfs_root *root,
282 struct extent_buffer *buf, 282 struct extent_buffer *buf,
283 struct extent_buffer *cow) 283 struct extent_buffer *cow,
284 int *last_ref)
284{ 285{
285 u64 refs; 286 u64 refs;
286 u64 owner; 287 u64 owner;
@@ -366,6 +367,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
366 BUG_ON(ret); 367 BUG_ON(ret);
367 } 368 }
368 clean_tree_block(trans, root, buf); 369 clean_tree_block(trans, root, buf);
370 *last_ref = 1;
369 } 371 }
370 return 0; 372 return 0;
371} 373}
@@ -392,6 +394,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
392 struct btrfs_disk_key disk_key; 394 struct btrfs_disk_key disk_key;
393 struct extent_buffer *cow; 395 struct extent_buffer *cow;
394 int level; 396 int level;
397 int last_ref = 0;
395 int unlock_orig = 0; 398 int unlock_orig = 0;
396 u64 parent_start; 399 u64 parent_start;
397 400
@@ -442,7 +445,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
442 (unsigned long)btrfs_header_fsid(cow), 445 (unsigned long)btrfs_header_fsid(cow),
443 BTRFS_FSID_SIZE); 446 BTRFS_FSID_SIZE);
444 447
445 update_ref_for_cow(trans, root, buf, cow); 448 update_ref_for_cow(trans, root, buf, cow, &last_ref);
446 449
447 if (buf == root->node) { 450 if (buf == root->node) {
448 WARN_ON(parent && parent != buf); 451 WARN_ON(parent && parent != buf);
@@ -457,8 +460,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
457 extent_buffer_get(cow); 460 extent_buffer_get(cow);
458 spin_unlock(&root->node_lock); 461 spin_unlock(&root->node_lock);
459 462
460 btrfs_free_tree_block(trans, root, buf->start, buf->len, 463 btrfs_free_tree_block(trans, root, buf, parent_start,
461 parent_start, root->root_key.objectid, level); 464 last_ref);
462 free_extent_buffer(buf); 465 free_extent_buffer(buf);
463 add_root_to_dirty_list(root); 466 add_root_to_dirty_list(root);
464 } else { 467 } else {
@@ -473,8 +476,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
473 btrfs_set_node_ptr_generation(parent, parent_slot, 476 btrfs_set_node_ptr_generation(parent, parent_slot,
474 trans->transid); 477 trans->transid);
475 btrfs_mark_buffer_dirty(parent); 478 btrfs_mark_buffer_dirty(parent);
476 btrfs_free_tree_block(trans, root, buf->start, buf->len, 479 btrfs_free_tree_block(trans, root, buf, parent_start,
477 parent_start, root->root_key.objectid, level); 480 last_ref);
478 } 481 }
479 if (unlock_orig) 482 if (unlock_orig)
480 btrfs_tree_unlock(buf); 483 btrfs_tree_unlock(buf);
@@ -949,6 +952,22 @@ int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
949 return bin_search(eb, key, level, slot); 952 return bin_search(eb, key, level, slot);
950} 953}
951 954
955static void root_add_used(struct btrfs_root *root, u32 size)
956{
957 spin_lock(&root->accounting_lock);
958 btrfs_set_root_used(&root->root_item,
959 btrfs_root_used(&root->root_item) + size);
960 spin_unlock(&root->accounting_lock);
961}
962
963static void root_sub_used(struct btrfs_root *root, u32 size)
964{
965 spin_lock(&root->accounting_lock);
966 btrfs_set_root_used(&root->root_item,
967 btrfs_root_used(&root->root_item) - size);
968 spin_unlock(&root->accounting_lock);
969}
970
952/* given a node and slot number, this reads the blocks it points to. The 971/* given a node and slot number, this reads the blocks it points to. The
953 * extent buffer is returned with a reference taken (but unlocked). 972 * extent buffer is returned with a reference taken (but unlocked).
954 * NULL is returned on error. 973 * NULL is returned on error.
@@ -1019,7 +1038,11 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1019 btrfs_tree_lock(child); 1038 btrfs_tree_lock(child);
1020 btrfs_set_lock_blocking(child); 1039 btrfs_set_lock_blocking(child);
1021 ret = btrfs_cow_block(trans, root, child, mid, 0, &child); 1040 ret = btrfs_cow_block(trans, root, child, mid, 0, &child);
1022 BUG_ON(ret); 1041 if (ret) {
1042 btrfs_tree_unlock(child);
1043 free_extent_buffer(child);
1044 goto enospc;
1045 }
1023 1046
1024 spin_lock(&root->node_lock); 1047 spin_lock(&root->node_lock);
1025 root->node = child; 1048 root->node = child;
@@ -1034,11 +1057,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1034 btrfs_tree_unlock(mid); 1057 btrfs_tree_unlock(mid);
1035 /* once for the path */ 1058 /* once for the path */
1036 free_extent_buffer(mid); 1059 free_extent_buffer(mid);
1037 ret = btrfs_free_tree_block(trans, root, mid->start, mid->len, 1060
1038 0, root->root_key.objectid, level); 1061 root_sub_used(root, mid->len);
1062 btrfs_free_tree_block(trans, root, mid, 0, 1);
1039 /* once for the root ptr */ 1063 /* once for the root ptr */
1040 free_extent_buffer(mid); 1064 free_extent_buffer(mid);
1041 return ret; 1065 return 0;
1042 } 1066 }
1043 if (btrfs_header_nritems(mid) > 1067 if (btrfs_header_nritems(mid) >
1044 BTRFS_NODEPTRS_PER_BLOCK(root) / 4) 1068 BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
@@ -1088,23 +1112,16 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1088 if (wret < 0 && wret != -ENOSPC) 1112 if (wret < 0 && wret != -ENOSPC)
1089 ret = wret; 1113 ret = wret;
1090 if (btrfs_header_nritems(right) == 0) { 1114 if (btrfs_header_nritems(right) == 0) {
1091 u64 bytenr = right->start;
1092 u32 blocksize = right->len;
1093
1094 clean_tree_block(trans, root, right); 1115 clean_tree_block(trans, root, right);
1095 btrfs_tree_unlock(right); 1116 btrfs_tree_unlock(right);
1096 free_extent_buffer(right);
1097 right = NULL;
1098 wret = del_ptr(trans, root, path, level + 1, pslot + 1117 wret = del_ptr(trans, root, path, level + 1, pslot +
1099 1); 1118 1);
1100 if (wret) 1119 if (wret)
1101 ret = wret; 1120 ret = wret;
1102 wret = btrfs_free_tree_block(trans, root, 1121 root_sub_used(root, right->len);
1103 bytenr, blocksize, 0, 1122 btrfs_free_tree_block(trans, root, right, 0, 1);
1104 root->root_key.objectid, 1123 free_extent_buffer(right);
1105 level); 1124 right = NULL;
1106 if (wret)
1107 ret = wret;
1108 } else { 1125 } else {
1109 struct btrfs_disk_key right_key; 1126 struct btrfs_disk_key right_key;
1110 btrfs_node_key(right, &right_key, 0); 1127 btrfs_node_key(right, &right_key, 0);
@@ -1136,21 +1153,15 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1136 BUG_ON(wret == 1); 1153 BUG_ON(wret == 1);
1137 } 1154 }
1138 if (btrfs_header_nritems(mid) == 0) { 1155 if (btrfs_header_nritems(mid) == 0) {
1139 /* we've managed to empty the middle node, drop it */
1140 u64 bytenr = mid->start;
1141 u32 blocksize = mid->len;
1142
1143 clean_tree_block(trans, root, mid); 1156 clean_tree_block(trans, root, mid);
1144 btrfs_tree_unlock(mid); 1157 btrfs_tree_unlock(mid);
1145 free_extent_buffer(mid);
1146 mid = NULL;
1147 wret = del_ptr(trans, root, path, level + 1, pslot); 1158 wret = del_ptr(trans, root, path, level + 1, pslot);
1148 if (wret) 1159 if (wret)
1149 ret = wret; 1160 ret = wret;
1150 wret = btrfs_free_tree_block(trans, root, bytenr, blocksize, 1161 root_sub_used(root, mid->len);
1151 0, root->root_key.objectid, level); 1162 btrfs_free_tree_block(trans, root, mid, 0, 1);
1152 if (wret) 1163 free_extent_buffer(mid);
1153 ret = wret; 1164 mid = NULL;
1154 } else { 1165 } else {
1155 /* update the parent key to reflect our changes */ 1166 /* update the parent key to reflect our changes */
1156 struct btrfs_disk_key mid_key; 1167 struct btrfs_disk_key mid_key;
@@ -1740,7 +1751,6 @@ again:
1740 p->nodes[level + 1], 1751 p->nodes[level + 1],
1741 p->slots[level + 1], &b); 1752 p->slots[level + 1], &b);
1742 if (err) { 1753 if (err) {
1743 free_extent_buffer(b);
1744 ret = err; 1754 ret = err;
1745 goto done; 1755 goto done;
1746 } 1756 }
@@ -2076,6 +2086,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
2076 if (IS_ERR(c)) 2086 if (IS_ERR(c))
2077 return PTR_ERR(c); 2087 return PTR_ERR(c);
2078 2088
2089 root_add_used(root, root->nodesize);
2090
2079 memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header)); 2091 memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header));
2080 btrfs_set_header_nritems(c, 1); 2092 btrfs_set_header_nritems(c, 1);
2081 btrfs_set_header_level(c, level); 2093 btrfs_set_header_level(c, level);
@@ -2134,6 +2146,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
2134 int nritems; 2146 int nritems;
2135 2147
2136 BUG_ON(!path->nodes[level]); 2148 BUG_ON(!path->nodes[level]);
2149 btrfs_assert_tree_locked(path->nodes[level]);
2137 lower = path->nodes[level]; 2150 lower = path->nodes[level];
2138 nritems = btrfs_header_nritems(lower); 2151 nritems = btrfs_header_nritems(lower);
2139 BUG_ON(slot > nritems); 2152 BUG_ON(slot > nritems);
@@ -2202,6 +2215,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
2202 if (IS_ERR(split)) 2215 if (IS_ERR(split))
2203 return PTR_ERR(split); 2216 return PTR_ERR(split);
2204 2217
2218 root_add_used(root, root->nodesize);
2219
2205 memset_extent_buffer(split, 0, 0, sizeof(struct btrfs_header)); 2220 memset_extent_buffer(split, 0, 0, sizeof(struct btrfs_header));
2206 btrfs_set_header_level(split, btrfs_header_level(c)); 2221 btrfs_set_header_level(split, btrfs_header_level(c));
2207 btrfs_set_header_bytenr(split, split->start); 2222 btrfs_set_header_bytenr(split, split->start);
@@ -2415,6 +2430,9 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
2415 2430
2416 if (left_nritems) 2431 if (left_nritems)
2417 btrfs_mark_buffer_dirty(left); 2432 btrfs_mark_buffer_dirty(left);
2433 else
2434 clean_tree_block(trans, root, left);
2435
2418 btrfs_mark_buffer_dirty(right); 2436 btrfs_mark_buffer_dirty(right);
2419 2437
2420 btrfs_item_key(right, &disk_key, 0); 2438 btrfs_item_key(right, &disk_key, 0);
@@ -2660,6 +2678,8 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
2660 btrfs_mark_buffer_dirty(left); 2678 btrfs_mark_buffer_dirty(left);
2661 if (right_nritems) 2679 if (right_nritems)
2662 btrfs_mark_buffer_dirty(right); 2680 btrfs_mark_buffer_dirty(right);
2681 else
2682 clean_tree_block(trans, root, right);
2663 2683
2664 btrfs_item_key(right, &disk_key, 0); 2684 btrfs_item_key(right, &disk_key, 0);
2665 wret = fixup_low_keys(trans, root, path, &disk_key, 1); 2685 wret = fixup_low_keys(trans, root, path, &disk_key, 1);
@@ -2669,8 +2689,6 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
2669 /* then fixup the leaf pointer in the path */ 2689 /* then fixup the leaf pointer in the path */
2670 if (path->slots[0] < push_items) { 2690 if (path->slots[0] < push_items) {
2671 path->slots[0] += old_left_nritems; 2691 path->slots[0] += old_left_nritems;
2672 if (btrfs_header_nritems(path->nodes[0]) == 0)
2673 clean_tree_block(trans, root, path->nodes[0]);
2674 btrfs_tree_unlock(path->nodes[0]); 2692 btrfs_tree_unlock(path->nodes[0]);
2675 free_extent_buffer(path->nodes[0]); 2693 free_extent_buffer(path->nodes[0]);
2676 path->nodes[0] = left; 2694 path->nodes[0] = left;
@@ -2932,10 +2950,10 @@ again:
2932 right = btrfs_alloc_free_block(trans, root, root->leafsize, 0, 2950 right = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
2933 root->root_key.objectid, 2951 root->root_key.objectid,
2934 &disk_key, 0, l->start, 0); 2952 &disk_key, 0, l->start, 0);
2935 if (IS_ERR(right)) { 2953 if (IS_ERR(right))
2936 BUG_ON(1);
2937 return PTR_ERR(right); 2954 return PTR_ERR(right);
2938 } 2955
2956 root_add_used(root, root->leafsize);
2939 2957
2940 memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); 2958 memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header));
2941 btrfs_set_header_bytenr(right, right->start); 2959 btrfs_set_header_bytenr(right, right->start);
@@ -3054,7 +3072,8 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
3054 3072
3055 btrfs_set_path_blocking(path); 3073 btrfs_set_path_blocking(path);
3056 ret = split_leaf(trans, root, &key, path, ins_len, 1); 3074 ret = split_leaf(trans, root, &key, path, ins_len, 1);
3057 BUG_ON(ret); 3075 if (ret)
3076 goto err;
3058 3077
3059 path->keep_locks = 0; 3078 path->keep_locks = 0;
3060 btrfs_unlock_up_safe(path, 1); 3079 btrfs_unlock_up_safe(path, 1);
@@ -3796,9 +3815,10 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
3796 */ 3815 */
3797 btrfs_unlock_up_safe(path, 0); 3816 btrfs_unlock_up_safe(path, 0);
3798 3817
3799 ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len, 3818 root_sub_used(root, leaf->len);
3800 0, root->root_key.objectid, 0); 3819
3801 return ret; 3820 btrfs_free_tree_block(trans, root, leaf, 0, 1);
3821 return 0;
3802} 3822}
3803/* 3823/*
3804 * delete the item at the leaf level in path. If that empties 3824 * delete the item at the leaf level in path. If that empties
@@ -3865,6 +3885,8 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
3865 if (leaf == root->node) { 3885 if (leaf == root->node) {
3866 btrfs_set_header_level(leaf, 0); 3886 btrfs_set_header_level(leaf, 0);
3867 } else { 3887 } else {
3888 btrfs_set_path_blocking(path);
3889 clean_tree_block(trans, root, leaf);
3868 ret = btrfs_del_leaf(trans, root, path, leaf); 3890 ret = btrfs_del_leaf(trans, root, path, leaf);
3869 BUG_ON(ret); 3891 BUG_ON(ret);
3870 } 3892 }