Skip to content

Commit 4651b16

Browse files
authored
Rollup merge of #114373 - xstaticxgpx:dev, r=the8472
unix/kernel_copy.rs: copy_file_range_candidate allows empty output files This is for rust-lang/rust#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. Simply, determine what is input or output given the passed boolean.
2 parents 6f152dc + a79a14a commit 4651b16

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

Diff for: 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)