Skip to content

Commit cdc5705

Browse files
committed
uucore: simplify fallback when splice failed
1 parent 34fd4be commit cdc5705

File tree

2 files changed

+8
-47
lines changed

2 files changed

+8
-47
lines changed

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,6 @@ mod tests {
5151
.unwrap()
5252
}
5353

54-
#[cfg(any(target_os = "linux", target_os = "android"))]
55-
#[test]
56-
fn test_copy_exact() {
57-
let (mut pipe_read, mut pipe_write) = pipes::pipe().unwrap();
58-
let data = b"Hello, world!";
59-
let n = pipe_write.write(data).unwrap();
60-
assert_eq!(n, data.len());
61-
let mut buf = [0; 1024];
62-
let n = copy_exact(&pipe_read, &pipe_write, data.len()).unwrap();
63-
let n2 = pipe_read.read(&mut buf).unwrap();
64-
assert_eq!(n, n2);
65-
assert_eq!(&buf[..n], data);
66-
}
67-
6854
#[test]
6955
#[cfg(unix)]
7056
fn test_copy_stream() {

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

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ pub trait FdWritable: Write + AsFd + AsRawFd {}
2828

2929
impl<T> FdWritable for T where T: Write + AsFd + AsRawFd {}
3030

31-
const BUF_SIZE: usize = 1024 * 16;
32-
3331
/// Conversion from a `rustix::io::Errno` into our `Error` which implements `UError`.
3432
impl From<rustix::io::Errno> for Error {
3533
fn from(error: rustix::io::Errno) -> Self {
@@ -55,7 +53,7 @@ where
5553
{
5654
// If we're on Linux or Android, try to use the splice() system call
5755
// for faster writing. If it works, we're done.
58-
if !splice_write(src, &dest.as_fd())? {
56+
if !splice_write(src, dest)? {
5957
return Ok(());
6058
}
6159

@@ -78,17 +76,17 @@ where
7876
/// - `source` - source handle
7977
/// - `dest` - destination handle
8078
#[inline]
81-
pub(crate) fn splice_write<R, S>(source: &R, dest: &S) -> UResult<bool>
79+
pub(crate) fn splice_write<R, S>(source: &R, dest: &mut S) -> UResult<bool>
8280
where
8381
R: Read + AsFd + AsRawFd,
84-
S: AsRawFd + AsFd,
82+
S: AsRawFd + AsFd + Write,
8583
{
86-
let (pipe_rd, pipe_wr) = pipe()?;
84+
let (pipe_rd, pipe_wr) = pipe()?; // todo: bypass this if input or output is pipe. We use this mostly for stream.
8785
// improve throughput
8886
// no need to increase pipe size of input fd since
8987
// - sender with splice probably increased size already
9088
// - sender without splice is bottleneck
91-
let _ = rustix::pipe::fcntl_setpipe_size(dest, MAX_ROOTLESS_PIPE_SIZE);
89+
let _ = rustix::pipe::fcntl_setpipe_size(&mut *dest, MAX_ROOTLESS_PIPE_SIZE);
9290

9391
loop {
9492
match splice(&source, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
@@ -100,36 +98,13 @@ where
10098
// we can recover by copying the data that we have from the
10199
// intermediate pipe to stdout using normal read/write. Then
102100
// we tell the caller to fall back.
103-
copy_exact(&pipe_rd, dest, n)?;
101+
let mut drain = Vec::with_capacity(n); // bounded by pipe size
102+
pipe_rd.take(n as u64).read_to_end(&mut drain)?;
103+
dest.write_all(&drain)?;
104104
return Ok(true);
105105
}
106106
}
107107
Err(_) => return Ok(true),
108108
}
109109
}
110110
}
111-
112-
/// Move exactly `num_bytes` bytes from `read_fd` to `write_fd` using the `read`
113-
/// and `write` calls.
114-
#[cfg(any(target_os = "linux", target_os = "android"))]
115-
pub(crate) fn copy_exact(
116-
read_fd: &impl AsFd,
117-
write_fd: &impl AsFd,
118-
num_bytes: usize,
119-
) -> std::io::Result<usize> {
120-
let mut left = num_bytes;
121-
let mut buf = [0; BUF_SIZE];
122-
let mut total_written = 0;
123-
while left > 0 {
124-
let n_read = rustix::io::read(read_fd, &mut buf)?;
125-
assert_ne!(n_read, 0, "unexpected end of pipe");
126-
let mut written = 0;
127-
while written < n_read {
128-
let n = rustix::io::write(write_fd, &buf[written..n_read])?;
129-
written += n;
130-
}
131-
total_written += written;
132-
left -= n_read;
133-
}
134-
Ok(total_written)
135-
}

0 commit comments

Comments
 (0)