Skip to content

Commit da4c604

Browse files
fdmananakdave
authored andcommitted
btrfs-progs: check: fix false alert on missing csum for hole
If we log a hole, fsync a file, partially write to the front of the hole and then fsync again the file, we end up with a file extent item in the log tree that represents a hole and has a disk address of 0 and an offset that is greater than zero (since we trimmed the front part of the range to accomodate for a file extent item of the new write). When this happens 'btrfs check' incorrectly reports that a csum is missing like this: $ btrfs check /dev/sdc Opening filesystem to check... Checking filesystem on /dev/sdc UUID: 46a85f62-4b6e-4aab-bfdc-f08d1bae9e08 [1/8] checking log ERROR: csum missing in log (root 5 inode 262 offset 5959680 address 0x5a000 length 1347584) ERROR: errors found in log [2/8] checking root items (...) And in the log tree, the corresponding file extent item: $ btrfs inspect-internal dump-tree /dev/sdc (...) item 38 key (262 EXTENT_DATA 5959680) itemoff 1796 itemsize 53 generation 11 type 1 (regular) extent data disk byte 0 nr 0 extent data offset 368640 nr 1347584 ram 1716224 extent compression 0 (none) (...) This false alert happens because we sum the file extent item's offset to its logical address before we attempt to skip holes at check_range_csummed(), so we end up passing a non-zero logical address to that function (0 + 368640), which will attempt to find a csum for that invalid address and fail. This type of error can be sporadically triggered by several test cases from fstests such as btrfs/192 for example. Fix this by skipping csum search if the file extent item's logical disk address is 0 before summing the offset. Fixes: 88dc309 ("btrfs-progs: check: explicit holes in log tree don't get csummed") Reviewed-by: Boris Burkov <[email protected]> Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent eeab081 commit da4c604

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

check/main.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9694,10 +9694,6 @@ static int check_range_csummed(struct btrfs_root *root, u64 addr, u64 length)
96949694
u64 data_len;
96959695
int ret;
96969696

9697-
/* Explicit holes don't get csummed */
9698-
if (addr == 0)
9699-
return 0;
9700-
97019697
ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
97029698
if (ret < 0)
97039699
return ret;
@@ -9807,12 +9803,15 @@ static int check_log_root(struct btrfs_root *root, struct cache_tree *root_cache
98079803
if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG)
98089804
goto next;
98099805

9806+
addr = btrfs_file_extent_disk_bytenr(leaf, fi);
9807+
/* An explicit hole, skip as holes don't have csums. */
9808+
if (addr == 0)
9809+
goto next;
9810+
98109811
if (btrfs_file_extent_compression(leaf, fi)) {
9811-
addr = btrfs_file_extent_disk_bytenr(leaf, fi);
98129812
length = btrfs_file_extent_disk_num_bytes(leaf, fi);
98139813
} else {
9814-
addr = btrfs_file_extent_disk_bytenr(leaf, fi) +
9815-
btrfs_file_extent_offset(leaf, fi);
9814+
addr += btrfs_file_extent_offset(leaf, fi);
98169815
length = btrfs_file_extent_num_bytes(leaf, fi);
98179816
}
98189817

0 commit comments

Comments
 (0)