Btrfs: fix possible corruption when fsyncing written prealloced extents
While working on my fsync patch my fsync tester kept hitting mismatching md5sums when I would randomly write to a prealloc'ed region, syncfs() and then write to the prealloced region some more and then fsync() and then immediately reboot. This is because the tree logging code will skip writing csums for file extents who's generation is less than the current running transaction. When we mark extents as written we haven't been updating their generation so they were always being skipped. This wouldn't happen if you were to preallocate and then write in the same transaction, but if you for example prealloced a VM you could definitely run into this problem. This patch makes my fsync tester happy again. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
This commit is contained in:
parent
54338b5cc4
commit
224ecce517
1 changed files with 12 additions and 0 deletions
|
@ -935,12 +935,16 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
|
|||
btrfs_set_item_key_safe(trans, root, path, &new_key);
|
||||
fi = btrfs_item_ptr(leaf, path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_generation(leaf, fi,
|
||||
trans->transid);
|
||||
btrfs_set_file_extent_num_bytes(leaf, fi,
|
||||
extent_end - end);
|
||||
btrfs_set_file_extent_offset(leaf, fi,
|
||||
end - orig_offset);
|
||||
fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_generation(leaf, fi,
|
||||
trans->transid);
|
||||
btrfs_set_file_extent_num_bytes(leaf, fi,
|
||||
end - other_start);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
|
@ -958,12 +962,16 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
|
|||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_num_bytes(leaf, fi,
|
||||
start - key.offset);
|
||||
btrfs_set_file_extent_generation(leaf, fi,
|
||||
trans->transid);
|
||||
path->slots[0]++;
|
||||
new_key.offset = start;
|
||||
btrfs_set_item_key_safe(trans, root, path, &new_key);
|
||||
|
||||
fi = btrfs_item_ptr(leaf, path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_generation(leaf, fi,
|
||||
trans->transid);
|
||||
btrfs_set_file_extent_num_bytes(leaf, fi,
|
||||
other_end - start);
|
||||
btrfs_set_file_extent_offset(leaf, fi,
|
||||
|
@ -991,12 +999,14 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
|
|||
leaf = path->nodes[0];
|
||||
fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_generation(leaf, fi, trans->transid);
|
||||
btrfs_set_file_extent_num_bytes(leaf, fi,
|
||||
split - key.offset);
|
||||
|
||||
fi = btrfs_item_ptr(leaf, path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
|
||||
btrfs_set_file_extent_generation(leaf, fi, trans->transid);
|
||||
btrfs_set_file_extent_offset(leaf, fi, split - orig_offset);
|
||||
btrfs_set_file_extent_num_bytes(leaf, fi,
|
||||
extent_end - split);
|
||||
|
@ -1056,12 +1066,14 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
|
|||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_type(leaf, fi,
|
||||
BTRFS_FILE_EXTENT_REG);
|
||||
btrfs_set_file_extent_generation(leaf, fi, trans->transid);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
} else {
|
||||
fi = btrfs_item_ptr(leaf, del_slot - 1,
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_type(leaf, fi,
|
||||
BTRFS_FILE_EXTENT_REG);
|
||||
btrfs_set_file_extent_generation(leaf, fi, trans->transid);
|
||||
btrfs_set_file_extent_num_bytes(leaf, fi,
|
||||
extent_end - key.offset);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
|
|
Loading…
Reference in a new issue