diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
| -rw-r--r-- | fs/btrfs/ctree.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index ecd25a1b4e51..ca9d8f1a3bb6 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -651,6 +651,8 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, | |||
| 651 | if (tree_mod_dont_log(fs_info, NULL)) | 651 | if (tree_mod_dont_log(fs_info, NULL)) |
| 652 | return 0; | 652 | return 0; |
| 653 | 653 | ||
| 654 | __tree_mod_log_free_eb(fs_info, old_root); | ||
| 655 | |||
| 654 | ret = tree_mod_alloc(fs_info, flags, &tm); | 656 | ret = tree_mod_alloc(fs_info, flags, &tm); |
| 655 | if (ret < 0) | 657 | if (ret < 0) |
| 656 | goto out; | 658 | goto out; |
| @@ -736,7 +738,7 @@ tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq) | |||
| 736 | static noinline void | 738 | static noinline void |
| 737 | tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, | 739 | tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, |
| 738 | struct extent_buffer *src, unsigned long dst_offset, | 740 | struct extent_buffer *src, unsigned long dst_offset, |
| 739 | unsigned long src_offset, int nr_items) | 741 | unsigned long src_offset, int nr_items, int log_removal) |
| 740 | { | 742 | { |
| 741 | int ret; | 743 | int ret; |
| 742 | int i; | 744 | int i; |
| @@ -750,10 +752,12 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, | |||
| 750 | } | 752 | } |
| 751 | 753 | ||
| 752 | for (i = 0; i < nr_items; i++) { | 754 | for (i = 0; i < nr_items; i++) { |
| 753 | ret = tree_mod_log_insert_key_locked(fs_info, src, | 755 | if (log_removal) { |
| 754 | i + src_offset, | 756 | ret = tree_mod_log_insert_key_locked(fs_info, src, |
| 755 | MOD_LOG_KEY_REMOVE); | 757 | i + src_offset, |
| 756 | BUG_ON(ret < 0); | 758 | MOD_LOG_KEY_REMOVE); |
| 759 | BUG_ON(ret < 0); | ||
| 760 | } | ||
| 757 | ret = tree_mod_log_insert_key_locked(fs_info, dst, | 761 | ret = tree_mod_log_insert_key_locked(fs_info, dst, |
| 758 | i + dst_offset, | 762 | i + dst_offset, |
| 759 | MOD_LOG_KEY_ADD); | 763 | MOD_LOG_KEY_ADD); |
| @@ -927,7 +931,6 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
| 927 | ret = btrfs_dec_ref(trans, root, buf, 1, 1); | 931 | ret = btrfs_dec_ref(trans, root, buf, 1, 1); |
| 928 | BUG_ON(ret); /* -ENOMEM */ | 932 | BUG_ON(ret); /* -ENOMEM */ |
| 929 | } | 933 | } |
| 930 | tree_mod_log_free_eb(root->fs_info, buf); | ||
| 931 | clean_tree_block(trans, root, buf); | 934 | clean_tree_block(trans, root, buf); |
| 932 | *last_ref = 1; | 935 | *last_ref = 1; |
| 933 | } | 936 | } |
| @@ -1046,6 +1049,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 1046 | btrfs_set_node_ptr_generation(parent, parent_slot, | 1049 | btrfs_set_node_ptr_generation(parent, parent_slot, |
| 1047 | trans->transid); | 1050 | trans->transid); |
| 1048 | btrfs_mark_buffer_dirty(parent); | 1051 | btrfs_mark_buffer_dirty(parent); |
| 1052 | tree_mod_log_free_eb(root->fs_info, buf); | ||
| 1049 | btrfs_free_tree_block(trans, root, buf, parent_start, | 1053 | btrfs_free_tree_block(trans, root, buf, parent_start, |
| 1050 | last_ref); | 1054 | last_ref); |
| 1051 | } | 1055 | } |
| @@ -1750,7 +1754,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1750 | goto enospc; | 1754 | goto enospc; |
| 1751 | } | 1755 | } |
| 1752 | 1756 | ||
| 1753 | tree_mod_log_free_eb(root->fs_info, root->node); | ||
| 1754 | tree_mod_log_set_root_pointer(root, child); | 1757 | tree_mod_log_set_root_pointer(root, child); |
| 1755 | rcu_assign_pointer(root->node, child); | 1758 | rcu_assign_pointer(root->node, child); |
| 1756 | 1759 | ||
| @@ -2995,7 +2998,7 @@ static int push_node_left(struct btrfs_trans_handle *trans, | |||
| 2995 | push_items = min(src_nritems - 8, push_items); | 2998 | push_items = min(src_nritems - 8, push_items); |
| 2996 | 2999 | ||
| 2997 | tree_mod_log_eb_copy(root->fs_info, dst, src, dst_nritems, 0, | 3000 | tree_mod_log_eb_copy(root->fs_info, dst, src, dst_nritems, 0, |
| 2998 | push_items); | 3001 | push_items, 1); |
| 2999 | copy_extent_buffer(dst, src, | 3002 | copy_extent_buffer(dst, src, |
| 3000 | btrfs_node_key_ptr_offset(dst_nritems), | 3003 | btrfs_node_key_ptr_offset(dst_nritems), |
| 3001 | btrfs_node_key_ptr_offset(0), | 3004 | btrfs_node_key_ptr_offset(0), |
| @@ -3066,7 +3069,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans, | |||
| 3066 | sizeof(struct btrfs_key_ptr)); | 3069 | sizeof(struct btrfs_key_ptr)); |
| 3067 | 3070 | ||
| 3068 | tree_mod_log_eb_copy(root->fs_info, dst, src, 0, | 3071 | tree_mod_log_eb_copy(root->fs_info, dst, src, 0, |
| 3069 | src_nritems - push_items, push_items); | 3072 | src_nritems - push_items, push_items, 1); |
| 3070 | copy_extent_buffer(dst, src, | 3073 | copy_extent_buffer(dst, src, |
| 3071 | btrfs_node_key_ptr_offset(0), | 3074 | btrfs_node_key_ptr_offset(0), |
| 3072 | btrfs_node_key_ptr_offset(src_nritems - push_items), | 3075 | btrfs_node_key_ptr_offset(src_nritems - push_items), |
| @@ -3218,12 +3221,18 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
| 3218 | int mid; | 3221 | int mid; |
| 3219 | int ret; | 3222 | int ret; |
| 3220 | u32 c_nritems; | 3223 | u32 c_nritems; |
| 3224 | int tree_mod_log_removal = 1; | ||
| 3221 | 3225 | ||
| 3222 | c = path->nodes[level]; | 3226 | c = path->nodes[level]; |
| 3223 | WARN_ON(btrfs_header_generation(c) != trans->transid); | 3227 | WARN_ON(btrfs_header_generation(c) != trans->transid); |
| 3224 | if (c == root->node) { | 3228 | if (c == root->node) { |
| 3225 | /* trying to split the root, lets make a new one */ | 3229 | /* trying to split the root, lets make a new one */ |
| 3226 | ret = insert_new_root(trans, root, path, level + 1); | 3230 | ret = insert_new_root(trans, root, path, level + 1); |
| 3231 | /* | ||
| 3232 | * removal of root nodes has been logged by | ||
| 3233 | * tree_mod_log_set_root_pointer due to locking | ||
| 3234 | */ | ||
| 3235 | tree_mod_log_removal = 0; | ||
| 3227 | if (ret) | 3236 | if (ret) |
| 3228 | return ret; | 3237 | return ret; |
| 3229 | } else { | 3238 | } else { |
| @@ -3261,7 +3270,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
| 3261 | (unsigned long)btrfs_header_chunk_tree_uuid(split), | 3270 | (unsigned long)btrfs_header_chunk_tree_uuid(split), |
| 3262 | BTRFS_UUID_SIZE); | 3271 | BTRFS_UUID_SIZE); |
| 3263 | 3272 | ||
| 3264 | tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid); | 3273 | tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid, |
| 3274 | tree_mod_log_removal); | ||
| 3265 | copy_extent_buffer(split, c, | 3275 | copy_extent_buffer(split, c, |
| 3266 | btrfs_node_key_ptr_offset(0), | 3276 | btrfs_node_key_ptr_offset(0), |
| 3267 | btrfs_node_key_ptr_offset(mid), | 3277 | btrfs_node_key_ptr_offset(mid), |
