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
14 changes: 5 additions & 9 deletions src/uu/cat/src/cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ use uucore::error::{UResult, strip_errno};
use uucore::translate;
use uucore::{fast_inc::fast_inc_one, format_usage};

/// Linux splice support
#[cfg(any(target_os = "linux", target_os = "android"))]
mod splice;

// Allocate 32 digits for the line number.
// An estimate is that we can print about 1e8 lines/seconds, so 32 digits
// would be enough for billions of universe lifetimes.
Expand Down Expand Up @@ -483,14 +479,14 @@ fn print_fast<R: FdReadable>(handle: &mut InputHandle<R>) -> CatResult<()> {
let stdout = io::stdout();
#[cfg(any(target_os = "linux", target_os = "android"))]
let mut stdout = stdout;
// Try to use the splice() system call for faster writing. If it works, we're done.
#[cfg(any(target_os = "linux", target_os = "android"))]
if !uucore::pipes::splice_unbounded_auto(&handle.reader, &mut stdout)?
&& !uucore::pipes::might_fuse(&handle.reader)
{
// If we're on Linux or Android, try to use the splice() system call
// for faster writing. If it works, we're done.
if !splice::write_fast_using_splice(handle, &mut stdout)? {
return Ok(());
}
return Ok(());
}

// If we're not on Linux or Android, or the splice() call failed,
// fall back on slower writing.
print_unbuffered(handle, stdout)
Expand Down
29 changes: 0 additions & 29 deletions src/uu/cat/src/splice.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/uu/tail/src/tail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ fn print_target_section<
} else {
// zero-copy fast-path
#[cfg(any(target_os = "linux", target_os = "android"))]
if uucore::pipes::splice_unbounded_broker(file, &mut stdout)? {
if uucore::pipes::splice_unbounded_auto(file, &mut stdout)? {
io::copy(file, &mut stdout)?;
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
Expand Down
23 changes: 8 additions & 15 deletions src/uucore/src/lib/features/buf_copy/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,14 @@ where
R: Read + AsFd + AsRawFd,
S: Write + AsFd + AsRawFd,
{
// If we're on Linux or Android, try to use the splice() system call
// for faster writing. If it works, we're done.
// todo: bypass broker pipe this if input or output is pipe. We use this mostly for stream.
if !crate::pipes::splice_unbounded_broker(src, dest)? {
return Ok(());
// try to use the splice() system call
// for faster writing. If it works, we're done
if crate::pipes::splice_unbounded_auto(&src, dest)? {
Comment thread
oech3 marked this conversation as resolved.
std::io::copy(src, dest)?;
// todo: Do not mix writing by raw syscall and std's buffered write,
// or order of output would be wrong when this was called multiple times
// and splice_unbounded_auto sent content partially. flush works as an workaround.
dest.flush()?;
Comment thread
oech3 marked this conversation as resolved.
}

// If the splice() call failed, fall back on slower writing.
std::io::copy(src, dest)?;

// If the splice() call failed and there has been some data written to
// stdout via while loop above AND there will be second splice() call
// that will succeed, data pushed through splice will be output before
// the data buffered in stdout.lock. Therefore additional explicit flush
// is required here.
dest.flush()?;
Ok(())
}
16 changes: 16 additions & 0 deletions src/uucore/src/lib/features/pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ where
}
}

/// try splice_unbounded 1st and splice_unbounded_broker if both of in/output are not pipe
#[inline]
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn splice_unbounded_auto<R, S>(source: &R, dest: &mut S) -> std::io::Result<bool>
where
R: Read + AsFd,
S: AsFd,
{
// use splice to check that input or output is pipe which is efficient
let fallback = match splice(&source, dest, MAX_ROOTLESS_PIPE_SIZE) {
Ok(_) => splice_unbounded(source, dest)?,
_ => splice_unbounded_broker(source, dest)?,
};
Ok(fallback)
}

/// splice `n` bytes with safe read/write fallback
/// return actually sent bytes
#[inline]
Expand Down
Loading