11// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22// SPDX-License-Identifier: Apache-2.0
33
4- use std:: fmt ;
4+ use std:: sync :: Arc ;
55use std:: time:: Duration ;
66
77use log:: error;
@@ -149,6 +149,7 @@ impl BalloonStats {
149149 }
150150}
151151
152+ #[ derive( Debug ) ]
152153/// Virtio balloon device.
153154pub struct Balloon {
154155 // Virtio fields.
@@ -161,7 +162,6 @@ pub struct Balloon {
161162 pub ( crate ) queues : Vec < Queue > ,
162163 pub ( crate ) queue_evts : [ EventFd ; BALLOON_NUM_QUEUES ] ,
163164 pub ( crate ) device_state : DeviceState ,
164- pub ( crate ) irq_trigger : IrqTrigger ,
165165
166166 // Implementation specific fields.
167167 pub ( crate ) restored_from_file : bool ,
@@ -175,29 +175,6 @@ pub struct Balloon {
175175 pub ( crate ) pfn_buffer : [ u32 ; MAX_PAGE_COMPACT_BUFFER ] ,
176176}
177177
178- // TODO Use `#[derive(Debug)]` when a new release of
179- // [rust-timerfd](https://github.com/main--/rust-timerfd) is published that includes
180- // https://github.com/main--/rust-timerfd/pull/12.
181- impl fmt:: Debug for Balloon {
182- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
183- f. debug_struct ( "Balloon" )
184- . field ( "avail_features" , & self . avail_features )
185- . field ( "acked_features" , & self . acked_features )
186- . field ( "config_space" , & self . config_space )
187- . field ( "activate_evt" , & self . activate_evt )
188- . field ( "queues" , & self . queues )
189- . field ( "queue_evts" , & self . queue_evts )
190- . field ( "device_state" , & self . device_state )
191- . field ( "irq_trigger" , & self . irq_trigger )
192- . field ( "restored_from_file" , & self . restored_from_file )
193- . field ( "stats_polling_interval_s" , & self . stats_polling_interval_s )
194- . field ( "stats_desc_index" , & self . stats_desc_index )
195- . field ( "latest_stats" , & self . latest_stats )
196- . field ( "pfn_buffer" , & self . pfn_buffer )
197- . finish ( )
198- }
199- }
200-
201178impl Balloon {
202179 /// Instantiate a new balloon device.
203180 pub fn new (
@@ -242,7 +219,6 @@ impl Balloon {
242219 } ,
243220 queue_evts,
244221 queues,
245- irq_trigger : IrqTrigger :: new ( ) . map_err ( BalloonError :: EventFd ) ?,
246222 device_state : DeviceState :: Inactive ,
247223 activate_evt : EventFd :: new ( libc:: EFD_NONBLOCK ) . map_err ( BalloonError :: EventFd ) ?,
248224 restored_from_file,
@@ -282,7 +258,7 @@ impl Balloon {
282258
283259 pub ( crate ) fn process_inflate ( & mut self ) -> Result < ( ) , BalloonError > {
284260 // This is safe since we checked in the event handler that the device is activated.
285- let mem = self . device_state . mem ( ) . unwrap ( ) ;
261+ let ( mem, _ ) = self . device_state . active_state ( ) . unwrap ( ) ;
286262 METRICS . inflate_count . inc ( ) ;
287263
288264 let queue = & mut self . queues [ INFLATE_INDEX ] ;
@@ -389,7 +365,7 @@ impl Balloon {
389365
390366 pub ( crate ) fn process_stats_queue ( & mut self ) -> Result < ( ) , BalloonError > {
391367 // This is safe since we checked in the event handler that the device is activated.
392- let mem = self . device_state . mem ( ) . unwrap ( ) ;
368+ let ( mem, _ ) = self . device_state . active_state ( ) . unwrap ( ) ;
393369 METRICS . stats_updates_count . inc ( ) ;
394370
395371 while let Some ( head) = self . queues [ STATS_INDEX ] . pop ( ) {
@@ -426,10 +402,12 @@ impl Balloon {
426402 }
427403
428404 pub ( crate ) fn signal_used_queue ( & self ) -> Result < ( ) , BalloonError > {
429- self . irq_trigger . trigger_irq ( IrqType :: Vring ) . map_err ( |err| {
430- METRICS . event_fails . inc ( ) ;
431- BalloonError :: InterruptError ( err)
432- } )
405+ self . interrupt_trigger ( )
406+ . trigger_irq ( IrqType :: Vring )
407+ . map_err ( |err| {
408+ METRICS . event_fails . inc ( ) ;
409+ BalloonError :: InterruptError ( err)
410+ } )
433411 }
434412
435413 /// Process device virtio queue(s).
@@ -461,7 +439,7 @@ impl Balloon {
461439 pub fn update_size ( & mut self , amount_mib : u32 ) -> Result < ( ) , BalloonError > {
462440 if self . is_activated ( ) {
463441 self . config_space . num_pages = mib_to_pages ( amount_mib) ?;
464- self . irq_trigger
442+ self . interrupt_trigger ( )
465443 . trigger_irq ( IrqType :: Config )
466444 . map_err ( BalloonError :: InterruptError )
467445 } else {
@@ -573,8 +551,11 @@ impl VirtioDevice for Balloon {
573551 & self . queue_evts
574552 }
575553
576- fn interrupt_trigger ( & self ) -> & IrqTrigger {
577- & self . irq_trigger
554+ fn interrupt_trigger ( & self ) -> Arc < IrqTrigger > {
555+ self . device_state
556+ . active_state ( )
557+ . expect ( "Device is not activated" )
558+ . 1
578559 }
579560
580561 fn read_config ( & self , offset : u64 , data : & mut [ u8 ] ) {
@@ -601,13 +582,17 @@ impl VirtioDevice for Balloon {
601582 dst. copy_from_slice ( data) ;
602583 }
603584
604- fn activate ( & mut self , mem : GuestMemoryMmap ) -> Result < ( ) , ActivateError > {
585+ fn activate (
586+ & mut self ,
587+ mem : GuestMemoryMmap ,
588+ interrupt : Arc < IrqTrigger > ,
589+ ) -> Result < ( ) , ActivateError > {
605590 for q in self . queues . iter_mut ( ) {
606591 q. initialize ( & mem)
607592 . map_err ( ActivateError :: QueueMemoryError ) ?;
608593 }
609594
610- self . device_state = DeviceState :: Activated ( mem) ;
595+ self . device_state = DeviceState :: Activated ( ( mem, interrupt ) ) ;
611596 if self . activate_evt . write ( 1 ) . is_err ( ) {
612597 METRICS . activate_fails . inc ( ) ;
613598 self . device_state = DeviceState :: Inactive ;
@@ -813,10 +798,11 @@ pub(crate) mod tests {
813798 fn test_invalid_request ( ) {
814799 let mut balloon = Balloon :: new ( 0 , true , 0 , false ) . unwrap ( ) ;
815800 let mem = default_mem ( ) ;
801+ let interrupt = Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ;
816802 // Only initialize the inflate queue to demonstrate invalid request handling.
817803 let infq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
818804 balloon. set_queue ( INFLATE_INDEX , infq. create_queue ( ) ) ;
819- balloon. activate ( mem. clone ( ) ) . unwrap ( ) ;
805+ balloon. activate ( mem. clone ( ) , interrupt ) . unwrap ( ) ;
820806
821807 // Fill the second page with non-zero bytes.
822808 for i in 0 ..0x1000 {
@@ -872,9 +858,10 @@ pub(crate) mod tests {
872858 fn test_inflate ( ) {
873859 let mut balloon = Balloon :: new ( 0 , true , 0 , false ) . unwrap ( ) ;
874860 let mem = default_mem ( ) ;
861+ let interrupt = Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ;
875862 let infq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
876863 balloon. set_queue ( INFLATE_INDEX , infq. create_queue ( ) ) ;
877- balloon. activate ( mem. clone ( ) ) . unwrap ( ) ;
864+ balloon. activate ( mem. clone ( ) , interrupt ) . unwrap ( ) ;
878865
879866 // Fill the third page with non-zero bytes.
880867 for i in 0 ..0x1000 {
@@ -942,9 +929,10 @@ pub(crate) mod tests {
942929 fn test_deflate ( ) {
943930 let mut balloon = Balloon :: new ( 0 , true , 0 , false ) . unwrap ( ) ;
944931 let mem = default_mem ( ) ;
932+ let interrupt = Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ;
945933 let defq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
946934 balloon. set_queue ( DEFLATE_INDEX , defq. create_queue ( ) ) ;
947- balloon. activate ( mem. clone ( ) ) . unwrap ( ) ;
935+ balloon. activate ( mem. clone ( ) , interrupt ) . unwrap ( ) ;
948936
949937 let page_addr = 0x10 ;
950938
@@ -990,9 +978,10 @@ pub(crate) mod tests {
990978 fn test_stats ( ) {
991979 let mut balloon = Balloon :: new ( 0 , true , 1 , false ) . unwrap ( ) ;
992980 let mem = default_mem ( ) ;
981+ let interrupt = Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ;
993982 let statsq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
994983 balloon. set_queue ( STATS_INDEX , statsq. create_queue ( ) ) ;
995- balloon. activate ( mem. clone ( ) ) . unwrap ( ) ;
984+ balloon. activate ( mem. clone ( ) , interrupt ) . unwrap ( ) ;
996985
997986 let page_addr = 0x100 ;
998987
@@ -1068,7 +1057,7 @@ pub(crate) mod tests {
10681057 assert!( balloon. stats_desc_index. is_some( ) ) ;
10691058 balloon. process_stats_timer_event( ) . unwrap( ) ;
10701059 assert!( balloon. stats_desc_index. is_none( ) ) ;
1071- assert!( balloon. irq_trigger . has_pending_irq( IrqType :: Vring ) ) ;
1060+ assert!( balloon. interrupt_trigger ( ) . has_pending_irq( IrqType :: Vring ) ) ;
10721061 } ) ;
10731062 }
10741063 }
@@ -1077,21 +1066,23 @@ pub(crate) mod tests {
10771066 fn test_process_balloon_queues ( ) {
10781067 let mut balloon = Balloon :: new ( 0x10 , true , 0 , false ) . unwrap ( ) ;
10791068 let mem = default_mem ( ) ;
1069+ let interrupt = Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ;
10801070 let infq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
10811071 let defq = VirtQueue :: new ( GuestAddress ( 0 ) , & mem, 16 ) ;
10821072
10831073 balloon. set_queue ( INFLATE_INDEX , infq. create_queue ( ) ) ;
10841074 balloon. set_queue ( DEFLATE_INDEX , defq. create_queue ( ) ) ;
10851075
1086- balloon. activate ( mem) . unwrap ( ) ;
1076+ balloon. activate ( mem, interrupt ) . unwrap ( ) ;
10871077 balloon. process_virtio_queues ( )
10881078 }
10891079
10901080 #[ test]
10911081 fn test_update_stats_interval ( ) {
10921082 let mut balloon = Balloon :: new ( 0 , true , 0 , false ) . unwrap ( ) ;
10931083 let mem = default_mem ( ) ;
1094- balloon. activate ( mem) . unwrap ( ) ;
1084+ let interrupt = Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ;
1085+ balloon. activate ( mem, interrupt) . unwrap ( ) ;
10951086 assert_eq ! (
10961087 format!( "{:?}" , balloon. update_stats_polling_interval( 1 ) ) ,
10971088 "Err(StatisticsStateChange)"
@@ -1100,7 +1091,8 @@ pub(crate) mod tests {
11001091
11011092 let mut balloon = Balloon :: new ( 0 , true , 1 , false ) . unwrap ( ) ;
11021093 let mem = default_mem ( ) ;
1103- balloon. activate ( mem) . unwrap ( ) ;
1094+ let interrupt = Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ;
1095+ balloon. activate ( mem, interrupt) . unwrap ( ) ;
11041096 assert_eq ! (
11051097 format!( "{:?}" , balloon. update_stats_polling_interval( 0 ) ) ,
11061098 "Err(StatisticsStateChange)"
@@ -1120,7 +1112,8 @@ pub(crate) mod tests {
11201112 fn test_num_pages ( ) {
11211113 let mut balloon = Balloon :: new ( 0 , true , 0 , false ) . unwrap ( ) ;
11221114 // Switch the state to active.
1123- balloon. device_state = DeviceState :: Activated ( single_region_mem ( 0x1 ) ) ;
1115+ balloon. device_state =
1116+ DeviceState :: Activated ( ( single_region_mem ( 0x1 ) , Arc :: new ( IrqTrigger :: new ( ) . unwrap ( ) ) ) ) ;
11241117
11251118 assert_eq ! ( balloon. num_pages( ) , 0 ) ;
11261119 assert_eq ! ( balloon. actual_pages( ) , 0 ) ;
0 commit comments