diff options
| author | Alex Saveau <saveau.alexandre@gmail.com> | 2024-12-21 15:10:29 -0800 |
|---|---|---|
| committer | Alex Saveau <saveau.alexandre@gmail.com> | 2024-12-21 15:22:28 -0800 |
| commit | e0a1549e44036a75feb2fad4ffbd98ad398eac3b (patch) | |
| tree | 945df136ffcbcf6263a1e0ba0014321ba302f9bb /library/std/src/sys/pal | |
| parent | 73b41fbcfacb8fcc5a8be3ffa849abcd543069b6 (diff) | |
| download | rust-e0a1549e44036a75feb2fad4ffbd98ad398eac3b.tar.gz rust-e0a1549e44036a75feb2fad4ffbd98ad398eac3b.zip | |
Eliminate redundant statx syscalls
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
Diffstat (limited to 'library/std/src/sys/pal')
| -rw-r--r-- | library/std/src/sys/pal/unix/fs.rs | 15 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/kernel_copy.rs | 58 |
2 files changed, 64 insertions, 9 deletions
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 3fb0ed064cb..c18f4d56679 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1944,7 +1944,7 @@ fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> #[cfg(target_os = "espidf")] fn open_to_and_set_permissions( to: &Path, - _reader_metadata: crate::fs::Metadata, + _reader_metadata: &crate::fs::Metadata, ) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::fs::OpenOptions; let writer = OpenOptions::new().open(to)?; @@ -1955,7 +1955,7 @@ fn open_to_and_set_permissions( #[cfg(not(target_os = "espidf"))] fn open_to_and_set_permissions( to: &Path, - reader_metadata: crate::fs::Metadata, + reader_metadata: &crate::fs::Metadata, ) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::fs::OpenOptions; use crate::os::unix::fs::{OpenOptionsExt, PermissionsExt}; @@ -1982,10 +1982,13 @@ fn open_to_and_set_permissions( #[cfg(not(target_vendor = "apple"))] pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { - let (mut reader, reader_metadata) = open_from(from)?; - let (mut writer, _) = open_to_and_set_permissions(to, reader_metadata)?; + let (reader, reader_metadata) = open_from(from)?; + let (writer, writer_metadata) = open_to_and_set_permissions(to, &reader_metadata)?; - io::copy(&mut reader, &mut writer) + io::copy( + &mut crate::sys::kernel_copy::CachedFileMetadata(reader, reader_metadata), + &mut crate::sys::kernel_copy::CachedFileMetadata(writer, writer_metadata), + ) } #[cfg(target_vendor = "apple")] @@ -2022,7 +2025,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { } // Fall back to using `fcopyfile` if `fclonefileat` does not succeed. - let (writer, writer_metadata) = open_to_and_set_permissions(to, reader_metadata)?; + let (writer, writer_metadata) = open_to_and_set_permissions(to, &reader_metadata)?; // We ensure that `FreeOnDrop` never contains a null pointer so it is // always safe to call `copyfile_state_free` diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs index a671383cb79..bddfe829f43 100644 --- a/library/std/src/sys/pal/unix/kernel_copy.rs +++ b/library/std/src/sys/pal/unix/kernel_copy.rs @@ -52,8 +52,8 @@ use crate::cmp::min; use crate::fs::{File, Metadata}; use crate::io::copy::generic_copy; use crate::io::{ - BufRead, BufReader, BufWriter, Error, Read, Result, StderrLock, StdinLock, StdoutLock, Take, - Write, + BorrowedCursor, BufRead, BufReader, BufWriter, Error, IoSlice, IoSliceMut, Read, Result, + StderrLock, StdinLock, StdoutLock, Take, Write, }; use crate::mem::ManuallyDrop; use crate::net::TcpStream; @@ -192,7 +192,7 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> { let w_cfg = writer.properties(); // before direct operations on file descriptors ensure that all source and sink buffers are empty - let mut flush = || -> crate::io::Result<u64> { + let mut flush = || -> Result<u64> { let bytes = reader.drain_to(writer, u64::MAX)?; // BufWriter buffered bytes have already been accounted for in earlier write() calls writer.flush()?; @@ -537,6 +537,58 @@ impl<T: ?Sized + CopyWrite> CopyWrite for BufWriter<T> { } } +pub(crate) struct CachedFileMetadata(pub File, pub Metadata); + +impl Read for CachedFileMetadata { + fn read(&mut self, buf: &mut [u8]) -> Result<usize> { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> { + self.0.read_vectored(bufs) + } + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> Result<()> { + self.0.read_buf(cursor) + } + #[inline] + fn is_read_vectored(&self) -> bool { + self.0.is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { + self.0.read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> Result<usize> { + self.0.read_to_string(buf) + } +} +impl Write for CachedFileMetadata { + fn write(&mut self, buf: &[u8]) -> Result<usize> { + self.0.write(buf) + } + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> { + self.0.write_vectored(bufs) + } + #[inline] + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } + #[inline] + fn flush(&mut self) -> Result<()> { + self.0.flush() + } +} + +impl CopyRead for CachedFileMetadata { + fn properties(&self) -> CopyParams { + CopyParams(FdMeta::Metadata(self.1.clone()), Some(self.0.as_raw_fd())) + } +} + +impl CopyWrite for CachedFileMetadata { + fn properties(&self) -> CopyParams { + CopyParams(FdMeta::Metadata(self.1.clone()), Some(self.0.as_raw_fd())) + } +} + fn fd_to_meta<T: AsRawFd>(fd: &T) -> FdMeta { let fd = fd.as_raw_fd(); let file: ManuallyDrop<File> = ManuallyDrop::new(unsafe { File::from_raw_fd(fd) }); |
