Lift the probe code of `copy_file_range` into a function · model-checking/verify-rust-std@7a6ddb3

@@ -577,6 +577,23 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->

577577

) -> libc::ssize_t

578578

}

579579580+

fn probe_copy_file_range_support() -> u8 {

581+

// In some cases, we cannot determine availability from the first

582+

// `copy_file_range` call. In this case, we probe with an invalid file

583+

// descriptor so that the results are easily interpretable.

584+

match unsafe {

585+

cvt(copy_file_range(INVALID_FD, ptr::null_mut(), INVALID_FD, ptr::null_mut(), 1, 0))

586+

.map_err(|e| e.raw_os_error())

587+

} {

588+

Err(Some(EPERM | ENOSYS)) => UNAVAILABLE,

589+

Err(Some(EBADF)) => AVAILABLE,

590+

Ok(_) => panic!("unexpected copy_file_range probe success"),

591+

// Treat other errors as the syscall

592+

// being unavailable.

593+

Err(_) => UNAVAILABLE,

594+

}

595+

}

596+580597

let mut written = 0u64;

581598

while written < max_len {

582599

let bytes_to_copy = cmp::min(max_len - written, usize::MAX as u64);

@@ -614,35 +631,20 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->

614631

if written == 0 =>

615632

{

616633

if !have_probed {

617-

let available = match raw_os_error {

618-

EPERM => {

619-

// EPERM can indicate seccomp filters or an

620-

// immutable file. To distinguish these

621-

// cases we probe with invalid file

622-

// descriptors which should result in EBADF

623-

// if the syscall is supported and EPERM or

624-

// ENOSYS if it's not available.

625-

match unsafe {

626-

cvt(copy_file_range(

627-

INVALID_FD,

628-

ptr::null_mut(),

629-

INVALID_FD,

630-

ptr::null_mut(),

631-

1,

632-

0,

633-

))

634-

.map_err(|e| e.raw_os_error())

635-

} {

636-

Err(Some(EPERM | ENOSYS)) => UNAVAILABLE,

637-

Err(Some(EBADF)) => AVAILABLE,

638-

Ok(_) => panic!("unexpected copy_file_range probe success"),

639-

// Treat other errors as the syscall

640-

// being unavailable.

641-

Err(_) => UNAVAILABLE,

642-

}

643-

}

644-

ENOSYS => UNAVAILABLE,

645-

_ => AVAILABLE,

634+

let available = if matches!(raw_os_error, ENOSYS | EOPNOTSUPP | EPERM) {

635+

// EPERM can indicate seccomp filters or an

636+

// immutable file. To distinguish these

637+

// cases we probe with invalid file

638+

// descriptors which should result in EBADF

639+

// if the syscall is supported and EPERM or

640+

// ENOSYS if it's not available.

641+

//

642+

// For EOPNOTSUPP, see below. In the case of

643+

// ENOSYS, we try to cover for faulty FUSE

644+

// drivers.

645+

probe_copy_file_range_support()

646+

} else {

647+

AVAILABLE

646648

};

647649

HAS_COPY_FILE_RANGE.store(available, Ordering::Relaxed);

648650

}