From a60b437f89b6f58bf980d71eb14e28751559b0bd Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Thu, 22 Oct 2020 15:33:34 +0100 Subject: [PATCH] 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 --- vmm/src/memory_manager.rs | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 819c74c37..2041880b2 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -823,8 +823,8 @@ impl MemoryManager { #[allow(clippy::too_many_arguments)] fn create_ram_region( - file: &Option, - mut file_offset: u64, + backing_file: &Option, + file_offset: u64, start_addr: GuestAddress, size: usize, prefault: bool, @@ -833,27 +833,12 @@ impl MemoryManager { host_numa_node: Option, ext_regions: &Option>, ) -> Result, Error> { - let mut backing_file: Option = file.clone(); let mut copy_ext_region_content: Option = None; if let Some(ext_regions) = ext_regions { for ext_region in ext_regions.iter() { if ext_region.start_addr == start_addr && ext_region.size as usize == size { - if ext_region.backing_file.is_some() { - // 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; - } - } + copy_ext_region_content = ext_region.backing_file.clone(); // No need to iterate further as we found the external // region matching the current region.