[PATCH] fs/btrfs: handle data extents, which crosss stripe boundaries, correctly

Andreas Schwab schwab at linux-m68k.org
Sun Feb 12 16:37:32 CET 2023


On Dez 30 2022, Qu Wenruo wrote:

> [BUG]
> Since btrfs supports single device RAID0 at mkfs time after btrfs-progs
> v5.14, if we create a single device raid0 btrfs, and created a file
> crossing stripe boundary:
>
>   # mkfs.btrfs -m dup -d raid0 test.img
>   # mount test.img mnt
>   # xfs_io -f -c "pwrite 0 128K" mnt/file
>   # umount mnt
>
> Since btrfs is using 64K as stripe length, above 128K data write is
> definitely going to cross at least one stripe boundary.
>
> Then u-boot would fail to read above 128K file:
>
>  => host bind 0 /home/adam/test.img
>  => ls host 0
>  <   >     131072  Fri Dec 30 00:18:25 2022  file
>  => load host 0 0 file
>  BTRFS: An error occurred while reading file file
>  Failed to load 'file'
>
> [CAUSE]
> Unlike tree blocks read, data extent reads doesn't consider cases in which
> one data extent can cross stripe boundary.
>
> In read_data_extent(), we just call btrfs_map_block() once and read the
> first mapped range.
>
> And if the first mapped range is smaller than the desired range, it
> would return error.
>
> But since even single device btrfs can utilize RAID0 profiles, the first
> mapped range can only be at most 64K for RAID0 profiles, and cause false
> error.
>
> [FIX]
> Just like read_whole_eb(), we should call btrfs_map_block() in a loop
> until we read all data.
>
> Since we're here, also add extra error messages for the following cases:
>
> - btrfs_map_block() failure
>   We already have the error message for it.
>
> - Missing device
>   This should not happen, as we only support single device for now.
>
> - __btrfs_devread() failure
>
> With this bug fixed, btrfs driver of u-boot can properly read the above
> 128K file, and have the correct content:
>
>  => host bind 0 /home/adam/test.img
>  => ls host 0
>  <   >     131072  Fri Dec 30 00:18:25 2022  file
>  => load host 0 0 file
>  131072 bytes read in 0 ms
>  => md5sum 0 0x20000
>  md5 for 00000000 ... 0001ffff ==> d48858312a922db7eb86377f638dbc9f
>  ^^^ Above md5sum also matches.
>
> Reported-by: Sam Winchenbach <swichenbach at tethers.com>
> Signed-off-by: Qu Wenruo <wqu at suse.com>

This breaks btrfs on the HiFive Unmatched.

=> pci enum
PCIE-0: Link up (Gen1-x8, Bus0)
=> nvme scan
=> load nvme 0:2 0x8c000000 /boot/dtb/sifive/hifive-unmatched-a00.dtb
[hangs]

-- 
Andreas Schwab, schwab at linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


More information about the U-Boot mailing list