Skip to content
Merged
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: 4 additions & 10 deletions src/uu/cat/src/splice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,10 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd + Write>(
write_fd: &mut S,
) -> CatResult<bool> {
if splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE).is_ok() {
// fcntl improves throughput
// todo: avoid fcntl overhead for small input, but don't fcntl inside of the loop
let _ = rustix::pipe::fcntl_setpipe_size(&mut *write_fd, MAX_ROOTLESS_PIPE_SIZE);
loop {
match splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE) {
Ok(1..) => {}
Ok(0) => return Ok(might_fuse(&handle.reader)),
Err(_) => return Ok(true),
}
}
Ok(
uucore::pipes::splice_unbounded(&handle.reader, write_fd)?
|| might_fuse(&handle.reader),
)
} else {
Ok(
uucore::pipes::splice_unbounded_broker(&handle.reader, write_fd)?
Expand Down
25 changes: 25 additions & 0 deletions src/uucore/src/lib/features/pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,31 @@ pub fn might_fuse(source: &impl AsFd) -> bool {
rustix::fs::fstatfs(source).map_or(true, |stats| stats.f_type == 0x6573_5546) // FUSE magic number, too many platform specific clippy warning with const
}

/// splice all of source to dest
/// return true if we need read/write fallback
/// fails if one of in/output should be pipe
#[inline]
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn splice_unbounded<R, S>(source: &R, dest: &mut S) -> std::io::Result<bool>
where
R: Read + AsFd,
S: AsFd + std::io::Write,
{
// improve throughput
// todo: avoid fcntl overhead for small input, but don't fcntl inside of the loop
// no need to increase pipe size of input fd since
// - sender with splice probably increased size already
// - sender without splice is bottleneck
let _ = fcntl_setpipe_size(&mut *dest, MAX_ROOTLESS_PIPE_SIZE);
loop {
match splice(&source, &dest, MAX_ROOTLESS_PIPE_SIZE) {
Ok(1..) => {}
Ok(0) => return Ok(false),
Err(_) => return Ok(true),
}
}
}

/// force-splice source to dest even both of them are not pipe
/// return true if we need read/write fallback
///
Expand Down
Loading