]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
copy-file-range: tune for more-modern kernels
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 1 Aug 2025 21:46:51 +0000 (14:46 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 1 Aug 2025 23:54:42 +0000 (16:54 -0700)
* lib/copy-file-range.c [__linux__ && HAVE_COPY_FILE_RANGE]:
Include <linux/version.h>.  Include <sys/utsname.h>
only for kernel 5.2 and earlier.
(CHECK_LINUX_KERNEL_VERSION): New macro.
(copy_file_range) [__linux__ && HAVE_COPY_FILE_RANGE]:
Call utsname only when built for kernel 5.2 and earlier.
(copy_file_range) [!__linux__ && HAVE_COPY_FILE_RANGE]:
Use underlying copy_file_range.  This doesn’t change
behavior since the code is not compiled in this case,
but it makes the code a bit cleaner.
* modules/copy-file-range (Depends-on): Add bool.

ChangeLog
lib/copy-file-range.c
m4/copy-file-range.m4
modules/copy-file-range

index 60b8d08d37b4da85c3ac5b6d95a98a7b2864199a..b33d7fd00b426abc527ffe817a1e54eb0d15cd01 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2025-08-01  Paul Eggert  <eggert@cs.ucla.edu>
+
+       copy-file-range: tune for more-modern kernels
+       * lib/copy-file-range.c [__linux__ && HAVE_COPY_FILE_RANGE]:
+       Include <linux/version.h>.  Include <sys/utsname.h>
+       only for kernel 5.2 and earlier.
+       (CHECK_LINUX_KERNEL_VERSION): New macro.
+       (copy_file_range) [__linux__ && HAVE_COPY_FILE_RANGE]:
+       Call utsname only when built for kernel 5.2 and earlier.
+       (copy_file_range) [!__linux__ && HAVE_COPY_FILE_RANGE]:
+       Use underlying copy_file_range.  This doesn’t change
+       behavior since the code is not compiled in this case,
+       but it makes the code a bit cleaner.
+       * modules/copy-file-range (Depends-on): Add bool.
+
 2025-08-01  Bruno Haible  <bruno@clisp.org>
 
        sigsegv: Use new ioctl available in Linux >= 6.11.
index 8e0c644c08617ae27da55e03d05ee060383baf2b..73e02db1c18d552197aebcabe32bcc5ac5143103 100644 (file)
 #include <errno.h>
 
 #if defined __linux__ && HAVE_COPY_FILE_RANGE
+# include <linux/version.h>
 # include <sys/utsname.h>
+# if LINUX_VERSION_CODE < KERNEL_VERSION (5, 3, 0)
+#  define CHECK_LINUX_KERNEL_VERSION true
+# else
+#  define CHECK_LINUX_KERNEL_VERSION false
+# endif
 #endif
 
 ssize_t
@@ -31,32 +37,38 @@ copy_file_range (int infd, off_t *pinoff,
 {
 #undef copy_file_range
 
-#if defined __linux__ && HAVE_COPY_FILE_RANGE
+#if HAVE_COPY_FILE_RANGE
+  bool ok = true;
+
+# if CHECK_LINUX_KERNEL_VERSION
   /* The implementation of copy_file_range (which first appeared in
      Linux kernel release 4.5) had many issues before release 5.3
      <https://lwn.net/Articles/789527/>, so fail with ENOSYS for Linux
      kernels 5.2 and earlier.
 
-     This workaround, and the configure-time check for Linux, can be
-     removed when such kernels (released March 2016 through September
-     2019) are no longer a consideration.  As of January 2021, the
-     furthest-future planned kernel EOL is December 2024 for kernel
-     release 4.19.  */
+     This workaround can be removed when such kernels (released March
+     2016 through September 2019) are no longer a consideration.
+     Although all such kernels have reached EOL, some distros use
+     older kernels.  For example, RHEL 8 uses kernel 4.18 and has an
+     EOL of 2029.  */
 
-    static signed char ok;
+  static signed char kernel_ok;
+  if (! kernel_ok)
+    {
+      struct utsname name;
+      uname (&name);
+      char *p = name.release;
+      kernel_ok = ((p[1] != '.' || '5' < p[0]
+                    || (p[0] == '5' && (p[3] != '.' || '2' < p[2])))
+                   ? 1 : -1);
+    }
 
-    if (! ok)
-      {
-        struct utsname name;
-        uname (&name);
-        char *p = name.release;
-        ok = ((p[1] != '.' || '5' < p[0]
-               || (p[0] == '5' && (p[3] != '.' || '2' < p[2])))
-              ? 1 : -1);
-      }
+  if (kernel_ok < 0)
+    ok = false;
+# endif
 
-    if (0 < ok)
-      return copy_file_range (infd, pinoff, outfd, poutoff, length, flags);
+  if (ok)
+    return copy_file_range (infd, pinoff, outfd, poutoff, length, flags);
 #endif
 
   /* There is little need to emulate copy_file_range with read+write,
index 13081d9b11c0bec283ef8f609421009d9e81895c..ec17fc68c72b2bd781b79a9bf39c12827847913d 100644 (file)
@@ -52,8 +52,7 @@ AC_DEFUN([gl_FUNC_COPY_FILE_RANGE],
 
     case $host_os in
       linux*)
-        # See copy-file-range.c comment re pre-5.3 Linux kernel bugs.
-        # We should be able to remove this hack in 2025.
+        # See copy-file-range.c comment re Linux kernel bugs.
         REPLACE_COPY_FILE_RANGE=1;;
     esac
   fi
index 12b6fcb86eabfaf60015c60ac9e3d7265b34fb4e..573558a9456e2bb2ffabfca1d1a87ef50d1cb487 100644 (file)
@@ -6,6 +6,7 @@ lib/copy-file-range.c
 m4/copy-file-range.m4
 
 Depends-on:
+bool
 largefile
 unistd-h