diff options
| author | Nicolas Koch <nioko1337@gmail.com> | 2018-05-17 14:10:14 +0200 |
|---|---|---|
| committer | Nicolas Koch <nioko1337@gmail.com> | 2018-05-17 14:10:14 +0200 |
| commit | 09d03bc245b27728c9cdd4976114506ae20208a7 (patch) | |
| tree | ba1eda7458aaa0f40f36aba1378edd0f57c60350 /src/libstd/sys | |
| parent | a5e2942861324493c2cc5a32cb1473e656857b98 (diff) | |
| download | rust-09d03bc245b27728c9cdd4976114506ae20208a7.tar.gz rust-09d03bc245b27728c9cdd4976114506ae20208a7.zip | |
Store ENOSYS in a global to avoid unnecessary system calls
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/unix/fs.rs | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index d8739d65326..8412540934e 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -781,6 +781,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { #[cfg(any(target_os = "linux", target_os = "android"))] pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { use fs::{File, set_permissions}; + use sync::atomic::{AtomicBool, Ordering}; + + // Kernel prior to 4.5 don't have copy_file_range + // We store the availability in a global to avoid unneccessary syscalls + static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true); unsafe fn copy_file_range( fd_in: libc::c_int, @@ -820,16 +825,26 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { } else { (len - written) as usize }; - let copy_result = unsafe { - // We actually don't have to adjust the offsets, - // because copy_file_range adjusts the file offset automatically - cvt(copy_file_range(reader.as_raw_fd(), - ptr::null_mut(), - writer.as_raw_fd(), - ptr::null_mut(), - bytes_to_copy, - 0) - ) + let copy_result = if HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) { + let copy_result = unsafe { + // We actually don't have to adjust the offsets, + // because copy_file_range adjusts the file offset automatically + cvt(copy_file_range(reader.as_raw_fd(), + ptr::null_mut(), + writer.as_raw_fd(), + ptr::null_mut(), + bytes_to_copy, + 0) + ) + }; + if let Err(ref copy_err) = copy_result { + if let Some(libc::ENOSYS) = copy_err.raw_os_error() { + HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed); + } + } + copy_result + } else { + Err(io::Error::from_raw_os_error(libc::ENOSYS)) }; match copy_result { Ok(ret) => written += ret as u64, |
