vmm: Directly (de)serialise CpuManager, DeviceManager and MemoryManager state

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford
2021-04-14 16:50:29 +01:00
committed by Sebastien Boeuf
parent 85f7913bb3
commit a7c4483b8b
3 changed files with 36 additions and 94 deletions

View File

@@ -365,41 +365,18 @@ impl Snapshottable for Vcpu {
} }
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
let snapshot = serde_json::to_vec(&self.saved_state)
.map_err(|e| MigratableError::Snapshot(e.into()))?;
let mut vcpu_snapshot = Snapshot::new(&format!("{}", self.id)); let mut vcpu_snapshot = Snapshot::new(&format!("{}", self.id));
vcpu_snapshot.add_data_section(SnapshotDataSection { vcpu_snapshot.add_data_section(SnapshotDataSection::new_from_state(
id: format!("{}-section", VCPU_SNAPSHOT_ID), VCPU_SNAPSHOT_ID,
snapshot, &self.saved_state,
}); )?);
Ok(vcpu_snapshot) Ok(vcpu_snapshot)
} }
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
if let Some(vcpu_section) = snapshot self.saved_state = Some(snapshot.to_state(VCPU_SNAPSHOT_ID)?);
.snapshot_data Ok(())
.get(&format!("{}-section", VCPU_SNAPSHOT_ID))
{
let vcpu_state = match serde_json::from_slice(&vcpu_section.snapshot) {
Ok(state) => state,
Err(error) => {
return Err(MigratableError::Restore(anyhow!(
"Could not deserialize the vCPU snapshot {}",
error
)))
}
};
self.saved_state = Some(vcpu_state);
Ok(())
} else {
Err(MigratableError::Restore(anyhow!(
"Could not find the vCPU snapshot section"
)))
}
} }
} }

View File

@@ -3869,32 +3869,18 @@ impl Snapshottable for DeviceManager {
} }
// Then we store the DeviceManager state. // Then we store the DeviceManager state.
snapshot.add_data_section(SnapshotDataSection { snapshot.add_data_section(SnapshotDataSection::new_from_state(
id: format!("{}-section", DEVICE_MANAGER_SNAPSHOT_ID), DEVICE_MANAGER_SNAPSHOT_ID,
snapshot: serde_json::to_vec(&self.state()) &self.state(),
.map_err(|e| MigratableError::Snapshot(e.into()))?, )?);
});
Ok(snapshot) Ok(snapshot)
} }
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
// Let's first restore the DeviceManager. // Let's first restore the DeviceManager.
if let Some(device_manager_section) = snapshot
.snapshot_data
.get(&format!("{}-section", DEVICE_MANAGER_SNAPSHOT_ID))
{
let device_manager_state = serde_json::from_slice(&device_manager_section.snapshot)
.map_err(|e| {
MigratableError::Restore(anyhow!("Could not deserialize DeviceManager {}", e))
})?;
self.set_state(&device_manager_state); self.set_state(&snapshot.to_state(DEVICE_MANAGER_SNAPSHOT_ID)?);
} else {
return Err(MigratableError::Restore(anyhow!(
"Could not find DeviceManager snapshot section"
)));
}
// Now that DeviceManager is updated with the right states, it's time // Now that DeviceManager is updated with the right states, it's time
// to create the devices based on the configuration. // to create the devices based on the configuration.

View File

@@ -853,47 +853,30 @@ impl MemoryManager {
if let Some(source_url) = source_url { if let Some(source_url) = source_url {
let vm_snapshot_path = url_to_path(source_url).map_err(Error::Restore)?; let vm_snapshot_path = url_to_path(source_url).map_err(Error::Restore)?;
if let Some(mem_section) = snapshot let mem_snapshot: MemoryManagerSnapshotData = snapshot
.snapshot_data .to_state(MEMORY_MANAGER_SNAPSHOT_ID)
.get(&format!("{}-section", MEMORY_MANAGER_SNAPSHOT_ID)) .map_err(Error::Restore)?;
{
let mem_snapshot: MemoryManagerSnapshotData =
match serde_json::from_slice(&mem_section.snapshot) {
Ok(snapshot) => snapshot,
Err(error) => {
return Err(Error::Restore(MigratableError::Restore(anyhow!(
"Could not deserialize MemoryManager {}",
error
))))
}
};
// Here we turn the content file name into a content file path as // Here we turn the content file name into a content file path as
// this will be needed to copy the content of the saved memory // this will be needed to copy the content of the saved memory
// region into the newly created memory region. // region into the newly created memory region.
// We simply ignore the content files that are None, as they // We simply ignore the content files that are None, as they
// represent regions that have been directly saved by the user, with // represent regions that have been directly saved by the user, with
// no need for saving into a dedicated external file. For these // no need for saving into a dedicated external file. For these
// files, the VmConfig already contains the information on where to // files, the VmConfig already contains the information on where to
// find them. // find them.
let mut saved_regions = mem_snapshot.memory_regions; let mut saved_regions = mem_snapshot.memory_regions;
for region in saved_regions.iter_mut() { for region in saved_regions.iter_mut() {
if let Some(content) = &mut region.content { if let Some(content) = &mut region.content {
let mut memory_region_path = vm_snapshot_path.clone(); let mut memory_region_path = vm_snapshot_path.clone();
memory_region_path.push(content.clone()); memory_region_path.push(content.clone());
*content = memory_region_path; *content = memory_region_path;
}
} }
mm.lock().unwrap().fill_saved_regions(saved_regions)?;
Ok(mm)
} else {
Err(Error::Restore(MigratableError::Restore(anyhow!(
"Could not find {}-section from snapshot",
MEMORY_MANAGER_SNAPSHOT_ID
))))
} }
mm.lock().unwrap().fill_saved_regions(saved_regions)?;
Ok(mm)
} else { } else {
Ok(mm) Ok(mm)
} }
@@ -2009,14 +1992,10 @@ impl Snapshottable for MemoryManager {
// memory region content for the regions requiring it. // memory region content for the regions requiring it.
self.snapshot_memory_regions = memory_regions.clone(); self.snapshot_memory_regions = memory_regions.clone();
let snapshot_data_section = memory_manager_snapshot.add_data_section(SnapshotDataSection::new_from_state(
serde_json::to_vec(&MemoryManagerSnapshotData { memory_regions }) MEMORY_MANAGER_SNAPSHOT_ID,
.map_err(|e| MigratableError::Snapshot(e.into()))?; &MemoryManagerSnapshotData { memory_regions },
)?);
memory_manager_snapshot.add_data_section(SnapshotDataSection {
id: format!("{}-section", MEMORY_MANAGER_SNAPSHOT_ID),
snapshot: snapshot_data_section,
});
let mut memory_snapshot = self.snapshot.lock().unwrap(); let mut memory_snapshot = self.snapshot.lock().unwrap();
*memory_snapshot = Some(guest_memory); *memory_snapshot = Some(guest_memory);