@@ -21,7 +21,7 @@ use virtio_gen::virtio_blk::*;
2121use vm_memory:: { Bytes , GuestMemoryMmap } ;
2222
2323use super :: {
24- super :: { ActivateResult , Queue , VirtioDevice , TYPE_BLOCK , VIRTIO_MMIO_INT_VRING } ,
24+ super :: { ActivateResult , DeviceState , Queue , VirtioDevice , TYPE_BLOCK , VIRTIO_MMIO_INT_VRING } ,
2525 request:: * ,
2626 Error , CONFIG_SPACE_SIZE , QUEUE_SIZES , SECTOR_SHIFT , SECTOR_SIZE ,
2727} ;
@@ -88,15 +88,15 @@ pub struct Block {
8888 avail_features : u64 ,
8989 acked_features : u64 ,
9090 config_space : Vec < u8 > ,
91+ pub ( crate ) activate_evt : EventFd ,
9192
9293 // Transport related fields.
9394 queues : Vec < Queue > ,
9495 interrupt_status : Arc < AtomicUsize > ,
9596 interrupt_evt : EventFd ,
9697 pub ( crate ) queue_evts : [ EventFd ; 1 ] ,
97- mem : GuestMemoryMmap ,
9898
99- device_activated : bool ,
99+ pub ( crate ) device_state : DeviceState ,
100100
101101 // Implementation specific fields.
102102 pub ( crate ) rate_limiter : RateLimiter ,
@@ -107,7 +107,6 @@ impl Block {
107107 ///
108108 /// The given file must be seekable and sizable.
109109 pub fn new (
110- mem : GuestMemoryMmap ,
111110 mut disk_image : File ,
112111 is_disk_read_only : bool ,
113112 rate_limiter : RateLimiter ,
@@ -132,12 +131,12 @@ impl Block {
132131 acked_features : 0u64 ,
133132 config_space : build_config_space ( disk_size) ,
134133 rate_limiter,
135- mem,
136134 interrupt_status : Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
137135 interrupt_evt : EventFd :: new ( libc:: EFD_NONBLOCK ) ?,
138136 queue_evts,
139137 queues,
140- device_activated : false ,
138+ device_state : DeviceState :: Inactive ,
139+ activate_evt : EventFd :: new ( libc:: EFD_NONBLOCK ) ?,
141140 } )
142141 }
143142
@@ -161,11 +160,16 @@ impl Block {
161160 }
162161
163162 pub ( crate ) fn process_queue ( & mut self , queue_index : usize ) -> bool {
163+ let mem = match self . device_state {
164+ DeviceState :: Activated ( ref mem) => mem,
165+ // This should never happen, it's been already validated in the event handler.
166+ DeviceState :: Inactive => unreachable ! ( ) ,
167+ } ;
164168 let queue = & mut self . queues [ queue_index] ;
165169 let mut used_any = false ;
166- while let Some ( head) = queue. pop ( & self . mem ) {
170+ while let Some ( head) = queue. pop ( mem) {
167171 let len;
168- match Request :: parse ( & head, & self . mem ) {
172+ match Request :: parse ( & head, mem) {
169173 Ok ( request) => {
170174 // If limiter.consume() fails it means there is no more TokenType::Ops
171175 // budget and rate limiting is in effect.
@@ -196,7 +200,7 @@ impl Block {
196200 let status = match request. execute (
197201 & mut self . disk_image ,
198202 self . disk_nsectors ,
199- & self . mem ,
203+ mem,
200204 & self . disk_image_id ,
201205 ) {
202206 Ok ( l) => {
@@ -212,15 +216,15 @@ impl Block {
212216 } ;
213217 // We use unwrap because the request parsing process already checked that the
214218 // status_addr was valid.
215- self . mem . write_obj ( status, request. status_addr ) . unwrap ( ) ;
219+ mem. write_obj ( status, request. status_addr ) . unwrap ( ) ;
216220 }
217221 Err ( e) => {
218222 error ! ( "Failed to parse available descriptor chain: {:?}" , e) ;
219223 METRICS . block . execute_fails . inc ( ) ;
220224 len = 0 ;
221225 }
222226 }
223- queue. add_used ( & self . mem , head. index , len) ;
227+ queue. add_used ( mem, head. index , len) ;
224228 used_any = true ;
225229 }
226230
@@ -318,17 +322,24 @@ impl VirtioDevice for Block {
318322 }
319323
320324 fn is_activated ( & self ) -> bool {
321- self . device_activated
325+ match self . device_state {
326+ DeviceState :: Inactive => false ,
327+ DeviceState :: Activated ( _) => true ,
328+ }
322329 }
323330
324- fn activate ( & mut self , _: GuestMemoryMmap ) -> ActivateResult {
325- self . device_activated = true ;
331+ fn activate ( & mut self , mem : GuestMemoryMmap ) -> ActivateResult {
332+ if self . activate_evt . write ( 1 ) . is_err ( ) {
333+ error ! ( "Block: Cannot write to activate_evt" ) ;
334+ return Err ( super :: super :: ActivateError :: BadActivate ) ;
335+ }
336+ self . device_state = DeviceState :: Activated ( mem) ;
326337 Ok ( ( ) )
327338 }
328339}
329340
330341#[ cfg( test) ]
331- mod tests {
342+ pub ( crate ) mod tests {
332343 use std:: fs:: metadata;
333344 use std:: os:: unix:: io:: AsRawFd ;
334345 use std:: thread;
@@ -352,7 +363,7 @@ mod tests {
352363 }
353364
354365 impl Block {
355- fn set_queue ( & mut self , idx : usize , q : Queue ) {
366+ pub ( crate ) fn set_queue ( & mut self , idx : usize , q : Queue ) {
356367 self . queues [ idx] = q;
357368 }
358369
@@ -366,7 +377,7 @@ mod tests {
366377 }
367378
368379 /// Create a default Block instance to be used in tests.
369- fn default_block ( ) -> Block {
380+ pub fn default_block ( ) -> Block {
370381 // Create backing file.
371382 let f = TempFile :: new ( ) . unwrap ( ) ;
372383 let block_file = f. into_file ( ) ;
@@ -375,12 +386,14 @@ mod tests {
375386 // Rate limiting is enabled but with a high operation rate (10 million ops/s).
376387 let rate_limiter = RateLimiter :: new ( 0 , None , 0 , 100_000 , None , 10 ) . unwrap ( ) ;
377388
378- let mem = GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , 0x10000 ) ] ) . unwrap ( ) ;
389+ Block :: new ( block_file, true , rate_limiter) . unwrap ( )
390+ }
379391
380- Block :: new ( mem, block_file, true , rate_limiter) . unwrap ( )
392+ pub fn default_mem ( ) -> GuestMemoryMmap {
393+ GuestMemoryMmap :: from_ranges ( & [ ( GuestAddress ( 0 ) , 0x10000 ) ] ) . unwrap ( )
381394 }
382395
383- fn initialize_virtqueue ( vq : & VirtQueue ) {
396+ pub fn initialize_virtqueue ( vq : & VirtQueue ) {
384397 let request_type_desc: usize = 0 ;
385398 let data_desc: usize = 1 ;
386399 let status_desc: usize = 2 ;
@@ -496,7 +509,7 @@ mod tests {
496509 #[ test]
497510 fn test_invalid_request ( ) {
498511 let mut block = default_block ( ) ;
499- let mem = block . mem . clone ( ) ;
512+ let mem = default_mem ( ) ;
500513 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
501514 block. set_queue ( 0 , vq. create_queue ( ) ) ;
502515 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
@@ -521,7 +534,7 @@ mod tests {
521534 #[ test]
522535 fn test_request_execute_failures ( ) {
523536 let mut block = default_block ( ) ;
524- let mem = block . mem . clone ( ) ;
537+ let mem = default_mem ( ) ;
525538 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
526539 block. set_queue ( 0 , vq. create_queue ( ) ) ;
527540 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
@@ -579,7 +592,7 @@ mod tests {
579592 #[ test]
580593 fn test_unsupported_request_type ( ) {
581594 let mut block = default_block ( ) ;
582- let mem = block . mem . clone ( ) ;
595+ let mem = default_mem ( ) ;
583596 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
584597 block. set_queue ( 0 , vq. create_queue ( ) ) ;
585598 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
@@ -609,7 +622,7 @@ mod tests {
609622 #[ test]
610623 fn test_read_write ( ) {
611624 let mut block = default_block ( ) ;
612- let mem = block . mem . clone ( ) ;
625+ let mem = default_mem ( ) ;
613626 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
614627 block. set_queue ( 0 , vq. create_queue ( ) ) ;
615628 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
@@ -668,7 +681,7 @@ mod tests {
668681 #[ test]
669682 fn test_flush ( ) {
670683 let mut block = default_block ( ) ;
671- let mem = block . mem . clone ( ) ;
684+ let mem = default_mem ( ) ;
672685 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
673686 block. set_queue ( 0 , vq. create_queue ( ) ) ;
674687 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
@@ -711,7 +724,7 @@ mod tests {
711724 #[ test]
712725 fn test_get_device_id ( ) {
713726 let mut block = default_block ( ) ;
714- let mem = block . mem . clone ( ) ;
727+ let mem = default_mem ( ) ;
715728 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
716729 block. set_queue ( 0 , vq. create_queue ( ) ) ;
717730 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
@@ -777,7 +790,7 @@ mod tests {
777790 #[ test]
778791 fn test_bandwidth_rate_limiter ( ) {
779792 let mut block = default_block ( ) ;
780- let mem = block . mem . clone ( ) ;
793+ let mem = default_mem ( ) ;
781794 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
782795 block. set_queue ( 0 , vq. create_queue ( ) ) ;
783796 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
@@ -842,7 +855,7 @@ mod tests {
842855 #[ test]
843856 fn test_ops_rate_limiter ( ) {
844857 let mut block = default_block ( ) ;
845- let mem = block . mem . clone ( ) ;
858+ let mem = default_mem ( ) ;
846859 let vq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
847860 block. set_queue ( 0 , vq. create_queue ( ) ) ;
848861 block. activate ( mem. clone ( ) ) . unwrap ( ) ;
0 commit comments