Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb092569

Browse files
committed
Auto merge of#122079 - tbu-:pr_copy_file_range_probe, r=the8472
Less syscalls for the `copy_file_range` probeIf it's obvious from the actual syscall results themselves that the syscall is supported or unsupported, don't do an extra syscall with an invalid file descriptor.CC#122052
2 parents785eb65 +7d67ee5 commitb092569

File tree

1 file changed

+48
-19
lines changed

1 file changed

+48
-19
lines changed

‎library/std/src/sys/pal/unix/kernel_copy.rs‎

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,12 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
560560
// We store the availability in a global to avoid unnecessary syscalls
561561
staticHAS_COPY_FILE_RANGE:AtomicU8 =AtomicU8::new(NOT_PROBED);
562562

563+
letmut have_probed =matchHAS_COPY_FILE_RANGE.load(Ordering::Relaxed){
564+
NOT_PROBED =>false,
565+
UNAVAILABLE =>returnCopyResult::Fallback(0),
566+
_ =>true,
567+
};
568+
563569
syscall!{
564570
fn copy_file_range(
565571
fd_in: libc::c_int,
@@ -571,25 +577,22 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
571577
) -> libc::ssize_t
572578
}
573579

574-
matchHAS_COPY_FILE_RANGE.load(Ordering::Relaxed){
575-
NOT_PROBED =>{
576-
// EPERM can indicate seccomp filters or an immutable file.
577-
// To distinguish these cases we probe with invalid file descriptors which should result in EBADF if the syscall is supported
578-
// and some other error (ENOSYS or EPERM) if it's not available
579-
let result =unsafe{
580-
cvt(copy_file_range(INVALID_FD, ptr::null_mut(),INVALID_FD, ptr::null_mut(),1,0))
581-
};
582-
583-
ifmatches!(result.map_err(|e| e.raw_os_error()),Err(Some(EBADF))){
584-
HAS_COPY_FILE_RANGE.store(AVAILABLE,Ordering::Relaxed);
585-
}else{
586-
HAS_COPY_FILE_RANGE.store(UNAVAILABLE,Ordering::Relaxed);
587-
returnCopyResult::Fallback(0);
588-
}
580+
fnprobe_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+
matchunsafe{
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,
589594
}
590-
UNAVAILABLE =>returnCopyResult::Fallback(0),
591-
_ =>{}
592-
};
595+
}
593596

594597
letmut written =0u64;
595598
while written < max_len{
@@ -604,6 +607,11 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
604607
cvt(copy_file_range(reader, ptr::null_mut(), writer, ptr::null_mut(), bytes_to_copy,0))
605608
};
606609

610+
if !have_probed && copy_result.is_ok(){
611+
have_probed =true;
612+
HAS_COPY_FILE_RANGE.store(AVAILABLE,Ordering::Relaxed);
613+
}
614+
607615
match copy_result{
608616
Ok(0)if written ==0 =>{
609617
// fallback to work around several kernel bugs where copy_file_range will fail to
@@ -619,7 +627,28 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
619627
returnmatch err.raw_os_error(){
620628
// when file offset + max_length > u64::MAX
621629
Some(EOVERFLOW) =>CopyResult::Fallback(written),
622-
Some(ENOSYS |EXDEV |EINVAL |EPERM |EOPNOTSUPP |EBADF)if written ==0 =>{
630+
Some(raw_os_error @(ENOSYS |EXDEV |EINVAL |EPERM |EOPNOTSUPP |EBADF))
631+
if written ==0 =>
632+
{
633+
if !have_probed{
634+
let available =ifmatches!(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
648+
};
649+
HAS_COPY_FILE_RANGE.store(available,Ordering::Relaxed);
650+
}
651+
623652
// Try fallback io::copy if either:
624653
// - Kernel version is < 4.5 (ENOSYS¹)
625654
// - Files are mounted on different fs (EXDEV)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp