On Mon, May 20, 2019 at 09:55:42AM +0100, fdmanana@xxxxxxxxxx wrote:
> From: Filipe Manana <fdmanana@xxxxxxxx>
>
> When using the no-holes feature, if we have a file with prealloc extents
> with a start offset beyond the file's eof, doing an incremental send can
> cause corruption of the file due to incorrect hole detection. Such case
> requires that the prealloc extent(s) exist in both the parent and send
> snapshots, and that a hole is punched into the file that covers all its
> extents that do not cross the eof boundary.
>
> Example reproducer:
>
> $ mkfs.btrfs -f -O no-holes /dev/sdb
> $ mount /dev/sdb /mnt/sdb
>
> $ xfs_io -f -c "pwrite -S 0xab 0 500K" /mnt/sdb/foobar
> $ xfs_io -c "falloc -k 1200K 800K" /mnt/sdb/foobar
>
> $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/base
>
> $ btrfs send -f /tmp/base.snap /mnt/sdb/base
>
> $ xfs_io -c "fpunch 0 500K" /mnt/sdb/foobar
>
> $ btrfs subvolume snapshot -r /mnt/sdb /mnt/sdb/incr
>
> $ btrfs send -p /mnt/sdb/base -f /tmp/incr.snap /mnt/sdb/incr
>
> $ md5sum /mnt/sdb/incr/foobar
> 816df6f64deba63b029ca19d880ee10a /mnt/sdb/incr/foobar
>
> $ mkfs.btrfs -f /dev/sdc
> $ mount /dev/sdc /mnt/sdc
>
> $ btrfs receive -f /tmp/base.snap /mnt/sdc
> $ btrfs receive -f /tmp/incr.snap /mnt/sdc
>
> $ md5sum /mnt/sdc/incr/foobar
> cf2ef71f4a9e90c2f6013ba3b2257ed2 /mnt/sdc/incr/foobar
>
> --> Different checksum, because the prealloc extent beyond the
> file's eof confused the hole detection code and it assumed
> a hole starting at offset 0 and ending at the offset of the
> prealloc extent (1200Kb) instead of ending at the offset
> 500Kb (the file's size).
>
> Fix this by ensuring we never cross the file's size when issuing the
> write operations for a hole.
>
> Fixes: 16e7549f045d33 ("Btrfs: incompatible format change to remove hole extents")
> CC: stable@xxxxxxxxxxxxxxx # 3.14+
> Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx>
Queued for 5.2-rc, thanks.