diff --git a/.vscode/cspell.dictionaries/workspace.wordlist.txt b/.vscode/cspell.dictionaries/workspace.wordlist.txt index a5d245016c7..a401d50a35f 100644 --- a/.vscode/cspell.dictionaries/workspace.wordlist.txt +++ b/.vscode/cspell.dictionaries/workspace.wordlist.txt @@ -369,6 +369,7 @@ weblate algs wasm wasip +SETPIPE # * stty terminal flags brkint diff --git a/src/uu/cat/src/splice.rs b/src/uu/cat/src/splice.rs index ca5265d2bf8..ed2c2e6299c 100644 --- a/src/uu/cat/src/splice.rs +++ b/src/uu/cat/src/splice.rs @@ -7,9 +7,8 @@ use super::{CatResult, FdReadable, InputHandle}; use nix::unistd; use std::os::{fd::AsFd, unix::io::AsRawFd}; -use uucore::pipes::{pipe, splice, splice_exact}; +use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, pipe, splice, splice_exact}; -const SPLICE_SIZE: usize = 1024 * 128; const BUF_SIZE: usize = 1024 * 16; /// This function is called from `write_fast()` on Linux and Android. The @@ -24,10 +23,16 @@ pub(super) fn write_fast_using_splice( handle: &InputHandle, write_fd: &S, ) -> CatResult { + use nix::fcntl::{FcntlArg, fcntl}; let (pipe_rd, pipe_wr) = pipe()?; + // improve performance + let _ = fcntl( + write_fd, + FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32), + ); loop { - match splice(&handle.reader, &pipe_wr, SPLICE_SIZE) { + match splice(&handle.reader, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) { Ok(n) => { if n == 0 { return Ok(false); diff --git a/src/uucore/src/lib/features/pipes.rs b/src/uucore/src/lib/features/pipes.rs index 069736c5215..a6fabc8e887 100644 --- a/src/uucore/src/lib/features/pipes.rs +++ b/src/uucore/src/lib/features/pipes.rs @@ -5,12 +5,14 @@ //! Thin pipe-related wrappers around functions from the `nix` crate. +#[cfg(any(target_os = "linux", target_os = "android"))] +use nix::fcntl::{FcntlArg, SpliceFFlags, fcntl}; +#[cfg(any(target_os = "linux", target_os = "android"))] use std::fs::File; #[cfg(any(target_os = "linux", target_os = "android"))] use std::os::fd::AsFd; - #[cfg(any(target_os = "linux", target_os = "android"))] -use nix::fcntl::SpliceFFlags; +pub const MAX_ROOTLESS_PIPE_SIZE: usize = 1024 * 1024; pub use nix::{Error, Result}; @@ -18,8 +20,13 @@ pub use nix::{Error, Result}; /// /// Returns two `File` objects: everything written to the second can be read /// from the first. +/// This is used only for resolving the limitation for splice: one of a input or output should be pipe +#[cfg(any(target_os = "linux", target_os = "android"))] pub fn pipe() -> Result<(File, File)> { let (read, write) = nix::unistd::pipe()?; + // improve performance for splice + let _ = fcntl(&read, FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32)); + Ok((File::from(read), File::from(write))) }