On Wed, Jun 24, 2020 at 10:00 PM Qu Wenruo <[email protected]> wrote:
>
> [BUG]
> The following script could lead to corrupted btrfs fs after
> btrfs-convert:
>
> fallocate -l 1G test.img
> mkfs.ext4 test.img
> mount test.img $mnt
> fallocate -l 200m $mnt/file1
> fallocate -l 200m $mnt/file2
> fallocate -l 200m $mnt/file3
> fallocate -l 200m $mnt/file4
> fallocate -l 205m $mnt/file1
> fallocate -l 205m $mnt/file2
> fallocate -l 205m $mnt/file3
> fallocate -l 205m $mnt/file4
> umount $mnt
> btrfs-convert test.img
>
> The result btrfs will have a device extent beyond its boundary:
> pening filesystem to check...
> Checking filesystem on test.img
> UUID: bbcd7399-fd5b-41a7-81ae-d48bc6935e43
> [1/7] checking root items
> [2/7] checking extents
> ERROR: dev extent devid 1 physical offset 993198080 len 85786624 is beyond
> device boundary 1073741824
> ERROR: errors found in extent allocation tree or chunk allocation
> [3/7] checking free space cache
> [4/7] checking fs roots
> [5/7] checking only csums items (without verifying data)
> [6/7] checking root refs
> [7/7] checking quota groups skipped (not enabled on this FS)
> found 913960960 bytes used, error(s) found
> total csum bytes: 891500
> total tree bytes: 1064960
> total fs tree bytes: 49152
> total extent tree bytes: 16384
> btree space waste bytes: 144885
> file data blocks allocated: 2129063936
> referenced 1772728320
>
> [CAUSE]
> Btrfs-convert first collect all used blocks in the original fs, then
> slightly enlarge the used blocks range as new btrfs data chunks.
>
> However the enlarge part has a problem, that it doesn't take the device
> boundary into consideration.
>
> Thus it caused device extents and data chunks to go beyond device
> boundary.
>
> [FIX]
> Just to extra check before inserting data chunks into
> btrfs_convert_context::data_chunk.
>
> Reported-by: Jiachen YANG <[email protected]>
> Signed-off-by: Qu Wenruo <[email protected]>
So, having upgraded a test box from btrfs-progs v5.6.1 to v5.10.1, I
now have btrfs/136 (fstests) failing:
$ ./check btrfs/136
FSTYP -- btrfs
PLATFORM -- Linux/x86_64 debian8 5.11.0-rc7-btrfs-next-81 #1 SMP
PREEMPT Tue Feb 16 12:29:07 WET 2021
MKFS_OPTIONS -- /dev/sdc
MOUNT_OPTIONS -- /dev/sdc /home/fdmanana/btrfs-tests/scratch_1
btrfs/136 7s ... [failed, exit status 1]- output mismatch (see
/home/fdmanana/git/hub/xfstests/results//btrfs/136.out.bad)
--- tests/btrfs/136.out 2020-06-10 19:29:03.818519162 +0100
+++ /home/fdmanana/git/hub/xfstests/results//btrfs/136.out.bad
2021-02-16 14:31:30.669559188 +0000
@@ -1,2 +1,3 @@
QA output created by 136
-Silence is golden
+btrfs-convert failed
+(see /home/fdmanana/git/hub/xfstests/results//btrfs/136.full for details)
...
(Run 'diff -u /home/fdmanana/git/hub/xfstests/tests/btrfs/136.out
/home/fdmanana/git/hub/xfstests/results//btrfs/136.out.bad' to see
the entire diff)
Ran: btrfs/136
Failures: btrfs/136
Failed 1 of 1 tests
A bisect pointed to this patch.
Did you get this failure on your test box as well?
Thanks.
> ---
> convert/main.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/convert/main.c b/convert/main.c
> index c86ddd988c63..7709e9a6c085 100644
> --- a/convert/main.c
> +++ b/convert/main.c
> @@ -669,6 +669,8 @@ static int calculate_available_space(struct
> btrfs_convert_context *cctx)
> cur_off = cache->start;
> cur_len = max(cache->start + cache->size - cur_off,
> min_stripe_size);
> + /* data chunks should never exceed device boundary */
> + cur_len = min(cctx->total_bytes - cur_off, cur_len);
> ret = add_merge_cache_extent(data_chunks, cur_off, cur_len);
> if (ret < 0)
> goto out;
> --
> 2.27.0
>
--
Filipe David Manana,
“Whether you think you can, or you think you can't — you're right.”