@@ -37,19 +37,29 @@ type IoVecVec = SmallVec<[iovec; 4]>;
3737/// It describes a buffer passed to us by the guest that is scattered across multiple
3838/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
3939/// of data from that buffer.
40- #[ derive( Debug ) ]
40+ #[ derive( Debug , Default ) ]
4141pub struct IoVecBuffer {
4242 // container of the memory regions included in this IO vector
4343 vecs : IoVecVec ,
4444 // Total length of the IoVecBuffer
4545 len : u32 ,
4646}
4747
48+ // SAFETY: `IoVecBuffer` doesn't allow for interior mutability and no shared ownership is possible
49+ // as it doesn't implement clone
50+ unsafe impl Send for IoVecBuffer { }
51+
4852impl IoVecBuffer {
4953 /// Create an `IoVecBuffer` from a `DescriptorChain`
50- pub fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
51- let mut vecs = IoVecVec :: new ( ) ;
52- let mut len = 0u32 ;
54+ ///
55+ /// # Safety
56+ ///
57+ /// The descriptor chain cannot be referencing the same memory location as another chain
58+ pub unsafe fn load_descriptor_chain (
59+ & mut self ,
60+ head : DescriptorChain ,
61+ ) -> Result < ( ) , IoVecError > {
62+ self . clear ( ) ;
5363
5464 let mut next_descriptor = Some ( head) ;
5565 while let Some ( desc) = next_descriptor {
@@ -66,18 +76,32 @@ impl IoVecBuffer {
6676 . ptr_guard_mut ( )
6777 . as_ptr ( )
6878 . cast :: < c_void > ( ) ;
69- vecs. push ( iovec {
79+ self . vecs . push ( iovec {
7080 iov_base,
7181 iov_len : desc. len as size_t ,
7282 } ) ;
73- len = len
83+ self . len = self
84+ . len
7485 . checked_add ( desc. len )
7586 . ok_or ( IoVecError :: OverflowedDescriptor ) ?;
7687
7788 next_descriptor = desc. next_descriptor ( ) ;
7889 }
7990
80- Ok ( Self { vecs, len } )
91+ Ok ( ( ) )
92+ }
93+
94+ /// Create an `IoVecBuffer` from a `DescriptorChain`
95+ ///
96+ /// # Safety
97+ ///
98+ /// The descriptor chain cannot be referencing the same memory location as another chain
99+ pub unsafe fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
100+ let mut new_buffer: Self = Default :: default ( ) ;
101+
102+ new_buffer. load_descriptor_chain ( head) ?;
103+
104+ Ok ( new_buffer)
81105 }
82106
83107 /// Get the total length of the memory regions covered by this `IoVecBuffer`
@@ -95,6 +119,12 @@ impl IoVecBuffer {
95119 self . vecs . len ( )
96120 }
97121
122+ /// Clears the `iovec` array
123+ pub fn clear ( & mut self ) {
124+ self . vecs . clear ( ) ;
125+ self . len = 0u32 ;
126+ }
127+
98128 /// Reads a number of bytes from the `IoVecBuffer` starting at a given offset.
99129 ///
100130 /// This will try to fill `buf` reading bytes from the `IoVecBuffer` starting from
@@ -428,11 +458,13 @@ mod tests {
428458 let mem = default_mem ( ) ;
429459 let ( mut q, _) = read_only_chain ( & mem) ;
430460 let head = q. pop ( & mem) . unwrap ( ) ;
431- IoVecBuffer :: from_descriptor_chain ( head) . unwrap ( ) ;
461+ // SAFETY: This descriptor chain is only loaded into one buffer
462+ unsafe { IoVecBuffer :: from_descriptor_chain ( head) . unwrap ( ) } ;
432463
433464 let ( mut q, _) = write_only_chain ( & mem) ;
434465 let head = q. pop ( & mem) . unwrap ( ) ;
435- IoVecBuffer :: from_descriptor_chain ( head) . unwrap_err ( ) ;
466+ // SAFETY: This descriptor chain is only loaded into one buffer
467+ unsafe { IoVecBuffer :: from_descriptor_chain ( head) . unwrap_err ( ) } ;
436468
437469 let ( mut q, _) = read_only_chain ( & mem) ;
438470 let head = q. pop ( & mem) . unwrap ( ) ;
@@ -449,7 +481,8 @@ mod tests {
449481 let ( mut q, _) = read_only_chain ( & mem) ;
450482 let head = q. pop ( & mem) . unwrap ( ) ;
451483
452- let iovec = IoVecBuffer :: from_descriptor_chain ( head) . unwrap ( ) ;
484+ // SAFETY: This descriptor chain is only loaded once in this test
485+ let iovec = unsafe { IoVecBuffer :: from_descriptor_chain ( head) . unwrap ( ) } ;
453486 assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
454487 }
455488
@@ -459,6 +492,7 @@ mod tests {
459492 let ( mut q, _) = write_only_chain ( & mem) ;
460493 let head = q. pop ( & mem) . unwrap ( ) ;
461494
495+ // SAFETY: This descriptor chain is only loaded once in this test
462496 let iovec = IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
463497 assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
464498 }
@@ -469,7 +503,8 @@ mod tests {
469503 let ( mut q, _) = read_only_chain ( & mem) ;
470504 let head = q. pop ( & mem) . unwrap ( ) ;
471505
472- let iovec = IoVecBuffer :: from_descriptor_chain ( head) . unwrap ( ) ;
506+ // SAFETY: This descriptor chain is only loaded once in this test
507+ let iovec = unsafe { IoVecBuffer :: from_descriptor_chain ( head) . unwrap ( ) } ;
473508
474509 let mut buf = vec ! [ 0u8 ; 257 ] ;
475510 assert_eq ! (
0 commit comments