@@ -45,6 +45,16 @@ pub struct IoVecBuffer {
45
45
len : u32 ,
46
46
}
47
47
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
+
48
58
// SAFETY: `IoVecBuffer` doesn't allow for interior mutability and no shared ownership is possible
49
59
// as it doesn't implement clone
50
60
unsafe impl Send for IoVecBuffer { }
@@ -218,21 +228,39 @@ impl IoVecBuffer {
218
228
/// It describes a write-only buffer passed to us by the guest that is scattered across multiple
219
229
/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
220
230
/// of data from that buffer.
221
- #[ derive( Debug ) ]
231
+ #[ derive( Debug , Default ) ]
222
232
pub struct IoVecBufferMut {
223
233
// container of the memory regions included in this IO vector
224
234
vecs : IoVecVec ,
225
235
// Total length of the IoVecBufferMut
226
236
len : u32 ,
227
237
}
228
238
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
+
229
252
impl IoVecBufferMut {
230
253
/// 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 ( ) ;
234
262
235
- for desc in head {
263
+ loop {
236
264
if !desc. is_write_only ( ) {
237
265
return Err ( IoVecError :: ReadOnlyDescriptor ) ;
238
266
}
@@ -248,23 +276,57 @@ impl IoVecBufferMut {
248
276
slice. bitmap ( ) . mark_dirty ( 0 , desc. len as usize ) ;
249
277
250
278
let iov_base = slice. ptr_guard_mut ( ) . as_ptr ( ) . cast :: < c_void > ( ) ;
251
- vecs. push ( iovec {
279
+ self . vecs . push ( iovec {
252
280
iov_base,
253
281
iov_len : desc. len as size_t ,
254
282
} ) ;
255
- len = len
283
+ self . len = self
284
+ . len
256
285
. checked_add ( desc. len )
257
286
. 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
+ }
258
293
}
259
294
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)
261
307
}
262
308
263
309
/// Get the total length of the memory regions covered by this `IoVecBuffer`
264
310
pub ( crate ) fn len ( & self ) -> u32 {
265
311
self . len
266
312
}
267
313
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
+
268
330
/// Writes a number of bytes into the `IoVecBufferMut` starting at a given offset.
269
331
///
270
332
/// This will try to fill `IoVecBufferMut` writing bytes from the `buf` starting from
@@ -469,11 +531,13 @@ mod tests {
469
531
470
532
let ( mut q, _) = read_only_chain ( & mem) ;
471
533
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 ( ) } ;
473
536
474
537
let ( mut q, _) = write_only_chain ( & mem) ;
475
538
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 ( ) } ;
477
541
}
478
542
479
543
#[ test]
@@ -494,7 +558,7 @@ mod tests {
494
558
let head = q. pop ( & mem) . unwrap ( ) ;
495
559
496
560
// 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 ( ) } ;
498
562
assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
499
563
}
500
564
@@ -559,7 +623,8 @@ mod tests {
559
623
// This is a descriptor chain with 4 elements 64 bytes long each.
560
624
let head = q. pop ( & mem) . unwrap ( ) ;
561
625
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 ( ) } ;
563
628
let buf = vec ! [ 0u8 , 1 , 2 , 3 , 4 ] ;
564
629
565
630
// One test vector for each part of the chain
0 commit comments