Skip to content

Commit 2232fe8

Browse files
committed
unix/kernel_copy.rs: copy_file_range_candidate allows empty output files
This is for #114341 The `meta.len() > 0` condition here is intended for inputs only, ie. when input is in the `/proc` filesystem as documented. That inaccurately included empty output files which are then shunted to the sendfile() routine leading to higher than nescessary IO util in some cases, specifically with CoW filesystems like btrfs. Further, `NoneObtained` is not relevant in this context, so remove it. Simply, determine what is input or output given the passed enum Unit.
1 parent d170833 commit 2232fe8

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

library/std/src/sys/unix/kernel_copy.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ enum FdMeta {
8989
NoneObtained,
9090
}
9191

92+
#[derive(PartialEq)]
93+
enum FdHandle {
94+
Input,
95+
Output,
96+
}
97+
9298
impl FdMeta {
9399
fn maybe_fifo(&self) -> bool {
94100
match self {
@@ -114,12 +120,14 @@ impl FdMeta {
114120
}
115121
}
116122

117-
fn copy_file_range_candidate(&self) -> bool {
123+
fn copy_file_range_candidate(&self, f: FdHandle) -> bool {
118124
match self {
119125
// copy_file_range will fail on empty procfs files. `read` can determine whether EOF has been reached
120126
// without extra cost and skip the write, thus there is no benefit in attempting copy_file_range
121-
FdMeta::Metadata(meta) if meta.is_file() && meta.len() > 0 => true,
122-
FdMeta::NoneObtained => true,
127+
FdMeta::Metadata(meta) if f == FdHandle::Input && meta.is_file() && meta.len() > 0 => {
128+
true
129+
}
130+
FdMeta::Metadata(meta) if f == FdHandle::Output && meta.is_file() => true,
123131
_ => false,
124132
}
125133
}
@@ -197,7 +205,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
197205
written += flush()?;
198206
let max_write = reader.min_limit();
199207

200-
if input_meta.copy_file_range_candidate() && output_meta.copy_file_range_candidate() {
208+
if input_meta.copy_file_range_candidate(FdHandle::Input)
209+
&& output_meta.copy_file_range_candidate(FdHandle::Output)
210+
{
201211
let result = copy_regular_files(readfd, writefd, max_write);
202212
result.update_take(reader);
203213

0 commit comments

Comments
 (0)