]> git.ipfire.org Git - people/arne_f/kernel.git/commit
Btrfs: send, fix file hole not being preserved due to inline extent
authorFilipe Manana <fdmanana@suse.com>
Tue, 4 Apr 2017 19:31:00 +0000 (20:31 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 24 Mar 2018 10:00:16 +0000 (11:00 +0100)
commit7016b20cab9b6e7e6d898355ea43eb07ecae14ad
treed768fb934fd3d797cb01d4c4666f0f9051de85d6
parentfd35ded5b59bf4d0c7e154b3bd5b72c5c06591e9
Btrfs: send, fix file hole not being preserved due to inline extent

[ Upstream commit e1cbfd7bf6dabdac561c75d08357571f44040a45 ]

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 e1699d2d7bf6
("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: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/btrfs/send.c