Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions library/std/src/io/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::cmp;
use crate::collections::VecDeque;
use crate::io::IoSlice;
use crate::mem::MaybeUninit;
use crate::sys::io::{CopyState, kernel_copy};

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -63,19 +64,17 @@ where
R: Read,
W: Write,
{
cfg_select! {
any(target_os = "linux", target_os = "android") => {
crate::sys::kernel_copy::copy_spec(reader, writer)
}
_ => {
generic_copy(reader, writer)
match kernel_copy(reader, writer)? {
CopyState::Ended(copied) => Ok(copied),
CopyState::Fallback(copied) => {
generic_copy(reader, writer).map(|additional| copied + additional)
}
}
}

/// The userspace read-write-loop implementation of `io::copy` that is used when
/// OS-specific specializations for copy offloading are not available or not applicable.
pub(crate) fn generic_copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64>
fn generic_copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64>
where
R: Read,
W: Write,
Expand Down Expand Up @@ -269,7 +268,7 @@ impl BufferedWriterSpec for Vec<u8> {
}
}

pub fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
reader: &mut R,
writer: &mut W,
) -> Result<u64> {
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cfg_select! {
pub use unix::chroot;
pub(crate) use unix::debug_assert_fd_is_open;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) use unix::CachedFileMetadata;
pub(super) use unix::CachedFileMetadata;
use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path;
}
target_os = "windows" => {
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/fs/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2166,7 +2166,7 @@ mod cfm {
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) use cfm::CachedFileMetadata;
pub(in crate::sys) use cfm::CachedFileMetadata;

#[cfg(not(target_vendor = "apple"))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ use libc::sendfile as sendfile64;
use libc::sendfile64;
use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};

use super::CopyState;
use crate::cmp::min;
use crate::fs::{File, Metadata};
use crate::io::copy::generic_copy;
use crate::io::{
BufRead, BufReader, BufWriter, Error, PipeReader, PipeWriter, Read, Result, StderrLock,
StdinLock, StdoutLock, Take, Write,
Expand All @@ -70,10 +70,10 @@ use crate::sys::weak::syscall;
#[cfg(test)]
mod tests;

pub(crate) fn copy_spec<R: Read + ?Sized, W: Write + ?Sized>(
pub fn kernel_copy<R: Read + ?Sized, W: Write + ?Sized>(
read: &mut R,
write: &mut W,
) -> Result<u64> {
) -> Result<CopyState> {
let copier = Copier { read, write };
SpecCopy::copy(copier)
}
Expand Down Expand Up @@ -176,17 +176,17 @@ struct Copier<'a, 'b, R: Read + ?Sized, W: Write + ?Sized> {
}

trait SpecCopy {
fn copy(self) -> Result<u64>;
fn copy(self) -> Result<CopyState>;
}

impl<R: Read + ?Sized, W: Write + ?Sized> SpecCopy for Copier<'_, '_, R, W> {
default fn copy(self) -> Result<u64> {
generic_copy(self.read, self.write)
default fn copy(self) -> Result<CopyState> {
Ok(CopyState::Fallback(0))
}
}

impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
fn copy(self) -> Result<u64> {
fn copy(self) -> Result<CopyState> {
let (reader, writer) = (self.read, self.write);
let r_cfg = reader.properties();
let w_cfg = writer.properties();
Expand Down Expand Up @@ -214,7 +214,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
result.update_take(reader);

match result {
CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
CopyResult::Ended(bytes_copied) => {
return Ok(CopyState::Ended(bytes_copied + written));
}
CopyResult::Error(e, _) => return Err(e),
CopyResult::Fallback(bytes) => written += bytes,
}
Expand All @@ -231,7 +233,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
result.update_take(reader);

match result {
CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
CopyResult::Ended(bytes_copied) => {
return Ok(CopyState::Ended(bytes_copied + written));
}
CopyResult::Error(e, _) => return Err(e),
CopyResult::Fallback(bytes) => written += bytes,
}
Expand All @@ -244,7 +248,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
result.update_take(reader);

match result {
CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
CopyResult::Ended(bytes_copied) => {
return Ok(CopyState::Ended(bytes_copied + written));
}
CopyResult::Error(e, _) => return Err(e),
CopyResult::Fallback(0) => { /* use the fallback below */ }
CopyResult::Fallback(_) => {
Expand All @@ -255,10 +261,7 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
}

// fallback if none of the more specialized syscalls wants to work with these file descriptors
match generic_copy(reader, writer) {
Ok(bytes) => Ok(bytes + written),
err => err,
}
Ok(CopyState::Fallback(written))
}
}

Expand Down Expand Up @@ -558,7 +561,7 @@ fn fd_to_meta<T: AsRawFd>(fd: &T) -> FdMeta {
}
}

pub(super) enum CopyResult {
enum CopyResult {
Ended(u64),
Error(Error, u64),
Fallback(u64),
Expand Down Expand Up @@ -587,7 +590,7 @@ const INVALID_FD: RawFd = -1;
/// Callers must handle fallback to a generic copy loop.
/// `Fallback` may indicate non-zero number of bytes already written
/// if one of the files' cursor +`max_len` would exceed u64::MAX (`EOVERFLOW`).
pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> CopyResult {
fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> CopyResult {
use crate::cmp;

const NOT_PROBED: u8 = 0;
Expand Down
23 changes: 23 additions & 0 deletions library/std/src/sys/io/kernel_copy/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pub enum CopyState {
#[cfg_attr(not(any(target_os = "linux", target_os = "android")), expect(dead_code))]
Ended(u64),
Fallback(u64),
}

cfg_select! {
any(target_os = "linux", target_os = "android") => {
mod linux;
pub use linux::kernel_copy;
}
_ => {
use crate::io::{Result, Read, Write};

pub fn kernel_copy<R: ?Sized, W: ?Sized>(_reader: &mut R, _writer: &mut W) -> Result<CopyState>
where
R: Read,
W: Write,
{
Ok(CopyState::Fallback(0))
}
}
}
3 changes: 3 additions & 0 deletions library/std/src/sys/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ mod is_terminal {
}
}

mod kernel_copy;

pub use io_slice::{IoSlice, IoSliceMut};
pub use is_terminal::is_terminal;
pub use kernel_copy::{CopyState, kernel_copy};

// Bare metal platforms usually have very small amounts of RAM
// (in the order of hundreds of KB)
Expand Down
2 changes: 0 additions & 2 deletions library/std/src/sys/pal/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ pub mod weak;
#[cfg(target_os = "fuchsia")]
pub mod fuchsia;
pub mod futex;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod kernel_copy;
#[cfg(target_os = "linux")]
pub mod linux;
pub mod os;
Expand Down
3 changes: 0 additions & 3 deletions src/tools/tidy/src/pal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,9 @@ const EXCEPTION_PATHS: &[&str] = &[
"library/std/src/os", // Platform-specific public interfaces
// Temporary `std` exceptions
// FIXME: platform-specific code should be moved to `sys`
"library/std/src/io/copy.rs",
"library/std/src/io/stdio.rs",
"library/std/src/lib.rs", // for miniz_oxide leaking docs, which itself workaround
"library/std/src/path.rs",
"library/std/src/sys_common", // Should only contain abstractions over platforms
"library/std/src/net/test.rs", // Utility helpers for tests
"library/std/src/io/error.rs", // Repr unpacked needed for UEFI
];

Expand Down
Loading