Skip to content

Commit b38eef8

Browse files
committed
cp: omit pipe() if input is pipe
1 parent 547a490 commit b38eef8

5 files changed

Lines changed: 30 additions & 54 deletions

File tree

src/uu/cat/src/cat.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ use uucore::error::{UResult, strip_errno};
2323
use uucore::translate;
2424
use uucore::{fast_inc::fast_inc_one, format_usage};
2525

26-
/// Linux splice support
27-
#[cfg(any(target_os = "linux", target_os = "android"))]
28-
mod splice;
29-
3026
// Allocate 32 digits for the line number.
3127
// An estimate is that we can print about 1e8 lines/seconds, so 32 digits
3228
// would be enough for billions of universe lifetimes.
@@ -483,14 +479,14 @@ fn print_fast<R: FdReadable>(handle: &mut InputHandle<R>) -> CatResult<()> {
483479
let stdout = io::stdout();
484480
#[cfg(any(target_os = "linux", target_os = "android"))]
485481
let mut stdout = stdout;
482+
// Try to use the splice() system call for faster writing. If it works, we're done.
486483
#[cfg(any(target_os = "linux", target_os = "android"))]
484+
if !uucore::pipes::splice_unbounded_auto(&handle.reader, &mut stdout)?
485+
&& !uucore::pipes::might_fuse(&handle.reader)
487486
{
488-
// If we're on Linux or Android, try to use the splice() system call
489-
// for faster writing. If it works, we're done.
490-
if !splice::write_fast_using_splice(handle, &mut stdout)? {
491-
return Ok(());
492-
}
487+
return Ok(());
493488
}
489+
494490
// If we're not on Linux or Android, or the splice() call failed,
495491
// fall back on slower writing.
496492
print_unbuffered(handle, stdout)

src/uu/cat/src/splice.rs

Lines changed: 0 additions & 29 deletions
This file was deleted.

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
@@ -154,6 +154,22 @@ where
154154
}
155155
}
156156

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

0 commit comments

Comments
 (0)