diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-10-19 03:22:03 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-10-23 09:09:11 -0400 |
commit | 57911b8ba814fae01306376a0d02bc7cdc88dc94 (patch) | |
tree | 785127860e4b9bae2543ecf940cbec80d5de997d /fs/btrfs/ctree.c | |
parent | f46dbe3dee853f8a860f889cb2b7ff4c624f2a7a (diff) |
Btrfs: don't put removals from push_node_left into tree mod log twice
Independant of the check (push_items < src_items) tree_mod_log_eb_copy did
log the removal of the old data entries from the source buffer. Therefore,
we must not call tree_mod_log_eb_move if the check evaluates to true, as
that would log the removal twice, finally resulting in (rewinded) buffers
with wrong values for header_nritems.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b33436211000..44a7e25353a6 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1225,6 +1225,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
1225 | free_extent_buffer(eb); | 1225 | free_extent_buffer(eb); |
1226 | 1226 | ||
1227 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); | 1227 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); |
1228 | WARN_ON(btrfs_header_nritems(eb_rewin) > | ||
1229 | BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root)); | ||
1228 | 1230 | ||
1229 | return eb_rewin; | 1231 | return eb_rewin; |
1230 | } | 1232 | } |
@@ -1280,6 +1282,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
1280 | else | 1282 | else |
1281 | WARN_ON(btrfs_header_level(eb) != 0); | 1283 | WARN_ON(btrfs_header_level(eb) != 0); |
1282 | extent_buffer_get(eb); | 1284 | extent_buffer_get(eb); |
1285 | WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); | ||
1283 | 1286 | ||
1284 | return eb; | 1287 | return eb; |
1285 | } | 1288 | } |
@@ -2970,8 +2973,10 @@ static int push_node_left(struct btrfs_trans_handle *trans, | |||
2970 | push_items * sizeof(struct btrfs_key_ptr)); | 2973 | push_items * sizeof(struct btrfs_key_ptr)); |
2971 | 2974 | ||
2972 | if (push_items < src_nritems) { | 2975 | if (push_items < src_nritems) { |
2973 | tree_mod_log_eb_move(root->fs_info, src, 0, push_items, | 2976 | /* |
2974 | src_nritems - push_items); | 2977 | * don't call tree_mod_log_eb_move here, key removal was already |
2978 | * fully logged by tree_mod_log_eb_copy above. | ||
2979 | */ | ||
2975 | memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), | 2980 | memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), |
2976 | btrfs_node_key_ptr_offset(push_items), | 2981 | btrfs_node_key_ptr_offset(push_items), |
2977 | (src_nritems - push_items) * | 2982 | (src_nritems - push_items) * |