]> git.proxmox.com Git - mirror_zfs.git/commit
BRT: Fix FICLONE/FICLONERANGE shortened copy
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 6 Feb 2024 00:44:45 +0000 (16:44 -0800)
committerGitHub <noreply@github.com>
Tue, 6 Feb 2024 00:44:45 +0000 (16:44 -0800)
commit6dccdf501ea47bb8a45f00e4904d26efcb917ad4
treec3a3f8525e4202edc8c8a97759fc354e5673664c
parenta0d3fe72bf78e9035d231b00583cc5408c5cc63d
BRT: Fix FICLONE/FICLONERANGE shortened copy

On Linux the ioctl_ficlonerange() and ioctl_ficlone() system calls
are expected to either fully clone the specified range or return an
error.  The range may be for an entire file.  While internally ZFS
supports cloning partial ranges there's no way to return the length
cloned to the caller so we need to make this all or nothing.

As part of this change support for the REMAP_FILE_CAN_SHORTEN flag
has been added.  When REMAP_FILE_CAN_SHORTEN is set zfs_clone_range()
will return a shortened range when encountering pending dirty records.
When it's clear zfs_clone_range() will block and wait for the records
to be written out allowing the blocks to be cloned.

Furthermore, the file range lock is held over the region being cloned
to prevent it from being modified while cloning.  This doesn't quite
provide an atomic semantics since if an error is encountered only a
portion of the range may be cloned.  This will be converted to an
error if REMAP_FILE_CAN_SHORTEN was not provided and returned to the
caller.  However, the destination file range is left in an undefined
state.

A test case has been added which exercises this functionality by
verifying that `cp --reflink=never|auto|always` works correctly.

Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #15728
Closes #15842
13 files changed:
include/os/freebsd/zfs/sys/zfs_vfsops_os.h
include/os/linux/zfs/sys/zfs_vfsops_os.h
include/sys/zfs_vnops.h
man/man4/zfs.4
module/os/freebsd/zfs/zfs_vfsops.c
module/os/linux/zfs/zfs_vnops_os.c
module/os/linux/zfs/zpl_file_range.c
module/zfs/zfs_vnops.c
tests/runfiles/common.run
tests/test-runner/bin/zts-report.py.in
tests/zfs-tests/include/tunables.cfg
tests/zfs-tests/tests/Makefile.am
tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh [new file with mode: 0755]