• Filipe Manana's avatar
    Btrfs: send, fix file hole not being preserved due to inline extent · e1cbfd7b
    Filipe Manana authored
    Normally we don't have inline extents followed by regular extents, but
    there's currently at least one harmless case where this happens. For
    example, when the page size is 4Kb and compression is enabled:
    
      $ mkfs.btrfs -f /dev/sdb
      $ mount -o compress /dev/sdb /mnt
      $ xfs_io -f -c "pwrite -S 0xaa 0 4K" -c "fsync" /mnt/foobar
      $ xfs_io -c "pwrite -S 0xbb 8K 4K" -c "fsync" /mnt/foobar
    
    In this case we get a compressed inline extent, representing 4Kb of
    data, followed by a hole extent and then a regular data extent. The
    inline extent was not expanded/converted to a regular extent exactly
    because it represents 4Kb of data. This does not cause any apparent
    problem (such as the issue solved by commit e1699d2d
    ("btrfs: add missing memset while reading compressed inline extents"))
    except trigger an unexpected case in the incremental send code path
    that makes us issue an operation to write a hole when it's not needed,
    resulting in more writes at the receiver and wasting space at the
    receiver.
    
    So teach the incremental send code to deal with this particular case.
    
    The issue can be currently triggered by running fstests btrfs/137 with
    compression enabled (MOUNT_OPTIONS="-o compress" ./check btrfs/137).
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Reviewed-by: default avatarLiu Bo <bo.li.liu@oracle.com>
    e1cbfd7b
send.c 156 KB