mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
vmm: memory_manager: Always copy anonymous RAM regions from disk
When restoring if a region of RAM is backed by anonymous memory i.e from memfd_create() then copy the contents of the ram from the file that has been saved to disk. Previously the code would map the memory from that file into the guest using a MAP_PRIVATE mapping. This has the effect of minimising the restore time but provides an issue where the restored VM does not have the same structure as the snapshotted VM, in particular memory is backed by files in the restored VM that were anonymously backed in the original. This creates two problems: * The snapshot data is mapped from files for the pages of the guest which prevents the storage from being reclaimed. * When snapshotting again the guest memory will not be correctly saved as it will have looked like it was backed by a file so it will not be written to disk but as it is a MAP_PRIVATE mapping the changes will never be written to the disk again. This results in incorrect behaviour. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
255dbd29ef
commit
a60b437f89
@ -823,8 +823,8 @@ impl MemoryManager {
|
|||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn create_ram_region(
|
fn create_ram_region(
|
||||||
file: &Option<PathBuf>,
|
backing_file: &Option<PathBuf>,
|
||||||
mut file_offset: u64,
|
file_offset: u64,
|
||||||
start_addr: GuestAddress,
|
start_addr: GuestAddress,
|
||||||
size: usize,
|
size: usize,
|
||||||
prefault: bool,
|
prefault: bool,
|
||||||
@ -833,27 +833,12 @@ impl MemoryManager {
|
|||||||
host_numa_node: Option<u32>,
|
host_numa_node: Option<u32>,
|
||||||
ext_regions: &Option<Vec<MemoryRegion>>,
|
ext_regions: &Option<Vec<MemoryRegion>>,
|
||||||
) -> Result<Arc<GuestRegionMmap>, Error> {
|
) -> Result<Arc<GuestRegionMmap>, Error> {
|
||||||
let mut backing_file: Option<PathBuf> = file.clone();
|
|
||||||
let mut copy_ext_region_content: Option<PathBuf> = None;
|
let mut copy_ext_region_content: Option<PathBuf> = None;
|
||||||
|
|
||||||
if let Some(ext_regions) = ext_regions {
|
if let Some(ext_regions) = ext_regions {
|
||||||
for ext_region in ext_regions.iter() {
|
for ext_region in ext_regions.iter() {
|
||||||
if ext_region.start_addr == start_addr && ext_region.size as usize == size {
|
if ext_region.start_addr == start_addr && ext_region.size as usize == size {
|
||||||
if ext_region.backing_file.is_some() {
|
copy_ext_region_content = ext_region.backing_file.clone();
|
||||||
// If the region is memory mapped as "shared", then we
|
|
||||||
// don't replace the backing file, but expect to copy
|
|
||||||
// the content from the external backing file after the
|
|
||||||
// region has been created.
|
|
||||||
if shared {
|
|
||||||
copy_ext_region_content = ext_region.backing_file.clone();
|
|
||||||
} else {
|
|
||||||
backing_file = ext_region.backing_file.clone();
|
|
||||||
// We must override the file offset as in this case
|
|
||||||
// we're restoring an existing region, which means
|
|
||||||
// it will fit perfectly the calculated region.
|
|
||||||
file_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to iterate further as we found the external
|
// No need to iterate further as we found the external
|
||||||
// region matching the current region.
|
// region matching the current region.
|
||||||
|
Loading…
Reference in New Issue
Block a user