Skip to content

Commit 44a46d0

Browse files
SidongYangadam900710
authored andcommitted
btrfs-progs: fix-data-checksum: fix an off-by-one error in the mirror bitmap
[BUG] With both mirrors of a DUP data block corrupted, only the first one shows up in the report: # btrfs rescue fix-data-checksum dup.img logical=84082688 corrtuped mirrors=1 affected files: (subvolume 5)/file2 While both mirrors have a checksum mismatch, so the expected output is: logical=84082688 corrtuped mirrors=1,2 affected files: (subvolume 5)/file2 [CAUSE] The error mirror bitmap uses bit 0 for mirror 1, as documented in struct corrupted_block, and add_corrupted_block() does that conversion when it allocates a new entry: set_bit(mirror - 1, last->error_mirror_bitmap); But when an entry for the same logical bytenr already exists, the mirror number is used as the bit number directly: set_bit(mirror, last->error_mirror_bitmap); The first corrupted mirror of a block always goes through the allocation path, so only the second and any following one are affected, and their bit ends up one position too high. For the last mirror this means bit @num_mirrors gets set, which is beyond the range report_corrupted_blocks() walks, so the mirror is dropped from the report. For the other mirrors the number reported is one larger than the corrupted one, e.g. on a RAID1C3 block with mirrors 1 and 2 corrupted the report claims mirrors 1 and 3, marking the only intact mirror as bad. This is more than a cosmetic problem, as the report is what the user bases the mirror choice on in the interactive mode. Picking a mirror that is reported as intact but is in fact corrupted updates the checksum item to match the corrupted data, making the corruption permanent. [FIX] Convert the mirror number to a bit number the same way the allocation path does. Fixes: 0e999c9 ("btrfs-progs: introduce "btrfs rescue fix-data-checksum"") Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
1 parent 3dbed58 commit 44a46d0

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

cmds/rescue-fix-data-checksum.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static int add_corrupted_block(struct btrfs_fs_info *fs_info, u64 logical,
8585
/* The last entry is the same, just set update the error mirror bitmap. */
8686
if (last->logical == logical) {
8787
UASSERT(last->error_mirror_bitmap);
88-
set_bit(mirror, last->error_mirror_bitmap);
88+
set_bit(mirror - 1, last->error_mirror_bitmap);
8989
return 0;
9090
}
9191
add:

0 commit comments

Comments
 (0)