This change sees --reflink behave similar to coreutils cp --reflink=auto. The kernel may attempt a copy-on-write clone of the range and may fallback to splice. cpio fallback to regular read/write is needed in case the source and destination reside on separate filesystems.
Signed-off-by: David Disseldorp <[email protected]> --- src/copyin.c | 2 +- src/copyout.c | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/copyin.c b/src/copyin.c index a096048..4987d7a 100644 --- a/src/copyin.c +++ b/src/copyin.c @@ -510,7 +510,7 @@ copyin_regular_file (struct cpio_file_stat* file_hdr, int in_file_des) } copy_files_tape_to_disk (in_file_des, out_file_des, file_hdr->c_filesize); disk_empty_output_buffer (out_file_des, true); - + if (to_stdout_option) { if (archive_format == arf_crcascii) diff --git a/src/copyout.c b/src/copyout.c index 5ca587f..1f0a917 100644 --- a/src/copyout.c +++ b/src/copyout.c @@ -718,9 +718,36 @@ process_copy_out () if (write_out_header (&file_hdr, out_file_des)) continue; - copy_files_disk_to_tape (in_file_des, - out_file_des, file_hdr.c_filesize, - orig_file_name); +#ifdef HAVE_CPIO_REFLINK + /* + * copy_file_range(2) should only be used if: + * - it has explicitly been requested via --reflink + * - crc calculations for aren't needed + * - output is a regular seekable file + */ + if (reflink_flag && !crc_i_flag && output_is_seekable) + { + ssize_t ret; + /* flush output buffer before copy_file_range I/O */ + tape_empty_output_buffer (out_file_des); + ret = copy_files_range (in_file_des, + out_file_des, + file_hdr.c_filesize); + /* -EXDEV: can't use copy_file_range, fallback to read/write */ + if (ret == -EXDEV || ret == -ENODATA) + copy_files_disk_to_tape (in_file_des, + out_file_des, file_hdr.c_filesize, + orig_file_name); + else if (ret < 0) + error (PAXEXIT_FAILURE, -ret, _("copy_file_range failed.")); + } + else +#endif /* HAVE_CPIO_REFLINK */ + { + copy_files_disk_to_tape (in_file_des, + out_file_des, file_hdr.c_filesize, + orig_file_name); + } warn_if_file_changed(orig_file_name, file_hdr.c_filesize, file_hdr.c_mtime); -- 2.26.2
