@@ -167,10 +167,11 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
167
167
168
168
if input_meta. copy_file_range_candidate ( ) && output_meta. copy_file_range_candidate ( ) {
169
169
let result = copy_regular_files ( readfd, writefd, max_write) ;
170
+ result. update_take ( reader) ;
170
171
171
172
match result {
172
- CopyResult :: Ended ( Ok ( bytes_copied) ) => return Ok ( bytes_copied + written) ,
173
- CopyResult :: Ended ( err ) => return err ,
173
+ CopyResult :: Ended ( bytes_copied) => return Ok ( bytes_copied + written) ,
174
+ CopyResult :: Error ( e , _ ) => return Err ( e ) ,
174
175
CopyResult :: Fallback ( bytes) => written += bytes,
175
176
}
176
177
}
@@ -182,20 +183,22 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
182
183
// fall back to the generic copy loop.
183
184
if input_meta. potential_sendfile_source ( ) {
184
185
let result = sendfile_splice ( SpliceMode :: Sendfile , readfd, writefd, max_write) ;
186
+ result. update_take ( reader) ;
185
187
186
188
match result {
187
- CopyResult :: Ended ( Ok ( bytes_copied) ) => return Ok ( bytes_copied + written) ,
188
- CopyResult :: Ended ( err ) => return err ,
189
+ CopyResult :: Ended ( bytes_copied) => return Ok ( bytes_copied + written) ,
190
+ CopyResult :: Error ( e , _ ) => return Err ( e ) ,
189
191
CopyResult :: Fallback ( bytes) => written += bytes,
190
192
}
191
193
}
192
194
193
195
if input_meta. maybe_fifo ( ) || output_meta. maybe_fifo ( ) {
194
196
let result = sendfile_splice ( SpliceMode :: Splice , readfd, writefd, max_write) ;
197
+ result. update_take ( reader) ;
195
198
196
199
match result {
197
- CopyResult :: Ended ( Ok ( bytes_copied) ) => return Ok ( bytes_copied + written) ,
198
- CopyResult :: Ended ( err ) => return err ,
200
+ CopyResult :: Ended ( bytes_copied) => return Ok ( bytes_copied + written) ,
201
+ CopyResult :: Error ( e , _ ) => return Err ( e ) ,
199
202
CopyResult :: Fallback ( 0 ) => { /* use the fallback below */ }
200
203
CopyResult :: Fallback ( _) => {
201
204
unreachable ! ( "splice should not return > 0 bytes on the fallback path" )
@@ -225,6 +228,9 @@ trait CopyRead: Read {
225
228
Ok ( 0 )
226
229
}
227
230
231
+ /// Updates `Take` wrappers to remove the number of bytes copied.
232
+ fn taken ( & mut self , _bytes : u64 ) { }
233
+
228
234
/// The minimum of the limit of all `Take<_>` wrappers, `u64::MAX` otherwise.
229
235
/// This method does not account for data `BufReader` buffers and would underreport
230
236
/// the limit of a `Take<BufReader<Take<_>>>` type. Thus its result is only valid
@@ -251,6 +257,10 @@ where
251
257
( * * self ) . drain_to ( writer, limit)
252
258
}
253
259
260
+ fn taken ( & mut self , bytes : u64 ) {
261
+ ( * * self ) . taken ( bytes) ;
262
+ }
263
+
254
264
fn min_limit ( & self ) -> u64 {
255
265
( * * self ) . min_limit ( )
256
266
}
@@ -407,6 +417,11 @@ impl<T: CopyRead> CopyRead for Take<T> {
407
417
Ok ( bytes_drained)
408
418
}
409
419
420
+ fn taken ( & mut self , bytes : u64 ) {
421
+ self . set_limit ( self . limit ( ) - bytes) ;
422
+ self . get_mut ( ) . taken ( bytes) ;
423
+ }
424
+
410
425
fn min_limit ( & self ) -> u64 {
411
426
min ( Take :: limit ( self ) , self . get_ref ( ) . min_limit ( ) )
412
427
}
@@ -432,6 +447,10 @@ impl<T: CopyRead> CopyRead for BufReader<T> {
432
447
Ok ( bytes as u64 + inner_bytes)
433
448
}
434
449
450
+ fn taken ( & mut self , bytes : u64 ) {
451
+ self . get_mut ( ) . taken ( bytes) ;
452
+ }
453
+
435
454
fn min_limit ( & self ) -> u64 {
436
455
self . get_ref ( ) . min_limit ( )
437
456
}
@@ -457,10 +476,21 @@ fn fd_to_meta<T: AsRawFd>(fd: &T) -> FdMeta {
457
476
}
458
477
459
478
pub ( super ) enum CopyResult {
460
- Ended ( Result < u64 > ) ,
479
+ Ended ( u64 ) ,
480
+ Error ( Error , u64 ) ,
461
481
Fallback ( u64 ) ,
462
482
}
463
483
484
+ impl CopyResult {
485
+ fn update_take ( & self , reader : & mut impl CopyRead ) {
486
+ match * self {
487
+ CopyResult :: Fallback ( bytes)
488
+ | CopyResult :: Ended ( bytes)
489
+ | CopyResult :: Error ( _, bytes) => reader. taken ( bytes) ,
490
+ }
491
+ }
492
+ }
493
+
464
494
/// linux-specific implementation that will attempt to use copy_file_range for copy offloading
465
495
/// as the name says, it only works on regular files
466
496
///
@@ -527,7 +557,7 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
527
557
// - copying from an overlay filesystem in docker. reported to occur on fedora 32.
528
558
return CopyResult :: Fallback ( 0 ) ;
529
559
}
530
- Ok ( 0 ) => return CopyResult :: Ended ( Ok ( written) ) , // reached EOF
560
+ Ok ( 0 ) => return CopyResult :: Ended ( written) , // reached EOF
531
561
Ok ( ret) => written += ret as u64 ,
532
562
Err ( err) => {
533
563
return match err. raw_os_error ( ) {
@@ -545,12 +575,12 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
545
575
assert_eq ! ( written, 0 ) ;
546
576
CopyResult :: Fallback ( 0 )
547
577
}
548
- _ => CopyResult :: Ended ( Err ( err) ) ,
578
+ _ => CopyResult :: Error ( err, written ) ,
549
579
} ;
550
580
}
551
581
}
552
582
}
553
- CopyResult :: Ended ( Ok ( written) )
583
+ CopyResult :: Ended ( written)
554
584
}
555
585
556
586
#[ derive( PartialEq ) ]
@@ -623,10 +653,10 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
623
653
Some ( os_err) if mode == SpliceMode :: Sendfile && os_err == libc:: EOVERFLOW => {
624
654
CopyResult :: Fallback ( written)
625
655
}
626
- _ => CopyResult :: Ended ( Err ( err) ) ,
656
+ _ => CopyResult :: Error ( err, written ) ,
627
657
} ;
628
658
}
629
659
}
630
660
}
631
- CopyResult :: Ended ( Ok ( written) )
661
+ CopyResult :: Ended ( written)
632
662
}
0 commit comments