From 0dc8b8b6a414a8f2dc1a40e205dc437c08e9b084 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Sun, 17 Apr 2022 15:30:35 +0800 Subject: [PATCH] btrfs-progs: check: fix wrong total bytes check for seed device [BUG] The following script can lead to false positive from btrfs check: mkfs.btrfs -f $dev1 mount $dev1 $mnt btrfstune -S1 $dev1 mount $dev1 $mnt btrfs dev add -f $dev2 $mnt umount $mnt # Now dev1 is seed, and dev2 is the rw fs. btrfs check $dev2 ... [2/7] checking extents WARNING: minor unaligned/mismatch device size detected WARNING: recommended to use 'btrfs rescue fix-device-size' to fix it ... This false positive only happens on $dev2, $dev1 is completely fine. [CAUSE] The warning is from is_super_size_valid(), in that function we verify the super block total bytes (@super_bytes) is correct against the total device bytes (@total_bytes). However the when calculating @total_bytes, we only use devices in current fs_devices, which only contains RW devices. Thus all bytes from seed device are not taken into consideration, and trigger the false positive. [FIX] Fix it by also iterating seed devices. Since we're here, also output @total_bytes and @super_bytes when outputting the warning message, to allow end users have a better idea on what's going wrong. Reviewed-by: Su Yue Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- check/main.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/check/main.c b/check/main.c index 93bef344..f0896e46 100644 --- a/check/main.c +++ b/check/main.c @@ -8599,13 +8599,17 @@ static int check_device_used(struct device_record *dev_rec, */ static bool is_super_size_valid(void) { - struct btrfs_device *dev; - struct list_head *dev_list = &gfs_info->fs_devices->devices; + struct btrfs_fs_devices *fs_devices = gfs_info->fs_devices; + const u64 super_bytes = btrfs_super_total_bytes(gfs_info->super_copy); u64 total_bytes = 0; - u64 super_bytes = btrfs_super_total_bytes(gfs_info->super_copy); - list_for_each_entry(dev, dev_list, dev_list) - total_bytes += dev->total_bytes; + while (fs_devices) { + struct btrfs_device *dev; + + list_for_each_entry(dev, &fs_devices->devices, dev_list) + total_bytes += dev->total_bytes; + fs_devices = fs_devices->seed; + } /* Important check, which can cause unmountable fs */ if (super_bytes < total_bytes) { @@ -8628,7 +8632,9 @@ static bool is_super_size_valid(void) if (!IS_ALIGNED(super_bytes, gfs_info->sectorsize) || !IS_ALIGNED(total_bytes, gfs_info->sectorsize) || super_bytes != total_bytes) { - warning("minor unaligned/mismatch device size detected"); + warning("minor unaligned/mismatch device size detected:" + "\tsuper block total bytes=%llu found total bytes=%llu", + super_bytes, total_bytes); warning( "recommended to use 'btrfs rescue fix-device-size' to fix it"); }