Skip to content

Commit

Permalink
Lift the probe code of copy_file_range into a function
Browse files Browse the repository at this point in the history
  • Loading branch information
tbu- committed Apr 27, 2024
1 parent 30c876c commit 7a6ddb3
Showing 1 changed file with 31 additions and 29 deletions.
60 changes: 31 additions & 29 deletions std/src/sys/pal/unix/kernel_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,23 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
) -> libc::ssize_t
}

fn probe_copy_file_range_support() -> u8 {
// In some cases, we cannot determine availability from the first
// `copy_file_range` call. In this case, we probe with an invalid file
// descriptor so that the results are easily interpretable.
match unsafe {
cvt(copy_file_range(INVALID_FD, ptr::null_mut(), INVALID_FD, ptr::null_mut(), 1, 0))
.map_err(|e| e.raw_os_error())
} {
Err(Some(EPERM | ENOSYS)) => UNAVAILABLE,
Err(Some(EBADF)) => AVAILABLE,
Ok(_) => panic!("unexpected copy_file_range probe success"),
// Treat other errors as the syscall
// being unavailable.
Err(_) => UNAVAILABLE,
}
}

let mut written = 0u64;
while written < max_len {
let bytes_to_copy = cmp::min(max_len - written, usize::MAX as u64);
Expand Down Expand Up @@ -614,35 +631,20 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
if written == 0 =>
{
if !have_probed {
let available = match raw_os_error {
EPERM => {
// EPERM can indicate seccomp filters or an
// immutable file. To distinguish these
// cases we probe with invalid file
// descriptors which should result in EBADF
// if the syscall is supported and EPERM or
// ENOSYS if it's not available.
match unsafe {
cvt(copy_file_range(
INVALID_FD,
ptr::null_mut(),
INVALID_FD,
ptr::null_mut(),
1,
0,
))
.map_err(|e| e.raw_os_error())
} {
Err(Some(EPERM | ENOSYS)) => UNAVAILABLE,
Err(Some(EBADF)) => AVAILABLE,
Ok(_) => panic!("unexpected copy_file_range probe success"),
// Treat other errors as the syscall
// being unavailable.
Err(_) => UNAVAILABLE,
}
}
ENOSYS => UNAVAILABLE,
_ => AVAILABLE,
let available = if matches!(raw_os_error, ENOSYS | EOPNOTSUPP | EPERM) {
// EPERM can indicate seccomp filters or an
// immutable file. To distinguish these
// cases we probe with invalid file
// descriptors which should result in EBADF
// if the syscall is supported and EPERM or
// ENOSYS if it's not available.
//
// For EOPNOTSUPP, see below. In the case of
// ENOSYS, we try to cover for faulty FUSE
// drivers.
probe_copy_file_range_support()
} else {
AVAILABLE
};
HAS_COPY_FILE_RANGE.store(available, Ordering::Relaxed);
}
Expand Down

0 comments on commit 7a6ddb3

Please sign in to comment.