Skip to content
  • Filipe Manana's avatar
    Btrfs: incremental send, fix file corruption when no-holes feature is enabled · 6b1f72e5
    Filipe Manana authored
    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: 16e7549f
    
     ("Btrfs: incompatible format change to remove hole extents")
    CC: stable@vger.kernel.org # 3.14+
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    6b1f72e5