Subject: bug#79139: cp --reflink truncates sparse files on ZFS

From: Collin Funk <[email-masked]>
Date: Fri, 01 Aug 2025 20:56:15 -0700

Paul Eggert <[email-masked]> writes:

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

Good point. I agree.

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

Can't we make this condition only occur for glibc 2.41 and glibc 2.42?
The issue shouldn't occur before commit
89b53077d2a58f00e7debdfe58afabe953dac60d in glibc (2024-06-25). Before
that commit SYSCALL_CANCEL was defined as the following:

#define SYSCALL_CANCEL(...) \
  ({									     \
    long int sc_ret;							     \
    if (NO_SYSCALL_CANCEL_CHECKING)					     \
      sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); 			     \
    else								     \
      {									     \
	int sc_cancel_oldtype = LIBC_CANCEL_ASYNC ();			     \
	sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__);			     \
        LIBC_CANCEL_RESET (sc_cancel_oldtype);				     \
      }									     \
    sc_ret;								     \
  })

So returning 'long int' like the now fixed version.

Also, I assume this bug will cause problems in any syscall returning
ssize_t (e.g. read, write, send).

Collin