On 2025-08-01 15:05, Collin Funk wrote:
I was hoping that file could be made a tiny stub, due to the
workarounds for Linux 4.19 being mostly unnecessary now that it is EOL.
But now we have a new problem to deal with. :)
That we do. But we can more thorougly stubify the old Linux kernel bug
workaround while we're in the neighborhood. Probably best not to remove
it entirely as RHEL 8 still uses the no-longer-supported kernel.
To do that, I installed the attached patches into Gnulib and propagated
them into coreutils.
Boldly closing the bug report. Thanks, Leah, for reporting it. That one
was quite a whopper.From 626f229915b114731cc4c9d9bda9eaa82d58180b Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 1 Aug 2025 14:46:51 -0700
Subject: [PATCH 1/2] copy-file-range: tune for more-modern kernels
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 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 | 15 +++++++++++++
lib/copy-file-range.c | 48 +++++++++++++++++++++++++----------------
m4/copy-file-range.m4 | 3 +--
modules/copy-file-range | 1 +
4 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 60b8d08d37..b33d7fd00b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2025-08-01 Paul Eggert <egg...@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 <br...@clisp.org>
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 <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,
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
--
2.48.1
From 948ba80168293e3d8a905eeffb0ab61424c4c374 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 1 Aug 2025 16:01:13 -0700
Subject: [PATCH 2/2] copy-file-range: work around glibc bug 33245
Problem reported by Leah Neukirchen <https://bugs.gnu.org/79139>.
* lib/copy-file-range.c: Include sys-limits.h.
(copy_file_range) [glibc 2.42 and earlier]:
Copy at most SYS_BUFSIZE_MAX bytes.
* m4/copy-file-range.m4 (gl_FUNC_COPY_FILE_RANGE):
Replace on glibc platforms, as well as on Linux platforms.
* modules/copy-file-range (Files): Add lib/sys-limits.h.
---
ChangeLog | 9 +++++++++
lib/copy-file-range.c | 17 ++++++++++++++++-
m4/copy-file-range.m4 | 4 ++--
modules/copy-file-range | 1 +
4 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index b33d7fd00b..e60a387611 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2025-08-01 Paul Eggert <egg...@cs.ucla.edu>
+ copy-file-range: work around glibc bug 33245
+ Problem reported by Leah Neukirchen <https://bugs.gnu.org/79139>.
+ * lib/copy-file-range.c: Include sys-limits.h.
+ (copy_file_range) [glibc 2.42 and earlier]:
+ Copy at most SYS_BUFSIZE_MAX bytes.
+ * m4/copy-file-range.m4 (gl_FUNC_COPY_FILE_RANGE):
+ Replace on glibc platforms, as well as on Linux platforms.
+ * modules/copy-file-range (Files): Add lib/sys-limits.h.
+
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>
diff --git a/lib/copy-file-range.c b/lib/copy-file-range.c
index 73e02db1c1..5c12f6f715 100644
--- a/lib/copy-file-range.c
+++ b/lib/copy-file-range.c
@@ -30,6 +30,8 @@
# endif
#endif
+#include "sys-limits.h"
+
ssize_t
copy_file_range (int infd, off_t *pinoff,
int outfd, off_t *poutoff,
@@ -68,7 +70,20 @@ copy_file_range (int infd, off_t *pinoff,
# endif
if (ok)
- return copy_file_range (infd, pinoff, outfd, poutoff, length, flags);
+ {
+# if defined __GLIBC__ && ! (2 < __GLIBC__ + (43 <= __GLIBC_MINOR__))
+ /* Work around glibc bug 33245
+ <https://sourceware.org/bugzilla/show_bug.cgi?id=33245>.
+ This bug is present in glibc 2.42 (2025) and fixed in 2.43,
+ so this workaround, and the configure-time check for glibc,
+ can be removed once glibc 2.42 and earlier is no longer a
+ consideration. Perhaps in 2040. */
+ if (SYS_BUFSIZE_MAX < length)
+ length = SYS_BUFSIZE_MAX;
+# endif
+
+ 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 ec17fc68c7..85cfef71f4 100644
--- a/m4/copy-file-range.m4
+++ b/m4/copy-file-range.m4
@@ -51,8 +51,8 @@ AC_DEFUN([gl_FUNC_COPY_FILE_RANGE],
[Define to 1 if the function copy_file_range exists.])
case $host_os in
- linux*)
- # See copy-file-range.c comment re Linux kernel bugs.
+ *-gnu* | gnu* | linux*)
+ # See copy-file-range.c comment re glibc and Linux kernel bugs.
REPLACE_COPY_FILE_RANGE=1;;
esac
fi
diff --git a/modules/copy-file-range b/modules/copy-file-range
index 573558a945..e3512eaffa 100644
--- a/modules/copy-file-range
+++ b/modules/copy-file-range
@@ -3,6 +3,7 @@ Copy parts of files
Files:
lib/copy-file-range.c
+lib/sys-limits.h
m4/copy-file-range.m4
Depends-on:
--
2.48.1