bug-cpio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 6/8] attempt copy_file_range if explicitly requested


From: David Disseldorp
Subject: [PATCH v2 6/8] attempt copy_file_range if explicitly requested
Date: Wed, 14 Apr 2021 01:19:11 +0200

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 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]