Skip to content

Commit a883358

Browse files
committed
feat(virtio-pmem): add snapshot support
Add logic to store and restore virtio-pmem device information in a snapshot. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent f954dba commit a883358

File tree

6 files changed

+272
-8
lines changed

6 files changed

+272
-8
lines changed

src/vmm/src/device_manager/pci_mngr.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use crate::devices::virtio::device::VirtioDevice;
2020
use crate::devices::virtio::generated::virtio_ids;
2121
use crate::devices::virtio::net::Net;
2222
use crate::devices::virtio::net::persist::{NetConstructorArgs, NetState};
23+
use crate::devices::virtio::pmem::device::Pmem;
24+
use crate::devices::virtio::pmem::persist::{PmemConstructorArgs, PmemState};
2325
use crate::devices::virtio::rng::Entropy;
2426
use crate::devices::virtio::rng::persist::{EntropyConstructorArgs, EntropyState};
2527
use crate::devices::virtio::transport::pci::device::{
@@ -238,6 +240,8 @@ pub struct PciDevicesState {
238240
pub mmds: Option<MmdsState>,
239241
/// Entropy device state.
240242
pub entropy_device: Option<VirtioDeviceState<EntropyState>>,
243+
/// Pmem device states.
244+
pub pmem_devices: Vec<VirtioDeviceState<PmemState>>,
241245
}
242246

243247
pub struct PciDevicesConstructorArgs<'a> {
@@ -386,6 +390,19 @@ impl<'a> Persist<'a> for PciDevices {
386390
transport_state,
387391
})
388392
}
393+
virtio_ids::VIRTIO_ID_PMEM => {
394+
let pmem_dev = locked_virtio_dev
395+
.as_mut_any()
396+
.downcast_mut::<Pmem>()
397+
.unwrap();
398+
let device_state = pmem_dev.save();
399+
state.pmem_devices.push(VirtioDeviceState {
400+
device_id: pmem_dev.config.id.clone(),
401+
pci_device_bdf,
402+
device_state,
403+
transport_state,
404+
});
405+
}
389406
_ => unreachable!(),
390407
}
391408
}
@@ -564,6 +581,34 @@ impl<'a> Persist<'a> for PciDevices {
564581
.unwrap()
565582
}
566583

