Eliminate redundant statx syscalls
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
This commit is contained in:
parent
73b41fbcfa
commit
e0a1549e44
2 changed files with 64 additions and 9 deletions
|
@ -1944,7 +1944,7 @@ fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)>
|
||||||
#[cfg(target_os = "espidf")]
|
#[cfg(target_os = "espidf")]
|
||||||
fn open_to_and_set_permissions(
|
fn open_to_and_set_permissions(
|
||||||
to: &Path,
|
to: &Path,
|
||||||
_reader_metadata: crate::fs::Metadata,
|
_reader_metadata: &crate::fs::Metadata,
|
||||||
) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
|
) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
|
||||||
use crate::fs::OpenOptions;
|
use crate::fs::OpenOptions;
|
||||||
let writer = OpenOptions::new().open(to)?;
|
let writer = OpenOptions::new().open(to)?;
|
||||||
|
@ -1955,7 +1955,7 @@ fn open_to_and_set_permissions(
|
||||||
#[cfg(not(target_os = "espidf"))]
|
#[cfg(not(target_os = "espidf"))]
|
||||||
fn open_to_and_set_permissions(
|
fn open_to_and_set_permissions(
|
||||||
to: &Path,
|
to: &Path,
|
||||||
reader_metadata: crate::fs::Metadata,
|
reader_metadata: &crate::fs::Metadata,
|
||||||
) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
|
) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
|
||||||
use crate::fs::OpenOptions;
|
use crate::fs::OpenOptions;
|
||||||
use crate::os::unix::fs::{OpenOptionsExt, PermissionsExt};
|
use crate::os::unix::fs::{OpenOptionsExt, PermissionsExt};
|
||||||
|
@ -1982,10 +1982,13 @@ fn open_to_and_set_permissions(
|
||||||
|
|
||||||
#[cfg(not(target_vendor = "apple"))]
|
#[cfg(not(target_vendor = "apple"))]
|
||||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||||
let (mut reader, reader_metadata) = open_from(from)?;
|
let (reader, reader_metadata) = open_from(from)?;
|
||||||
let (mut writer, _) = open_to_and_set_permissions(to, reader_metadata)?;
|
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")]
|
#[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.
|
// 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
|
// We ensure that `FreeOnDrop` never contains a null pointer so it is
|
||||||
// always safe to call `copyfile_state_free`
|
// always safe to call `copyfile_state_free`
|
||||||
|
|
|
@ -52,8 +52,8 @@ use crate::cmp::min;
|
||||||
use crate::fs::{File, Metadata};
|
use crate::fs::{File, Metadata};
|
||||||
use crate::io::copy::generic_copy;
|
use crate::io::copy::generic_copy;
|
||||||
use crate::io::{
|
use crate::io::{
|
||||||
BufRead, BufReader, BufWriter, Error, Read, Result, StderrLock, StdinLock, StdoutLock, Take,
|
BorrowedCursor, BufRead, BufReader, BufWriter, Error, IoSlice, IoSliceMut, Read, Result,
|
||||||
Write,
|
StderrLock, StdinLock, StdoutLock, Take, Write,
|
||||||
};
|
};
|
||||||
use crate::mem::ManuallyDrop;
|
use crate::mem::ManuallyDrop;
|
||||||
use crate::net::TcpStream;
|
use crate::net::TcpStream;
|
||||||
|
@ -192,7 +192,7 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
|
||||||
let w_cfg = writer.properties();
|
let w_cfg = writer.properties();
|
||||||
|
|
||||||
// before direct operations on file descriptors ensure that all source and sink buffers are empty
|
// 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)?;
|
let bytes = reader.drain_to(writer, u64::MAX)?;
|
||||||
// BufWriter buffered bytes have already been accounted for in earlier write() calls
|
// BufWriter buffered bytes have already been accounted for in earlier write() calls
|
||||||
writer.flush()?;
|
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 {
|
fn fd_to_meta<T: AsRawFd>(fd: &T) -> FdMeta {
|
||||||
let fd = fd.as_raw_fd();
|
let fd = fd.as_raw_fd();
|
||||||
let file: ManuallyDrop<File> = ManuallyDrop::new(unsafe { File::from_raw_fd(fd) });
|
let file: ManuallyDrop<File> = ManuallyDrop::new(unsafe { File::from_raw_fd(fd) });
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue