@@ -81,26 +81,21 @@ pub fn might_fuse(source: &impl AsFd) -> bool {
8181}
8282
8383/// splice all of source to dest
84- /// return true if we need read/write fallback
85- /// fails if one of in/output should be pipe
84+ /// return true if splice failed (e.g. both of in/output are not pipe)
85+ ///
86+ /// splice_unbounded_broker can be used as a fallback
8687#[ inline]
8788#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
88- pub fn splice_unbounded < R , S > ( source : & R , dest : & mut S ) -> std :: io :: Result < bool >
89+ fn splice_unbounded < R , S > ( source : & R , dest : & mut S ) -> bool
8990where
9091 R : Read + AsFd ,
9192 S : AsFd ,
9293{
93- // improve throughput
94- // todo: avoid fcntl overhead for small input, but don't fcntl inside of the loop
95- // no need to increase pipe size of input fd since
96- // - sender with splice probably increased size already
97- // - sender without splice is bottleneck
98- let _ = fcntl_setpipe_size ( & mut * dest, MAX_ROOTLESS_PIPE_SIZE ) ;
9994 loop {
10095 match splice ( & source, & dest, MAX_ROOTLESS_PIPE_SIZE ) {
101- Ok ( 1 .. ) => { }
102- Ok ( 0 ) => return Ok ( false ) ,
103- Err ( _) => return Ok ( true ) ,
96+ Ok ( 0 ) => return false ,
97+ Ok ( _ ) => { }
98+ Err ( _) => return true ,
10499 }
105100 }
106101}
@@ -111,7 +106,7 @@ where
111106/// This should not be used if one of them are pipe to save resources
112107#[ inline]
113108#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
114- pub fn splice_unbounded_broker < R , S > ( source : & R , dest : & mut S ) -> std:: io:: Result < bool >
109+ fn splice_unbounded_broker < R , S > ( source : & R , dest : & mut S ) -> std:: io:: Result < bool >
115110where
116111 R : Read + AsFd ,
117112 S : AsFd ,
@@ -123,11 +118,6 @@ where
123118 else {
124119 return Ok ( true ) ;
125120 } ;
126- // improve throughput
127- // no need to increase pipe size of input fd since
128- // - sender with splice probably increased size already
129- // - sender without splice is bottleneck
130- let _ = fcntl_setpipe_size ( & mut * dest, MAX_ROOTLESS_PIPE_SIZE ) ;
131121
132122 loop {
133123 match splice ( & source, & pipe_wr, MAX_ROOTLESS_PIPE_SIZE ) {
@@ -159,10 +149,17 @@ where
159149 R : Read + AsFd ,
160150 S : AsFd ,
161151{
162- // use splice to check that input or output is pipe which is efficient
163- let fallback = match splice ( & source, dest, MAX_ROOTLESS_PIPE_SIZE ) {
164- Ok ( _) => splice_unbounded ( source, dest) ?,
165- _ => splice_unbounded_broker ( source, dest) ?,
152+ // use fcntl or splice to check that input or output is pipe which is efficient
153+ // no need to increase pipe size of input for throughput since
154+ // - sender with splice probably increased size already
155+ // - sender without splice is bottleneck
156+ // todo: cache this fcntl call
157+ let is_direct_splice = fcntl_setpipe_size ( & mut * dest, MAX_ROOTLESS_PIPE_SIZE ) . is_ok ( )
158+ || splice ( & source, dest, MAX_ROOTLESS_PIPE_SIZE ) . is_ok ( ) ;
159+ let fallback = if is_direct_splice {
160+ splice_unbounded ( source, dest)
161+ } else {
162+ splice_unbounded_broker ( source, dest) ?
166163 } ;
167164 Ok ( fallback)
168165}
0 commit comments