@@ -8,7 +8,7 @@ use std::sync::{Arc, Mutex};
8
8
9
9
use event_manager:: { MutEventSubscriber , SubscriberOps } ;
10
10
use kvm_ioctls:: VmFd ;
11
- use log:: error;
11
+ use log:: { error, warn } ;
12
12
use snapshot:: Persist ;
13
13
use versionize:: { VersionMap , Versionize , VersionizeError , VersionizeResult } ;
14
14
use versionize_derive:: Versionize ;
@@ -30,12 +30,17 @@ use crate::devices::virtio::rng::persist::{
30
30
EntropyConstructorArgs , EntropyPersistError as EntropyError , EntropyState ,
31
31
} ;
32
32
use crate :: devices:: virtio:: rng:: Entropy ;
33
+ use crate :: devices:: virtio:: vhost_user_block:: device:: VhostUserBlock ;
34
+ use crate :: devices:: virtio:: vhost_user_block:: persist:: {
35
+ VhostUserBlockConstructorArgs , VhostUserBlockState ,
36
+ } ;
33
37
use crate :: devices:: virtio:: vsock:: persist:: {
34
38
VsockConstructorArgs , VsockState , VsockUdsConstructorArgs ,
35
39
} ;
36
40
use crate :: devices:: virtio:: vsock:: { Vsock , VsockError , VsockUnixBackend , VsockUnixBackendError } ;
37
41
use crate :: devices:: virtio:: {
38
- MmioTransport , VirtioDevice , TYPE_BALLOON , TYPE_BLOCK , TYPE_NET , TYPE_RNG , TYPE_VSOCK ,
42
+ MmioTransport , VhostUserBlockError , VirtioDevice , TYPE_BALLOON , TYPE_BLOCK , TYPE_NET , TYPE_RNG ,
43
+ TYPE_VSOCK ,
39
44
} ;
40
45
#[ cfg( target_arch = "aarch64" ) ]
41
46
use crate :: logger;
@@ -49,7 +54,8 @@ use crate::EventManager;
49
54
#[ derive( Debug , derive_more:: From ) ]
50
55
pub enum DevicePersistError {
51
56
Balloon ( BalloonError ) ,
52
- Block ( VirtioBlockError ) ,
57
+ VirtioBlock ( VirtioBlockError ) ,
58
+ VhostUserBlock ( VhostUserBlockError ) ,
53
59
DeviceManager ( super :: mmio:: MmioError ) ,
54
60
MmioTransport ,
55
61
#[ cfg( target_arch = "aarch64" ) ]
@@ -75,10 +81,10 @@ pub struct ConnectedBalloonState {
75
81
pub device_info : MMIODeviceInfo ,
76
82
}
77
83
78
- /// Holds the state of a block device connected to the MMIO space.
84
+ /// Holds the state of a virtio block device connected to the MMIO space.
79
85
// NOTICE: Any changes to this structure require a snapshot version bump.
80
86
#[ derive( Debug , Clone , Versionize ) ]
81
- pub struct ConnectedBlockState {
87
+ pub struct ConnectedVirtioBlockState {
82
88
/// Device identifier.
83
89
pub device_id : String ,
84
90
/// Device state.
@@ -89,6 +95,20 @@ pub struct ConnectedBlockState {
89
95
pub device_info : MMIODeviceInfo ,
90
96
}
91
97
98
+ /// Holds the state of a vhost-user block device connected to the MMIO space.
99
+ // NOTICE: Any changes to this structure require a snapshot version bump.
100
+ #[ derive( Debug , Clone , Versionize ) ]
101
+ pub struct ConnectedVhostUserBlockState {
102
+ /// Device identifier.
103
+ pub device_id : String ,
104
+ /// Device state.
105
+ pub device_state : VhostUserBlockState ,
106
+ /// Mmio transport state.
107
+ pub transport_state : MmioTransportState ,
108
+ /// VmmResources.
109
+ pub device_info : MMIODeviceInfo ,
110
+ }
111
+
92
112
/// Holds the state of a net device connected to the MMIO space.
93
113
// NOTICE: Any changes to this structure require a snapshot version bump.
94
114
#[ derive( Debug , Clone , Versionize ) ]
@@ -174,8 +194,11 @@ pub struct DeviceStates {
174
194
#[ cfg( target_arch = "aarch64" ) ]
175
195
// State of legacy devices in MMIO space.
176
196
pub legacy_devices : Vec < ConnectedLegacyState > ,
177
- /// Block device states.
178
- pub block_devices : Vec < ConnectedBlockState > ,
197
+ /// Virtio block device states.
198
+ pub virtio_block_devices : Vec < ConnectedVirtioBlockState > ,
199
+ /// Vhost-user block device states.
200
+ #[ version( start = 5 , de_fn = "de_vhost_user_block" ) ]
201
+ pub vhost_user_block_devices : Vec < ConnectedVhostUserBlockState > ,
179
202
/// Net device states.
180
203
pub net_devices : Vec < ConnectedNetState > ,
181
204
/// Vsock device state.
@@ -195,13 +218,23 @@ pub struct DeviceStates {
195
218
/// from a snapshot.
196
219
#[ derive( Debug ) ]
197
220
pub enum SharedDeviceType {
198
- Block ( Arc < Mutex < VirtioBlock > > ) ,
221
+ VirtioBlock ( Arc < Mutex < VirtioBlock > > ) ,
222
+ VhostUserBlock ( Arc < Mutex < VhostUserBlock > > ) ,
199
223
Network ( Arc < Mutex < Net > > ) ,
200
224
Balloon ( Arc < Mutex < Balloon > > ) ,
201
225
Vsock ( Arc < Mutex < Vsock < VsockUnixBackend > > > ) ,
202
226
Entropy ( Arc < Mutex < Entropy > > ) ,
203
227
}
204
228
229
+ impl DeviceStates {
230
+ fn de_vhost_user_block ( & mut self , source_version : u16 ) -> VersionizeResult < ( ) > {
231
+ if source_version < 5 {
232
+ self . vhost_user_block_devices = vec ! [ ] ;
233
+ }
234
+
235
+ Ok ( ( ) )
236
+ }
237
+ }
205
238
pub struct MMIODevManagerConstructorArgs < ' a > {
206
239
pub mem : GuestMemoryMmap ,
207
240
pub vm : & ' a VmFd ,
@@ -229,16 +262,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
229
262
type Error = DevicePersistError ;
230
263
231
264
fn save ( & self ) -> Self :: State {
232
- let mut states = DeviceStates {
233
- balloon_device : None ,
234
- block_devices : Vec :: new ( ) ,
235
- net_devices : Vec :: new ( ) ,
236
- vsock_device : None ,
237
- #[ cfg( target_arch = "aarch64" ) ]
238
- legacy_devices : Vec :: new ( ) ,
239
- mmds_version : None ,
240
- entropy_device : None ,
241
- } ;
265
+ let mut states = DeviceStates :: default ( ) ;
242
266
let _: Result < ( ) , ( ) > = self . for_each_device ( |devtype, devid, device_info, bus_dev| {
243
267
if * devtype == crate :: arch:: DeviceType :: BootTimer {
244
268
// No need to save BootTimer state.
@@ -279,18 +303,22 @@ impl<'a> Persist<'a> for MMIODeviceManager {
279
303
device_info : device_info. clone ( ) ,
280
304
} ) ;
281
305
}
306
+ // Both virtio-block and vhost-user-block share same device type.
282
307
TYPE_BLOCK => {
283
- let block = locked_device
284
- . as_mut_any ( )
285
- . downcast_mut :: < VirtioBlock > ( )
286
- . unwrap ( ) ;
287
- block. prepare_save ( ) ;
288
- states. block_devices . push ( ConnectedBlockState {
289
- device_id : devid. clone ( ) ,
290
- device_state : block. save ( ) ,
291
- transport_state,
292
- device_info : device_info. clone ( ) ,
293
- } ) ;
308
+ if let Some ( block) = locked_device. as_mut_any ( ) . downcast_mut :: < VirtioBlock > ( ) {
309
+ block. prepare_save ( ) ;
310
+ states. virtio_block_devices . push ( ConnectedVirtioBlockState {
311
+ device_id : devid. clone ( ) ,
312
+ device_state : block. save ( ) ,
313
+ transport_state,
314
+ device_info : device_info. clone ( ) ,
315
+ } )
316
+ } else {
317
+ warn ! (
318
+ "Skipping vhost-user-block device. VhostUserBlock does not support \
319
+ snapshotting yet"
320
+ ) ;
321
+ }
294
322
}
295
323
TYPE_NET => {
296
324
let net = locked_device. as_any ( ) . downcast_ref :: < Net > ( ) . unwrap ( ) ;
@@ -477,23 +505,44 @@ impl<'a> Persist<'a> for MMIODeviceManager {
477
505
) ?;
478
506
}
479
507
480
- for block_state in & state. block_devices {
508
+ for virtio_block_state in & state. virtio_block_devices {
481
509
let device = Arc :: new ( Mutex :: new ( VirtioBlock :: restore (
482
510
VirtioBlockConstructorArgs { mem : mem. clone ( ) } ,
483
- & block_state. device_state ,
511
+ & virtio_block_state. device_state ,
512
+ ) ?) ) ;
513
+
514
+ ( constructor_args. for_each_restored_device ) (
515
+ constructor_args. vm_resources ,
516
+ SharedDeviceType :: VirtioBlock ( device. clone ( ) ) ,
517
+ ) ;
518
+
519
+ restore_helper (
520
+ device. clone ( ) ,
521
+ device,
522
+ & virtio_block_state. device_id ,
523
+ & virtio_block_state. transport_state ,
524
+ & virtio_block_state. device_info ,
525
+ constructor_args. event_manager ,
526
+ ) ?;
527
+ }
528
+
529
+ for vhost_user_block_state in & state. vhost_user_block_devices {
530
+ let device = Arc :: new ( Mutex :: new ( VhostUserBlock :: restore (
531
+ VhostUserBlockConstructorArgs { mem : mem. clone ( ) } ,
532
+ & vhost_user_block_state. device_state ,
484
533
) ?) ) ;
485
534
486
535
( constructor_args. for_each_restored_device ) (
487
536
constructor_args. vm_resources ,
488
- SharedDeviceType :: Block ( device. clone ( ) ) ,
537
+ SharedDeviceType :: VhostUserBlock ( device. clone ( ) ) ,
489
538
) ;
490
539
491
540
restore_helper (
492
541
device. clone ( ) ,
493
542
device,
494
- & block_state . device_id ,
495
- & block_state . transport_state ,
496
- & block_state . device_info ,
543
+ & vhost_user_block_state . device_id ,
544
+ & vhost_user_block_state . transport_state ,
545
+ & vhost_user_block_state . device_info ,
497
546
constructor_args. event_manager ,
498
547
) ?;
499
548
}
@@ -619,8 +668,8 @@ mod tests {
619
668
}
620
669
}
621
670
622
- impl PartialEq for ConnectedBlockState {
623
- fn eq ( & self , other : & ConnectedBlockState ) -> bool {
671
+ impl PartialEq for ConnectedVirtioBlockState {
672
+ fn eq ( & self , other : & ConnectedVirtioBlockState ) -> bool {
624
673
// Actual device state equality is checked by the device's tests.
625
674
self . transport_state == other. transport_state && self . device_info == other. device_info
626
675
}
@@ -643,7 +692,7 @@ mod tests {
643
692
impl PartialEq for DeviceStates {
644
693
fn eq ( & self , other : & DeviceStates ) -> bool {
645
694
self . balloon_device == other. balloon_device
646
- && self . block_devices == other. block_devices
695
+ && self . virtio_block_devices == other. virtio_block_devices
647
696
&& self . net_devices == other. net_devices
648
697
&& self . vsock_device == other. vsock_device
649
698
}
0 commit comments