mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
vmm: memory: Restore with Copy-on-Write when possible
This patch extends the previous behavior on the restore codepath. Instead of copying the memory regions content from the snapshot files into the new memory regions, the VMM will use the snapshot region files as the backing files behind each mapped region. This is done in order to reduce the time for the VM to be restored. When the source VM has been initially started with a backing file, this means it has been mapped with the MAP_SHARED flag. For this case, we cannot use the CoW trick to speed up the VM restore path and we simply fallback onto the copy of the memory regions content. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
d771223b2f
commit
b2cdee80b6
@ -384,8 +384,6 @@ impl MemoryManager {
|
||||
config: &MemoryConfig,
|
||||
source_url: &str,
|
||||
) -> Result<Arc<Mutex<MemoryManager>>, Error> {
|
||||
let memory_manager = MemoryManager::new(fd, config, None)?;
|
||||
|
||||
let url = Url::parse(source_url).unwrap();
|
||||
/* url must be valid dir which is verified in recv_vm_snapshot() */
|
||||
let vm_snapshot_path = url.to_file_path().unwrap();
|
||||
@ -405,35 +403,54 @@ impl MemoryManager {
|
||||
}
|
||||
};
|
||||
|
||||
memory_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.guest_memory
|
||||
.memory()
|
||||
.with_regions(|index, region| {
|
||||
let mut memory_region_path = vm_snapshot_path.clone();
|
||||
memory_region_path
|
||||
.push(mem_snapshot.memory_regions[index].backing_file.clone());
|
||||
let mut ext_regions = mem_snapshot.memory_regions;
|
||||
for region in ext_regions.iter_mut() {
|
||||
let mut memory_region_path = vm_snapshot_path.clone();
|
||||
memory_region_path.push(region.backing_file.clone());
|
||||
region.backing_file = memory_region_path;
|
||||
}
|
||||
|
||||
// Create the snapshot file for the region
|
||||
let mut memory_region_file = OpenOptions::new()
|
||||
.read(true)
|
||||
.open(memory_region_path)
|
||||
.map_err(|e| Error::Restore(MigratableError::MigrateReceive(e.into())))?;
|
||||
// In case there was no backing file, we can safely use CoW by
|
||||
// mapping the source files provided for restoring. This case
|
||||
// allows for a faster VM restoration and does not require us to
|
||||
// fill the memory content, hence we can return right away.
|
||||
if config.file.is_none() {
|
||||
return MemoryManager::new(fd, config, Some(ext_regions));
|
||||
};
|
||||
|
||||
region
|
||||
.read_from(
|
||||
MemoryRegionAddress(0),
|
||||
&mut memory_region_file,
|
||||
region.len().try_into().unwrap(),
|
||||
)
|
||||
.map_err(|e| Error::Restore(MigratableError::MigrateReceive(e.into())))?;
|
||||
let memory_manager = MemoryManager::new(fd, config, None)?;
|
||||
let guest_memory = memory_manager.lock().unwrap().guest_memory();
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
// In case the previous config was using a backing file, this means
|
||||
// it was MAP_SHARED, therefore we must copy the content into the
|
||||
// new regions so that we can still use MAP_SHARED when restoring
|
||||
// the VM.
|
||||
guest_memory.memory().with_regions(|index, region| {
|
||||
// Open (read only) the snapshot file for the given region.
|
||||
let mut memory_region_file = OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&ext_regions[index].backing_file)
|
||||
.map_err(|e| Error::Restore(MigratableError::MigrateReceive(e.into())))?;
|
||||
|
||||
// Fill the region with the file content.
|
||||
region
|
||||
.read_from(
|
||||
MemoryRegionAddress(0),
|
||||
&mut memory_region_file,
|
||||
region.len().try_into().unwrap(),
|
||||
)
|
||||
.map_err(|e| Error::Restore(MigratableError::MigrateReceive(e.into())))?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(memory_manager)
|
||||
} else {
|
||||
Err(Error::Restore(MigratableError::Restore(anyhow!(
|
||||
"Could not find {}-section from snapshot",
|
||||
MEMORY_MANAGER_SNAPSHOT_ID
|
||||
))))
|
||||
}
|
||||
|
||||
Ok(memory_manager)
|
||||
}
|
||||
|
||||
fn create_ram_region(
|
||||
|
Loading…
Reference in New Issue
Block a user