diff options
author | Josef Bacik <jbacik@fusionio.com> | 2012-08-16 16:32:06 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-01 15:19:02 -0400 |
commit | 224ecce517af3a952321202cdf304c12e138caca (patch) | |
tree | 086997611ebc47bf99fddeb91b52f45a499a484d /fs/btrfs/file.c | |
parent | 54338b5cc4fa3cfe260e8e4ade8b62a9079ea3f9 (diff) |
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>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 5caf285c6e4d..b7c885c8423f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -935,12 +935,16 @@ again: | |||
935 | btrfs_set_item_key_safe(trans, root, path, &new_key); | 935 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
936 | fi = btrfs_item_ptr(leaf, path->slots[0], | 936 | fi = btrfs_item_ptr(leaf, path->slots[0], |
937 | struct btrfs_file_extent_item); | 937 | struct btrfs_file_extent_item); |
938 | btrfs_set_file_extent_generation(leaf, fi, | ||
939 | trans->transid); | ||
938 | btrfs_set_file_extent_num_bytes(leaf, fi, | 940 | btrfs_set_file_extent_num_bytes(leaf, fi, |
939 | extent_end - end); | 941 | extent_end - end); |
940 | btrfs_set_file_extent_offset(leaf, fi, | 942 | btrfs_set_file_extent_offset(leaf, fi, |
941 | end - orig_offset); | 943 | end - orig_offset); |
942 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, | 944 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, |
943 | struct btrfs_file_extent_item); | 945 | struct btrfs_file_extent_item); |
946 | btrfs_set_file_extent_generation(leaf, fi, | ||
947 | trans->transid); | ||
944 | btrfs_set_file_extent_num_bytes(leaf, fi, | 948 | btrfs_set_file_extent_num_bytes(leaf, fi, |
945 | end - other_start); | 949 | end - other_start); |
946 | btrfs_mark_buffer_dirty(leaf); | 950 | btrfs_mark_buffer_dirty(leaf); |
@@ -958,12 +962,16 @@ again: | |||
958 | struct btrfs_file_extent_item); | 962 | struct btrfs_file_extent_item); |
959 | btrfs_set_file_extent_num_bytes(leaf, fi, | 963 | btrfs_set_file_extent_num_bytes(leaf, fi, |
960 | start - key.offset); | 964 | start - key.offset); |
965 | btrfs_set_file_extent_generation(leaf, fi, | ||
966 | trans->transid); | ||
961 | path->slots[0]++; | 967 | path->slots[0]++; |
962 | new_key.offset = start; | 968 | new_key.offset = start; |
963 | btrfs_set_item_key_safe(trans, root, path, &new_key); | 969 | btrfs_set_item_key_safe(trans, root, path, &new_key); |
964 | 970 | ||
965 | fi = btrfs_item_ptr(leaf, path->slots[0], | 971 | fi = btrfs_item_ptr(leaf, path->slots[0], |
966 | struct btrfs_file_extent_item); | 972 | struct btrfs_file_extent_item); |
973 | btrfs_set_file_extent_generation(leaf, fi, | ||
974 | trans->transid); | ||
967 | btrfs_set_file_extent_num_bytes(leaf, fi, | 975 | btrfs_set_file_extent_num_bytes(leaf, fi, |
968 | other_end - start); | 976 | other_end - start); |
969 | btrfs_set_file_extent_offset(leaf, fi, | 977 | btrfs_set_file_extent_offset(leaf, fi, |
@@ -991,12 +999,14 @@ again: | |||
991 | leaf = path->nodes[0]; | 999 | leaf = path->nodes[0]; |
992 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, | 1000 | fi = btrfs_item_ptr(leaf, path->slots[0] - 1, |
993 | struct btrfs_file_extent_item); | 1001 | struct btrfs_file_extent_item); |
1002 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | ||
994 | btrfs_set_file_extent_num_bytes(leaf, fi, | 1003 | btrfs_set_file_extent_num_bytes(leaf, fi, |
995 | split - key.offset); | 1004 | split - key.offset); |
996 | 1005 | ||
997 | fi = btrfs_item_ptr(leaf, path->slots[0], | 1006 | fi = btrfs_item_ptr(leaf, path->slots[0], |
998 | struct btrfs_file_extent_item); | 1007 | struct btrfs_file_extent_item); |
999 | 1008 | ||
1009 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | ||
1000 | btrfs_set_file_extent_offset(leaf, fi, split - orig_offset); | 1010 | btrfs_set_file_extent_offset(leaf, fi, split - orig_offset); |
1001 | btrfs_set_file_extent_num_bytes(leaf, fi, | 1011 | btrfs_set_file_extent_num_bytes(leaf, fi, |
1002 | extent_end - split); | 1012 | extent_end - split); |
@@ -1056,12 +1066,14 @@ again: | |||
1056 | struct btrfs_file_extent_item); | 1066 | struct btrfs_file_extent_item); |
1057 | btrfs_set_file_extent_type(leaf, fi, | 1067 | btrfs_set_file_extent_type(leaf, fi, |
1058 | BTRFS_FILE_EXTENT_REG); | 1068 | BTRFS_FILE_EXTENT_REG); |
1069 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | ||
1059 | btrfs_mark_buffer_dirty(leaf); | 1070 | btrfs_mark_buffer_dirty(leaf); |
1060 | } else { | 1071 | } else { |
1061 | fi = btrfs_item_ptr(leaf, del_slot - 1, | 1072 | fi = btrfs_item_ptr(leaf, del_slot - 1, |
1062 | struct btrfs_file_extent_item); | 1073 | struct btrfs_file_extent_item); |
1063 | btrfs_set_file_extent_type(leaf, fi, | 1074 | btrfs_set_file_extent_type(leaf, fi, |
1064 | BTRFS_FILE_EXTENT_REG); | 1075 | BTRFS_FILE_EXTENT_REG); |
1076 | btrfs_set_file_extent_generation(leaf, fi, trans->transid); | ||
1065 | btrfs_set_file_extent_num_bytes(leaf, fi, | 1077 | btrfs_set_file_extent_num_bytes(leaf, fi, |
1066 | extent_end - key.offset); | 1078 | extent_end - key.offset); |
1067 | btrfs_mark_buffer_dirty(leaf); | 1079 | btrfs_mark_buffer_dirty(leaf); |