Skip to content

Commit 09d03bc

Browse files
committed
Store ENOSYS in a global to avoid unnecessary system calls
1 parent a5e2942 commit 09d03bc

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

src/libstd/sys/unix/fs.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
781781
#[cfg(any(target_os = "linux", target_os = "android"))]
782782
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
783783
use fs::{File, set_permissions};
784+
use sync::atomic::{AtomicBool, Ordering};
785+
786+
// Kernel prior to 4.5 don't have copy_file_range
787+
// We store the availability in a global to avoid unneccessary syscalls
788+
static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true);
784789

785790
unsafe fn copy_file_range(
786791
fd_in: libc::c_int,
@@ -820,16 +825,26 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
820825
} else {
821826
(len - written) as usize
822827
};
823-
let copy_result = unsafe {
824-
// We actually don't have to adjust the offsets,
825-
// because copy_file_range adjusts the file offset automatically
826-
cvt(copy_file_range(reader.as_raw_fd(),
827-
ptr::null_mut(),
828-
writer.as_raw_fd(),
829-
ptr::null_mut(),
830-
bytes_to_copy,
831-
0)
832-
)
828+
let copy_result = if HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) {
829+
let copy_result = unsafe {
830+
// We actually don't have to adjust the offsets,
831+
// because copy_file_range adjusts the file offset automatically
832+
cvt(copy_file_range(reader.as_raw_fd(),
833+
ptr::null_mut(),
834+
writer.as_raw_fd(),
835+
ptr::null_mut(),
836+
bytes_to_copy,
837+
0)
838+
)
839+
};
840+
if let Err(ref copy_err) = copy_result {
841+
if let Some(libc::ENOSYS) = copy_err.raw_os_error() {
842+
HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed);
843+
}
844+
}
845+
copy_result
846+
} else {
847+
Err(io::Error::from_raw_os_error(libc::ENOSYS))
833848
};
834849
match copy_result {
835850
Ok(ret) => written += ret as u64,

0 commit comments

Comments
 (0)