]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
perf: Use copy_file_range to copy files if available (#1680)
authorOleg Sidorkin <osidorkin@gmail.com>
Sat, 31 Jan 2026 09:46:13 +0000 (12:46 +0300)
committerGitHub <noreply@github.com>
Sat, 31 Jan 2026 09:46:13 +0000 (10:46 +0100)
cmake/GenerateConfigurationFile.cmake
cmake/config.h.in
src/ccache/util/file.cpp

index 01522ad9c87681cfa26f738296aafb0f390ae91f..ad8cce6a40672b37167dff8eac0e837b19ab6576 100644 (file)
@@ -25,6 +25,7 @@ endforeach()
 
 include(CheckFunctionExists)
 set(functions
+    copy_file_range
     getopt_long
     getpwuid
     localtime_r
index dfd8e4e33263129f9598100f71b082c7033f93a6..87dd03224a21d39b951859f7a29413c9eb39f44f 100644 (file)
 
 // === Functions ===
 
+// Define if you have the "copy_file_range" function.
+#cmakedefine HAVE_COPY_FILE_RANGE
+
 // Define if you have the "getopt_long" function.
 #cmakedefine HAVE_GETOPT_LONG
 
index 4631eb3315e5f582661d5068a33e3bffe10b0faf..4653e2478a4911e0b9751509739ac106dc6c29c0 100644 (file)
@@ -161,17 +161,23 @@ copy_file_impl(const fs::path& src,
       FMT("Failed to copy {} to {}: {}", src, dest, strerror(errno)));
   }
   return {};
-#  elif defined(HAVE_SYS_SENDFILE_H)
+#  elif defined(HAVE_COPY_FILE_RANGE) || defined(HAVE_SYS_SENDFILE_H)
   DirEntry dir_entry(src, *src_fd);
   if (!dir_entry) {
     return tl::unexpected(FMT("Failed to stat {}: {}", src, strerror(errno)));
   }
   ssize_t bytes_left = dir_entry.size();
   while (bytes_left > 0) {
+#    if defined(HAVE_SYS_SENDFILE_H)
     ssize_t n = sendfile(*dst_fd, *src_fd, nullptr, bytes_left);
+#    elif defined(HAVE_COPY_FILE_RANGE)
+    ssize_t n =
+      copy_file_range(*src_fd, nullptr, *dst_fd, nullptr, bytes_left, 0);
+#    endif
     if (n < 0) {
       switch (errno) {
       case EINVAL:
+      case EXDEV:
       case ENOSYS:
         return copy_fd(*src_fd, *dst_fd);
       default: