File 0005-attempt-copy_file_range-if-explicitly-requested.patch of Package cpio

From 107ff5396754ad3d424b97e6fa33b0fa4c31173a Mon Sep 17 00:00:00 2001
From: David Disseldorp <ddiss@suse.de>
Date: Mon, 1 Mar 2021 01:03:41 +0100
Subject: [PATCH 5/7] attempt copy_file_range if explicitly requested

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 <ddiss@suse.de>
---
 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 c8ea278..f6d7292 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
openSUSE Build Service is sponsored by