From: Paul Eggert Date: Fri, 1 Aug 2025 21:46:51 +0000 (-0700) Subject: copy-file-range: tune for more-modern kernels X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=626f229915b114731cc4c9d9bda9eaa82d58180b;p=thirdparty%2Fgnulib.git copy-file-range: tune for more-modern kernels * lib/copy-file-range.c [__linux__ && HAVE_COPY_FILE_RANGE]: Include . Include 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. --- diff --git a/ChangeLog b/ChangeLog index 60b8d08d37..b33d7fd00b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2025-08-01 Paul Eggert + + copy-file-range: tune for more-modern kernels + * lib/copy-file-range.c [__linux__ && HAVE_COPY_FILE_RANGE]: + Include . Include + 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 sigsegv: Use new ioctl available in Linux >= 6.11. diff --git a/lib/copy-file-range.c b/lib/copy-file-range.c index 8e0c644c08..73e02db1c1 100644 --- a/lib/copy-file-range.c +++ b/lib/copy-file-range.c @@ -21,7 +21,13 @@ #include #if defined __linux__ && HAVE_COPY_FILE_RANGE +# include # include +# 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 , 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, diff --git a/m4/copy-file-range.m4 b/m4/copy-file-range.m4 index 13081d9b11..ec17fc68c7 100644 --- a/m4/copy-file-range.m4 +++ b/m4/copy-file-range.m4 @@ -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 diff --git a/modules/copy-file-range b/modules/copy-file-range index 12b6fcb86e..573558a945 100644 --- a/modules/copy-file-range +++ b/modules/copy-file-range @@ -6,6 +6,7 @@ lib/copy-file-range.c m4/copy-file-range.m4 Depends-on: +bool largefile unistd-h