A bug in file cloning/reflinking was recently found that afftected both
Btrfs and XFS, which was caused by allowing the cloning of an eof block
into the middle of a file when the eof is not aligned to the filesystem's
block size.
The fix consists of returning the errno -EINVAL to user space when the
arguments passed to the system call lead to the scenario of data
corruption. However this overlaps with some cases where the system call,
in Btrfs, returned -EOPNOTSUPP, which means we are trying to reflink
inline extents. That is unsupported in Btrfs due to the huge complexity
of supporting it (due to copying and trimming inline extents, deal with
eventual compression, etc).
We have a few btrfs test cases that verify that attempts to clone inline
extents result in a failure, and are currently expecting an -EINVAL error
message from the output of the cloner program. So create a filter that
converts error messages related to the -EOPNOTSUPP error to messages
related to the -EINVAL error, so that the test can run both on patched
and non-patched linux kernels.
The corresponding btrfs patch for the linux kernel is titled:
"Btrfs: fix data corruption due to cloning of eof block"
And the VFS change that introduces the -EINVAL error return was introduced
by the following linux kernel commit (landed in 4.20-rc1):
07d19dc9fbe9 ("vfs: avoid problematic remapping requests into partial EOF block")
The btrfs patch is not yet in Linus' tree (it was submitted around the
same time as this change) and the VFS change was introduced in 4.10-rc1.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
The test currently verifies that cloning one file with an inline extent
with a size of 10 bytes into a file with an inline extent that has a size
of 20 bytes succeeds. But this results in data loss, because the btrfs
clone operation drops the 20 bytes inline extent from the destination
inode and then copies the 10 bytes inline extent from the source file
into the destination file, resulting in data loss of the last 10 bytes
of data that the destination file had.
Fixing btrfs to correctly operate for this case (not resulting in data
loss) is actually a lot of work and brings a lot of complexity, specially
considering that any of the inline extents can be compressed. For the
moment there's a fix to make the clone operation return the errno
EOPNOTSUPP and not touch any of the inodes. This is the same approach
we do for other cases involving operation against inline extents, so
this just adds one more case that should have never been allowed.
Cloning inline extents is a rare operation and pointless, since it
involves copying them and not doing any actual deduplication or saving
space.
The btrfs patch for the linux kernel that prevents this data loss,
and fixes some file corruption cases, is titled:
"Btrfs: fix file corruption and data loss after cloning inline extents"
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
So that the same check (btrfs cloner program presence) can be reused
by other tests.
Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
Reviewed-by: David Disseldorp <ddiss@suse.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This test uses the newly added cloner binary to dispatch full file and
range specific clone (reflink) requests.
Signed-off-by: David Disseldorp <ddiss@suse.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>