@@ -217,7 +217,7 @@ impl IoVecBuffer {
217
217
/// It describes a write-only buffer passed to us by the guest that is scattered across multiple
218
218
/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
219
219
/// of data from that buffer.
220
- #[ derive( Debug ) ]
220
+ #[ derive( Debug , Default , Clone ) ]
221
221
pub struct IoVecBufferMut {
222
222
// container of the memory regions included in this IO vector
223
223
vecs : IoVecVec ,
@@ -226,12 +226,19 @@ pub struct IoVecBufferMut {
226
226
}
227
227
228
228
impl IoVecBufferMut {
229
- /// Create an `IoVecBufferMut` from a `DescriptorChain`
230
- pub fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
231
- let mut vecs = IoVecVec :: new ( ) ;
232
- let mut len = 0u32 ;
229
+ /// Create an `IoVecBuffer` from a `DescriptorChain`
230
+ ///
231
+ /// # Safety
232
+ ///
233
+ /// The descriptor chain cannot be referencing the same memory location as another chain
234
+ pub unsafe fn load_descriptor_chain (
235
+ & mut self ,
236
+ head : DescriptorChain ,
237
+ ) -> Result < ( ) , IoVecError > {
238
+ self . clear ( ) ;
233
239
234
- for desc in head {
240
+ let mut next_descriptor = Some ( head) ;
241
+ while let Some ( desc) = next_descriptor {
235
242
if !desc. is_write_only ( ) {
236
243
return Err ( IoVecError :: ReadOnlyDescriptor ) ;
237
244
}
@@ -247,23 +254,45 @@ impl IoVecBufferMut {
247
254
slice. bitmap ( ) . mark_dirty ( 0 , desc. len as usize ) ;
248
255
249
256
let iov_base = slice. ptr_guard_mut ( ) . as_ptr ( ) . cast :: < c_void > ( ) ;
250
- vecs. push ( iovec {
257
+ self . vecs . push ( iovec {
251
258
iov_base,
252
259
iov_len : desc. len as size_t ,
253
260
} ) ;
254
- len = len
261
+ self . len = self
262
+ . len
255
263
. checked_add ( desc. len )
256
264
. ok_or ( IoVecError :: OverflowedDescriptor ) ?;
265
+
266
+ next_descriptor = desc. next_descriptor ( ) ;
257
267
}
258
268
259
- Ok ( Self { vecs, len } )
269
+ Ok ( ( ) )
270
+ }
271
+
272
+ /// Create an `IoVecBuffer` from a `DescriptorChain`
273
+ ///
274
+ /// # Safety
275
+ ///
276
+ /// The descriptor chain cannot be referencing the same memory location as another chain
277
+ pub unsafe fn from_descriptor_chain ( head : DescriptorChain ) -> Result < Self , IoVecError > {
278
+ let mut new_buffer: Self = Default :: default ( ) ;
279
+
280
+ new_buffer. load_descriptor_chain ( head) ?;
281
+
282
+ Ok ( new_buffer)
260
283
}
261
284
262
285
/// Get the total length of the memory regions covered by this `IoVecBuffer`
263
286
pub ( crate ) fn len ( & self ) -> u32 {
264
287
self . len
265
288
}
266
289
290
+ /// Clears the `iovec` array
291
+ pub fn clear ( & mut self ) {
292
+ self . vecs . clear ( ) ;
293
+ self . len = 0u32 ;
294
+ }
295
+
267
296
/// Writes a number of bytes into the `IoVecBufferMut` starting at a given offset.
268
297
///
269
298
/// This will try to fill `IoVecBufferMut` writing bytes from the `buf` starting from
@@ -468,11 +497,13 @@ mod tests {
468
497
469
498
let ( mut q, _) = read_only_chain ( & mem) ;
470
499
let head = q. pop ( & mem) . unwrap ( ) ;
471
- IoVecBufferMut :: from_descriptor_chain ( head) . unwrap_err ( ) ;
500
+ // SAFETY: This descriptor chain is only loaded into one buffer
501
+ unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap_err ( ) } ;
472
502
473
503
let ( mut q, _) = write_only_chain ( & mem) ;
474
504
let head = q. pop ( & mem) . unwrap ( ) ;
475
- IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
505
+ // SAFETY: This descriptor chain is only loaded into one buffer
506
+ unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) } ;
476
507
}
477
508
478
509
#[ test]
@@ -493,7 +524,7 @@ mod tests {
493
524
let head = q. pop ( & mem) . unwrap ( ) ;
494
525
495
526
// SAFETY: This descriptor chain is only loaded once in this test
496
- let iovec = IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
527
+ let iovec = unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) } ;
497
528
assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
498
529
}
499
530
@@ -558,7 +589,8 @@ mod tests {
558
589
// This is a descriptor chain with 4 elements 64 bytes long each.
559
590
let head = q. pop ( & mem) . unwrap ( ) ;
560
591
561
- let mut iovec = IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
592
+ // SAFETY: This descriptor chain is only loaded into one buffer
593
+ let mut iovec = unsafe { IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) } ;
562
594
let buf = vec ! [ 0u8 , 1 , 2 , 3 , 4 ] ;
563
595
564
596
// One test vector for each part of the chain
0 commit comments