@@ -48,6 +48,8 @@ pub struct Entropy {
4848
4949 // Device specific fields
5050 rate_limiter : RateLimiter ,
51+
52+ buffer : IoVecBufferMut ,
5153}
5254
5355impl Entropy {
@@ -75,6 +77,7 @@ impl Entropy {
7577 queue_events,
7678 irq_trigger,
7779 rate_limiter,
80+ buffer : IoVecBufferMut :: default ( ) ,
7881 } )
7982 }
8083
@@ -88,13 +91,13 @@ impl Entropy {
8891 . map_err ( DeviceError :: FailedSignalingIrq )
8992 }
9093
91- fn rate_limit_request ( rate_limiter : & mut RateLimiter , bytes : u64 ) -> bool {
92- if !rate_limiter. consume ( 1 , TokenType :: Ops ) {
94+ fn rate_limit_request ( & mut self , bytes : u64 ) -> bool {
95+ if !self . rate_limiter . consume ( 1 , TokenType :: Ops ) {
9396 return false ;
9497 }
9598
96- if !rate_limiter. consume ( bytes, TokenType :: Bytes ) {
97- rate_limiter. manual_replenish ( 1 , TokenType :: Ops ) ;
99+ if !self . rate_limiter . consume ( bytes, TokenType :: Bytes ) {
100+ self . rate_limiter . manual_replenish ( 1 , TokenType :: Ops ) ;
98101 return false ;
99102 }
100103
@@ -106,53 +109,52 @@ impl Entropy {
106109 rate_limiter. manual_replenish ( bytes, TokenType :: Bytes ) ;
107110 }
108111
109- fn handle_one ( & self , iovec : & mut IoVecBufferMut ) -> Result < u32 , EntropyError > {
112+ fn handle_one ( & mut self ) -> Result < u32 , EntropyError > {
110113 // If guest provided us with an empty buffer just return directly
111- if iovec . len ( ) == 0 {
114+ if self . buffer . len ( ) == 0 {
112115 return Ok ( 0 ) ;
113116 }
114117
115- let mut rand_bytes = vec ! [ 0 ; iovec . len( ) as usize ] ;
118+ let mut rand_bytes = vec ! [ 0 ; self . buffer . len( ) as usize ] ;
116119 rand:: fill ( & mut rand_bytes) . map_err ( |err| {
117120 METRICS . host_rng_fails . inc ( ) ;
118121 err
119122 } ) ?;
120123
121124 // It is ok to unwrap here. We are writing `iovec.len()` bytes at offset 0.
122- iovec . write_all_volatile_at ( & rand_bytes, 0 ) . unwrap ( ) ;
123- Ok ( iovec . len ( ) )
125+ self . buffer . write_all_volatile_at ( & rand_bytes, 0 ) . unwrap ( ) ;
126+ Ok ( self . buffer . len ( ) )
124127 }
125128
126129 fn process_entropy_queue ( & mut self ) {
127- // This is safe since we checked in the event handler that the device is activated.
128- let mem = self . device_state . mem ( ) . unwrap ( ) ;
129-
130130 let mut used_any = false ;
131131 while let Some ( desc) = self . queues [ RNG_QUEUE ] . pop ( ) {
132+ // This is safe since we checked in the event handler that the device is activated.
133+ let mem = self . device_state . mem ( ) . unwrap ( ) ;
132134 let index = desc. index ;
133135 METRICS . entropy_event_count . inc ( ) ;
134136
135- // SAFETY: This descriptor chain is only loaded once
136- // virtio requests are handled sequentially so no two IoVecBuffers
137- // are live at the same time, meaning this has exclusive ownership over the memory
138- let bytes = match unsafe { IoVecBufferMut :: from_descriptor_chain ( mem, desc) } {
139- Ok ( mut iovec ) => {
137+ // SAFETY: This descriptor chain points to a single `DescriptorChain` memory buffer,
138+ // no other `IoVecBufferMut` object points to the same `DescriptorChain` at the same
139+ // time and we clear the `iovec` after we process the request.
140+ let bytes = match unsafe { self . buffer . load_descriptor_chain ( mem, desc) } {
141+ Ok ( ( ) ) => {
140142 debug ! (
141143 "entropy: guest request for {} bytes of entropy" ,
142- iovec . len( )
144+ self . buffer . len( )
143145 ) ;
144146
145147 // Check for available rate limiting budget.
146148 // If not enough budget is available, leave the request descriptor in the queue
147149 // to handle once we do have budget.
148- if !Self :: rate_limit_request ( & mut self . rate_limiter , u64:: from ( iovec . len ( ) ) ) {
150+ if !self . rate_limit_request ( u64:: from ( self . buffer . len ( ) ) ) {
149151 debug ! ( "entropy: throttling entropy queue" ) ;
150152 METRICS . entropy_rate_limiter_throttled . inc ( ) ;
151153 self . queues [ RNG_QUEUE ] . undo_pop ( ) ;
152154 break ;
153155 }
154156
155- self . handle_one ( & mut iovec ) . unwrap_or_else ( |err| {
157+ self . handle_one ( ) . unwrap_or_else ( |err| {
156158 error ! ( "entropy: {err}" ) ;
157159 METRICS . entropy_event_fails . inc ( ) ;
158160 0
@@ -444,8 +446,8 @@ mod tests {
444446 // This should succeed, we should have one more descriptor
445447 let desc = entropy_dev. queues_mut ( ) [ RNG_QUEUE ] . pop ( ) . unwrap ( ) ;
446448 // SAFETY: This descriptor chain is only loaded into one buffer
447- let mut iovec = unsafe { IoVecBufferMut :: from_descriptor_chain ( & mem, desc) . unwrap ( ) } ;
448- entropy_dev. handle_one ( & mut iovec ) . unwrap ( ) ;
449+ entropy_dev . buffer = unsafe { IoVecBufferMut :: from_descriptor_chain ( & mem, desc) . unwrap ( ) } ;
450+ entropy_dev. handle_one ( ) . unwrap ( ) ;
449451 }
450452
451453 #[ test]
0 commit comments