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 | |
parent | Fix large file copies on 32 bit platforms (diff) | |
download | grust-09d03bc245b27728c9cdd4976114506ae20208a7.tar.gz grust-09d03bc245b27728c9cdd4976114506ae20208a7.tar.bz2 grust-09d03bc245b27728c9cdd4976114506ae20208a7.tar.xz |
Store ENOSYS in a global to avoid unnecessary system calls
-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 d8739d6532..8412540934 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> { | |||
781 | #[cfg(any(target_os = "linux", target_os = "android"))] | 781 | #[cfg(any(target_os = "linux", target_os = "android"))] |
782 | pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { | 782 | pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { |
783 | use fs::{File, set_permissions}; | 783 | 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); | ||
784 | 789 | ||
785 | unsafe fn copy_file_range( | 790 | unsafe fn copy_file_range( |
786 | fd_in: libc::c_int, | 791 | fd_in: libc::c_int, |
@@ -820,16 +825,26 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { | |||
820 | } else { | 825 | } else { |
821 | (len - written) as usize | 826 | (len - written) as usize |
822 | }; | 827 | }; |
823 | let copy_result = unsafe { | 828 | let copy_result = if HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) { |
824 | // We actually don't have to adjust the offsets, | 829 | let copy_result = unsafe { |
825 | // because copy_file_range adjusts the file offset automatically | 830 | // We actually don't have to adjust the offsets, |
826 | cvt(copy_file_range(reader.as_raw_fd(), | 831 | // because copy_file_range adjusts the file offset automatically |
827 | ptr::null_mut(), | 832 | cvt(copy_file_range(reader.as_raw_fd(), |
828 | writer.as_raw_fd(), | 833 | ptr::null_mut(), |
829 | ptr::null_mut(), | 834 | writer.as_raw_fd(), |
830 | bytes_to_copy, | 835 | ptr::null_mut(), |
831 | 0) | 836 | bytes_to_copy, |
832 | ) | 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)) | ||
833 | }; | 848 | }; |
834 | match copy_result { | 849 | match copy_result { |
835 | Ok(ret) => written += ret as u64, | 850 | Ok(ret) => written += ret as u64, |