Skip to content

Commit 7e64abe

Browse files
committed
cp: omit pipe() if input is pipe
1 parent db25551 commit 7e64abe

4 files changed

Lines changed: 27 additions & 24 deletions

File tree

src/uu/cat/src/splice.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ use super::{CatResult, FdReadable, InputHandle};
66

77
use std::os::fd::AsFd;
88

9-
use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, might_fuse, splice};
10-
119
/// This function is called from `write_fast()` on Linux and Android. The
1210
/// function `splice()` is used to move data between two file descriptors
1311
/// without copying between kernel and user spaces. This results in a large
@@ -20,10 +18,6 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsFd>(
2018
handle: &InputHandle<R>,
2119
write_fd: &mut S,
2220
) -> CatResult<bool> {
23-
let res = match splice(&handle.reader, &write_fd, MAX_ROOTLESS_PIPE_SIZE) {
24-
Ok(_) => uucore::pipes::splice_unbounded(&handle.reader, write_fd)?,
25-
// both of in/output are not pipe
26-
_ => uucore::pipes::splice_unbounded_broker(&handle.reader, write_fd)?,
27-
};
28-
Ok(res || might_fuse(&handle.reader))
21+
let res = uucore::pipes::splice_unbounded_auto(&handle.reader, write_fd)?;
22+
Ok(res || uucore::pipes::might_fuse(&handle.reader))
2923
}

src/uu/tail/src/tail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ fn print_target_section<
591591
} else {
592592
// zero-copy fast-path
593593
#[cfg(any(target_os = "linux", target_os = "android"))]
594-
if uucore::pipes::splice_unbounded_broker(file, &mut stdout)? {
594+
if uucore::pipes::splice_unbounded_auto(file, &mut stdout)? {
595595
io::copy(file, &mut stdout)?;
596596
}
597597
#[cfg(not(any(target_os = "linux", target_os = "android")))]

src/uucore/src/lib/features/buf_copy/linux.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,14 @@ where
3939
R: Read + AsFd + AsRawFd,
4040
S: Write + AsFd + AsRawFd,
4141
{
42-
// If we're on Linux or Android, try to use the splice() system call
43-
// for faster writing. If it works, we're done.
44-
// todo: bypass broker pipe this if input or output is pipe. We use this mostly for stream.
45-
if !crate::pipes::splice_unbounded_broker(src, dest)? {
46-
return Ok(());
42+
// try to use the splice() system call
43+
// for faster writing. If it works, we're done
44+
if crate::pipes::splice_unbounded_auto(&src, dest)? {
45+
std::io::copy(src, dest)?;
46+
// todo: Do not mix writing by raw syscall and std's buffered write,
47+
// or order of output would be wrong when this was called multiple times
48+
// and splice_unbounded_auto sent content partially. flush works as an workaround.
49+
dest.flush()?;
4750
}
48-
49-
// If the splice() call failed, fall back on slower writing.
50-
std::io::copy(src, dest)?;
51-
52-
// If the splice() call failed and there has been some data written to
53-
// stdout via while loop above AND there will be second splice() call
54-
// that will succeed, data pushed through splice will be output before
55-
// the data buffered in stdout.lock. Therefore additional explicit flush
56-
// is required here.
57-
dest.flush()?;
5851
Ok(())
5952
}

src/uucore/src/lib/features/pipes.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,22 @@ where
151151
}
152152
}
153153

154+
/// try splice_unbounded 1st and splice_unbounded_broker if both of in/output are not pipe
155+
#[inline]
156+
#[cfg(any(target_os = "linux", target_os = "android"))]
157+
pub fn splice_unbounded_auto<R, S>(source: &R, dest: &mut S) -> std::io::Result<bool>
158+
where
159+
R: Read + AsFd,
160+
S: AsFd,
161+
{
162+
// use splice to check that input or output is pipe which is efficient
163+
let fallback = match splice(&source, dest, MAX_ROOTLESS_PIPE_SIZE) {
164+
Ok(_) => splice_unbounded(source, dest)?,
165+
_ => splice_unbounded_broker(source, dest)?,
166+
};
167+
Ok(fallback)
168+
}
169+
154170
/// splice `n` bytes with safe read/write fallback
155171
/// return actually sent bytes
156172
#[inline]

0 commit comments

Comments
 (0)