@@ -45,6 +45,16 @@ pub struct IoVecBuffer {
4545 len : u32 ,
4646}
4747
48+ impl IoVecBuffer {
49+ /// Create an empty `IoVecBuffer` with a given capacity.
50+ pub fn with_capacity ( cap : usize ) -> IoVecBuffer {
51+ IoVecBuffer {
52+ vecs : IoVecVec :: with_capacity ( cap) ,
53+ len : 0 ,
54+ }
55+ }
56+ }
57+
4858// SAFETY: `IoVecBuffer` doesn't allow for interior mutability and no shared ownership is possible
4959// as it doesn't implement clone
5060unsafe impl Send for IoVecBuffer { }
@@ -218,21 +228,39 @@ impl IoVecBuffer {
218228/// It describes a write-only buffer passed to us by the guest that is scattered across multiple
219229/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
220230/// of data from that buffer.
221- #[ derive( Debug ) ]
231+ #[ derive( Debug , Default ) ]
222232pub struct IoVecBufferMut {
223233 // container of the memory regions included in this IO vector
224234 vecs : IoVecVec ,
225235 // Total length of the IoVecBufferMut
226236 len : u32 ,
227237}
228238
239+ impl IoVecBufferMut {
240+ /// Create an empty `IoVecBufferMut` with a given capacity.
241+ pub fn with_capacity ( cap : usize ) -> IoVecBufferMut {
242+ IoVecBufferMut {
243+ vecs : IoVecVec :: with_capacity ( cap) ,
244+ len : 0 ,
245+ }
246+ }
247+ }
248+
249+ // SAFETY: iovec pointers are safe to send across threads.
250+ unsafe impl Send for IoVecBufferMut { }
251+
229252impl IoVecBufferMut {
230253 /// Create an `IoVecBufferMut` from a `DescriptorChain`
231- pub fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
232- let mut vecs = IoVecVec :: new ( ) ;
233- let mut len = 0u32 ;
254+ /// # Safety
255+ /// The descriptor chain cannot be referencing the same memory location as another chain.
256+ pub unsafe fn load_descriptor_chain (
257+ & mut self ,
258+ mut desc : DescriptorChain ,
259+ max_size : Option < u32 > ,
260+ ) -> Result < ( ) , IoVecError > {
261+ self . clear ( ) ;
234262
235- for desc in head {
263+ loop {
236264 if !desc. is_write_only ( ) {
237265 return Err ( IoVecError :: ReadOnlyDescriptor ) ;
238266 }
@@ -248,23 +276,57 @@ impl IoVecBufferMut {
248276 slice. bitmap ( ) . mark_dirty ( 0 , desc. len as usize ) ;
249277
250278 let iov_base = slice. ptr_guard_mut ( ) . as_ptr ( ) . cast :: < c_void > ( ) ;
251- vecs. push ( iovec {
279+ self . vecs . push ( iovec {
252280 iov_base,
253281 iov_len : desc. len as size_t ,
254282 } ) ;
255- len = len
283+ self . len = self
284+ . len
256285 . checked_add ( desc. len )
257286 . ok_or ( IoVecError :: OverflowedDescriptor ) ?;
287+ if matches ! ( max_size, Some ( max) if self . len >= max) {
288+ break ;
289+ }
290+ if desc. load_next_descriptor ( ) . is_none ( ) {
291+ break ;
292+ }
258293 }
259294
260- Ok ( Self { vecs, len } )
295+ Ok ( ( ) )
296+ }
297+
298+ /// Create an `IoVecBufferMut` from a `DescriptorChain`
299+ /// # Safety
300+ /// The descriptor chain cannot be referencing the same memory location as another chain.
301+ pub unsafe fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
302+ let mut new_buffer = Self :: default ( ) ;
303+
304+ Self :: load_descriptor_chain ( & mut new_buffer, head, None ) ?;
305+
306+ Ok ( new_buffer)
261307 }
262308
263309 /// Get the total length of the memory regions covered by this `IoVecBuffer`
264310 pub ( crate ) fn len ( & self ) -> u32 {
265311 self . len
266312 }
267313
314+ /// Returns a pointer to the memory keeping the `iovec` structs
315+ pub fn as_iovec_ptr ( & self ) -> * const iovec {
316+ self . vecs . as_ptr ( )
317+ }
318+
319+ /// Returns the length of the `iovec` array.
320+ pub fn iovec_count ( & self ) -> usize {
321+ self . vecs . len ( )
322+ }
323+
324+ /// Clears the `iovec` array
325+ pub fn clear ( & mut self ) {
326+ self . vecs . clear ( ) ;
327+ self . len = 0u32 ;
328+ }
329+
268330 /// Writes a number of bytes into the `IoVecBufferMut` starting at a given offset.
269331 ///
270332 /// This will try to fill `IoVecBufferMut` writing bytes from the `buf` starting from
@@ -469,11 +531,13 @@ mod tests {
469531
470532 let ( mut q, _) = read_only_chain ( & mem) ;
471533 let head = q. pop ( & mem) . unwrap ( ) ;
472- IoVecBufferMut :: from_descriptor_chain ( head) . unwrap_err ( ) ;
534+ // SAFETY: This descriptor chain is only loaded into one buffer.
535+ unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap_err ( ) } ;
473536
474537 let ( mut q, _) = write_only_chain ( & mem) ;
475538 let head = q. pop ( & mem) . unwrap ( ) ;
476- IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
539+ // SAFETY: This descriptor chain is only loaded into one buffer.
540+ unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) } ;
477541 }
478542
479543 #[ test]
@@ -494,7 +558,7 @@ mod tests {
494558 let head = q. pop ( & mem) . unwrap ( ) ;
495559
496560 // SAFETY: This descriptor chain is only loaded once in this test
497- let iovec = IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
561+ let iovec = unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) } ;
498562 assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
499563 }
500564
@@ -559,7 +623,8 @@ mod tests {
559623 // This is a descriptor chain with 4 elements 64 bytes long each.
560624 let head = q. pop ( & mem) . unwrap ( ) ;
561625
562- let mut iovec = IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
626+ // SAFETY: This descriptor chain is only loaded into one buffer.
627+ let mut iovec = unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) } ;
563628 let buf = vec ! [ 0u8 , 1 , 2 , 3 , 4 ] ;
564629
565630 // One test vector for each part of the chain
0 commit comments