When building in a RHEL 7 container on a RHEL 8 host, the current configure
check will detect a working SYS_copy_file_range() syscall.
Later when the resulting smbd binary is run in a RHEL 7 container on a RHEL
7 (vs 8 on the build host) host, SYS_copy_file_range() will fail with
EOPNOTSUPP.
Since the kernel support for copy_file_range() included a fallback in case
filesystems didn't implement it, the caching of copy_file_range() support can be
made a global via the static try_copy_file_range bool, there's no need to deal
with per-fileystem behaviour differences. For the curious: SYS_copy_file_range()
appeared in Linux 4.5, fallback code being vfs_copy_file_range() ->
do_splice_direct().
On current kernels the fallback function is generic_copy_file_range() (which
still calls do_splice_direct()) called from the filesystem backends directly or
from vfs_copy_file_range() -> do_copy_file_range().
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14795
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
NTSTATUS status;
bool same_file;
bool ok;
+ static bool try_copy_file_range = true;
-#ifndef USE_COPY_FILE_RANGE
- return NT_STATUS_MORE_PROCESSING_REQUIRED;
-#endif
+ if (!try_copy_file_range) {
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+ }
same_file = file_id_equal(&state->src_fsp->file_id,
&state->dst_fsp->file_id);
(intmax_t)state->remaining,
strerror(errno));
switch (errno) {
+ case EOPNOTSUPP:
+ case ENOSYS:
+ try_copy_file_range = false;
+ status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+ break;
case EXDEV:
status = NT_STATUS_MORE_PROCESSING_REQUIRED;
break;