On 2021/2/16 下午10:45, Filipe Manana wrote:
On Wed, Jun 24, 2020 at 10:00 PM Qu Wenruo <w...@suse.com> 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 <farsee...@gmail.com>
Signed-off-by: Qu Wenruo <w...@suse.com>

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?

Nope.

Just tested with btrfs-progs v5.10.1, it passes:
 $ which btrfs
 /usr/bin/btrfs
 $ btrfs --version
 btrfs-progs v5.10.1
 $ sudo ./check btrfs/136
 FSTYP         -- btrfs
 PLATFORM      -- Linux/x86_64 btrfs-desktop-vm 5.11.0-rc4-custom+ #4
SMP PREEMPT Mon Jan 25 18:35:22 CST 2021
 MKFS_OPTIONS  -- /dev/mapper/test-scratch1
 MOUNT_OPTIONS -- /dev/mapper/test-scratch1 /mnt/scratch

 btrfs/136 6s ...  10s
 Ran: btrfs/136
 Passed all 1 tests

Would you mind to provide the 136.full to help debugging the failure?

Thanks,
Qu

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



Reply via email to