@@ -37,19 +37,29 @@ type IoVecVec = SmallVec<[iovec; 4]>;
37
37
/// It describes a buffer passed to us by the guest that is scattered across multiple
38
38
/// memory regions. Additionally, this wrapper provides methods that allow reading arbitrary ranges
39
39
/// of data from that buffer.
40
- #[ derive( Debug ) ]
40
+ #[ derive( Debug , Default ) ]
41
41
pub struct IoVecBuffer {
42
42
// container of the memory regions included in this IO vector
43
43
vecs : IoVecVec ,
44
44
// Total length of the IoVecBuffer
45
45
len : u32 ,
46
46
}
47
47
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
+
48
52
impl IoVecBuffer {
49
53
/// 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 ( ) ;
53
63
54
64
let mut next_descriptor = Some ( head) ;
55
65
while let Some ( desc) = next_descriptor {
@@ -66,18 +76,32 @@ impl IoVecBuffer {
66
76
. ptr_guard_mut ( )
67
77
. as_ptr ( )
68
78
. cast :: < c_void > ( ) ;
69
- vecs. push ( iovec {
79
+ self . vecs . push ( iovec {
70
80
iov_base,
71
81
iov_len : desc. len as size_t ,
72
82
} ) ;
73
- len = len
83
+ self . len = self
84
+ . len
74
85
. checked_add ( desc. len )
75
86
. ok_or ( IoVecError :: OverflowedDescriptor ) ?;
76
87
77
88
next_descriptor = desc. next_descriptor ( ) ;
78
89
}
79
90
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)
81
105
}
82
106
83
107
/// Get the total length of the memory regions covered by this `IoVecBuffer`
@@ -95,6 +119,12 @@ impl IoVecBuffer {
95
119
self . vecs . len ( )
96
120
}
97
121
122
+ /// Clears the `iovec` array
123
+ pub fn clear ( & mut self ) {
124
+ self . vecs . clear ( ) ;
125
+ self . len = 0u32 ;
126
+ }
127
+
98
128
/// Reads a number of bytes from the `IoVecBuffer` starting at a given offset.
99
129
///
100
130
/// This will try to fill `buf` reading bytes from the `IoVecBuffer` starting from
@@ -428,11 +458,13 @@ mod tests {
428
458
let mem = default_mem ( ) ;
429
459
let ( mut q, _) = read_only_chain ( & mem) ;
430
460
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 ( ) } ;
432
463
433
464
let ( mut q, _) = write_only_chain ( & mem) ;
434
465
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 ( ) } ;
436
468
437
469
let ( mut q, _) = read_only_chain ( & mem) ;
438
470
let head = q. pop ( & mem) . unwrap ( ) ;
@@ -449,7 +481,8 @@ mod tests {
449
481
let ( mut q, _) = read_only_chain ( & mem) ;
450
482
let head = q. pop ( & mem) . unwrap ( ) ;
451
483
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 ( ) } ;
453
486
assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
454
487
}
455
488
@@ -459,6 +492,7 @@ mod tests {
459
492
let ( mut q, _) = write_only_chain ( & mem) ;
460
493
let head = q. pop ( & mem) . unwrap ( ) ;
461
494
495
+ // SAFETY: This descriptor chain is only loaded once in this test
462
496
let iovec = IoVecBufferMut :: from_descriptor_chain ( head) . unwrap ( ) ;
463
497
assert_eq ! ( iovec. len( ) , 4 * 64 ) ;
464
498
}
@@ -469,7 +503,8 @@ mod tests {
469
503
let ( mut q, _) = read_only_chain ( & mem) ;
470
504
let head = q. pop ( & mem) . unwrap ( ) ;
471
505
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 ( ) } ;
473
508
474
509
let mut buf = vec ! [ 0u8 ; 257 ] ;
475
510
assert_eq ! (
0 commit comments