584+
for pmem_state in &state.pmem_devices {
585+
let device = Arc::new(Mutex::new(
586+
Pmem::restore(
587+
PmemConstructorArgs {
588+
mem,
589+
vm: constructor_args.vm.as_ref(),
590+
},
591+
&pmem_state.device_state,
592+
)
593+
.unwrap(),
594+
));
595+
596+
constructor_args
597+
.vm_resources
598+
.update_from_restored_device(SharedDeviceType::Pmem(device.clone()))
599+
.unwrap();
600+
601+
pci_devices
602+
.restore_pci_device(
603+
constructor_args.vm,
604+
device,
605+
&pmem_state.device_id,
606+
&pmem_state.transport_state,
607+
constructor_args.event_manager,
608+
)
609+
.unwrap()
610+
}
611+
567612
Ok(pci_devices)
568613
}
569614
}
@@ -582,13 +627,15 @@ mod tests {
582627
use crate::vmm_config::balloon::BalloonDeviceConfig;
583628
use crate::vmm_config::entropy::EntropyDeviceConfig;
584629
use crate::vmm_config::net::NetworkInterfaceConfig;
630+
use crate::vmm_config::pmem::PmemConfig;
585631
use crate::vmm_config::vsock::VsockDeviceConfig;
586632

587633
#[test]
588634
fn test_device_manager_persistence() {
589635
let mut buf = vec![0; 65536];
590636
// These need to survive so the restored blocks find them.
591637
let _block_files;
638+
let _pmem_files;
592639
let mut tmp_sock_file = TempFile::new().unwrap();
593640
tmp_sock_file.remove().unwrap();
594641
// Set up a vmm with one of each device, and get the serialized DeviceStates.
@@ -642,6 +689,16 @@ mod tests {
642689
// Add an entropy device.
643690
let entropy_config = EntropyDeviceConfig::default();
644691
insert_entropy_device(&mut vmm, &mut cmdline, &mut event_manager, entropy_config);
692+
// Add a pmem device.
693+
let pmem_id = String::from("pmem");
694+
let pmem_configs = vec![PmemConfig {
695+
id: pmem_id,
696+
path_on_host: "".into(),
697+
root_device: true,
698+
read_only: true,
699+
}];
700+
_pmem_files =
701+
insert_pmem_devices(&mut vmm, &mut cmdline, &mut event_manager, pmem_configs);
645702

646703
Snapshot::new(vmm.device_manager.save())
647704
.save(&mut buf.as_mut_slice())
@@ -731,10 +788,18 @@ mod tests {
731788
"entropy": {{
732789
"rate_limiter": null
733790
}},
734-
"pmem": []
791+
"pmem": [
792+
{{
793+
"id": "pmem",
794+
"path_on_host": "{}",
795+
"root_device": true,
796+
"read_only": true
797+
}}
798+
]
735799
}}"#,
736800
_block_files.last().unwrap().as_path().to_str().unwrap(),
737-
tmp_sock_file.as_path().to_str().unwrap()
801+
tmp_sock_file.as_path().to_str().unwrap(),
802+
_pmem_files.last().unwrap().as_path().to_str().unwrap(),
738803
);
739804

740805
assert_eq!(

src/vmm/src/device_manager/persist.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ use crate::devices::virtio::net::persist::{
3030
NetConstructorArgs, NetPersistError as NetError, NetState,
3131
};
3232
use crate::devices::virtio::persist::{MmioTransportConstructorArgs, MmioTransportState};
33+
use crate::devices::virtio::pmem::device::Pmem;
34+
use crate::devices::virtio::pmem::persist::{
35+
PmemConstructorArgs, PmemPersistError as PmemError, PmemState,
36+
};
3337
use crate::devices::virtio::rng::Entropy;
3438
use crate::devices::virtio::rng::persist::{
3539
EntropyConstructorArgs, EntropyPersistError as EntropyError, EntropyState,
@@ -73,6 +77,8 @@ pub enum DevicePersistError {
7377
MmdsConfig(#[from] MmdsConfigError),
7478
/// Entropy: {0}
7579
Entropy(#[from] EntropyError),
80+
/// Pmem: {0}
81+
Pmem(#[from] PmemError),
7682
/// Resource misconfiguration: {0}. Is the snapshot file corrupted?
7783
ResourcesError(#[from] ResourcesError),
7884
/// Could not activate device: {0}
@@ -126,6 +132,8 @@ pub struct DeviceStates {
126132
pub mmds: Option<MmdsState>,
127133
/// Entropy device state.
128134
pub entropy_device: Option<VirtioDeviceState<EntropyState>>,
135+
/// Pmem device states.
136+
pub pmem_devices: Vec<VirtioDeviceState<PmemState>>,
129137
}
130138

131139
/// A type used to extract the concrete `Arc<Mutex<T>>` for each of the device
@@ -137,6 +145,7 @@ pub enum SharedDeviceType {
137145
Balloon(Arc<Mutex<Balloon>>),
138146
Vsock(Arc<Mutex<Vsock<VsockUnixBackend>>>),
139147
Entropy(Arc<Mutex<Entropy>>),
148+
Pmem(Arc<Mutex<Pmem>>),
140149
}
141150

142151
pub struct MMIODevManagerConstructorArgs<'a> {
@@ -336,6 +345,16 @@ impl<'a> Persist<'a> for MMIODeviceManager {
336345
device_info,
337346
});
338347
}
348+
virtio_ids::VIRTIO_ID_PMEM => {
349+
let pmem = locked_device.as_mut_any().downcast_mut::<Pmem>().unwrap();
350+
let device_state = pmem.save();
351+
states.pmem_devices.push(VirtioDeviceState {
352+
device_id,
353+
device_state,
354+
transport_state,
355+
device_info,
356+
})
357+
}
339358
_ => unreachable!(),
340359
};
341360

@@ -550,6 +569,31 @@ impl<'a> Persist<'a> for MMIODeviceManager {
550569
)?;
551570
}
552571

572+
for pmem_state in &state.pmem_devices {
573+
let device = Arc::new(Mutex::new(Pmem::restore(
574+
PmemConstructorArgs {
575+
mem,
576+
vm: vm.as_ref(),
577+
},
578+
&pmem_state.device_state,
579+
)?));
580+
581+
constructor_args
582+
.vm_resources
583+
.update_from_restored_device(SharedDeviceType::Pmem(device.clone()))?;
584+
585+
restore_helper(
586+
device.clone(),
587+
pmem_state.device_state.virtio_state.activated,
588+
false,
589+
device,
590+
&pmem_state.device_id,
591+
&pmem_state.transport_state,
592+
&pmem_state.device_info,
593+
constructor_args.event_manager,
594+
)?;
595+
}
596+
553597
Ok(dev_manager)
554598
}
555599
}
@@ -567,6 +611,7 @@ mod tests {
567611
use crate::vmm_config::balloon::BalloonDeviceConfig;
568612
use crate::vmm_config::entropy::EntropyDeviceConfig;
569613
use crate::vmm_config::net::NetworkInterfaceConfig;
614+
use crate::vmm_config::pmem::PmemConfig;
570615
use crate::vmm_config::vsock::VsockDeviceConfig;
571616

572617
impl<T> PartialEq for VirtioDeviceState<T> {
@@ -614,6 +659,7 @@ mod tests {
614659
let mut buf = vec![0; 65536];
615660
// These need to survive so the restored blocks find them.
616661
let _block_files;
662+
let _pmem_files;
617663
let mut tmp_sock_file = TempFile::new().unwrap();
618664
tmp_sock_file.remove().unwrap();
619665
// Set up a vmm with one of each device, and get the serialized DeviceStates.
@@ -666,6 +712,16 @@ mod tests {
666712
// Add an entropy device.
667713
let entropy_config = EntropyDeviceConfig::default();
668714
insert_entropy_device(&mut vmm, &mut cmdline, &mut event_manager, entropy_config);
715+
// Add a pmem device.
716+
let pmem_id = String::from("pmem");
717+
let pmem_configs = vec![PmemConfig {
718+
id: pmem_id,
719+
path_on_host: "".into(),
720+
root_device: true,
721+
read_only: true,
722+
}];
723+
_pmem_files =
724+
insert_pmem_devices(&mut vmm, &mut cmdline, &mut event_manager, pmem_configs);
669725

670726
Snapshot::new(vmm.device_manager.save())
671727
.save(&mut buf.as_mut_slice())
@@ -751,10 +807,18 @@ mod tests {
751807
"entropy": {{
752808
"rate_limiter": null
753809
}},
754-
"pmem": []
810+
"pmem": [
811+
{{
812+
"id": "pmem",
813+
"path_on_host": "{}",
814+
"root_device": true,
815+
"read_only": true
816+
}}
817+
]
755818
}}"#,
756819
_block_files.last().unwrap().as_path().to_str().unwrap(),
757-
tmp_sock_file.as_path().to_str().unwrap()
820+
tmp_sock_file.as_path().to_str().unwrap(),
821+
_pmem_files.last().unwrap().as_path().to_str().unwrap(),
758822
);
759823

760824
assert_eq!(

src/vmm/src/devices/virtio/pmem/device.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const VIRTIO_PMEM_REQ_TYPE_FLUSH: u32 = 0;
6060
const SUCCESS: i32 = 0;
6161
const FAILURE: i32 = -1;
6262

63-
#[derive(Debug, Default, Copy, Clone)]
63+
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
6464
#[repr(C)]
6565
pub struct ConfigSpace {
6666
// Physical address of the first byte of the persistent memory region.

src/vmm/src/devices/virtio/pmem/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
pub mod device;
55
pub mod event_handler;
66
pub mod metrics;
7+
pub mod persist;
8+
9+
pub const PMEM_NUM_QUEUES: usize = 1;
10+
pub const PMEM_QUEUE_SIZE: u16 = 256;

0 commit comments

Comments
 (0)