From 2e6895d911ff0dd49b0a627de4a93ddd393f82cd Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Wed, 29 Apr 2020 16:16:30 +0200 Subject: [PATCH] vmm: Store and restore virtio-fs resources This device has a dedicated memory region in the guest address space, which means in case of snapshot/restore, it must be restored in the exact same location it was during the snapshot. That's through the resources that we can describe the location of this extra memory region, allowing the device for correct restoring. Signed-off-by: Sebastien Boeuf --- vmm/src/device_manager.rs | 99 ++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 22 deletions(-) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index e1877e80a..a03bb4a7f 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -328,6 +328,9 @@ pub enum DeviceManagerError { /// Expected resources for virtio-mmio could not be found. MissingVirtioMmioResources, + + /// Expected resources for virtio-fs could not be found. + MissingVirtioFsResources, } pub type DeviceManagerResult = result::Result; @@ -1533,24 +1536,82 @@ impl DeviceManager { id }; - self.device_tree.insert(id.clone(), Node::default()); + // Look for the id in the device tree. If it can be found, that means + // the device is being restored, otherwise it's created from scratch. + let cache_range = if let Some(node) = self.device_tree.get(&id) { + debug!("Restoring virtio-fs {} resources", id); + + let mut cache_range: Option<(u64, u64)> = None; + for resource in node.resources.iter() { + match resource { + Resource::MmioAddressRange { base, size } => { + if cache_range.is_some() { + return Err(DeviceManagerError::ResourceAlreadyExists); + } + + cache_range = Some((*base, *size)); + } + _ => { + error!("Unexpected resource {:?} for {}", resource, id); + } + } + } + + if cache_range.is_none() { + return Err(DeviceManagerError::MissingVirtioFsResources); + } + + cache_range + } else { + self.device_tree.insert(id.clone(), Node::default()); + None + }; if let Some(fs_sock) = fs_cfg.sock.to_str() { let cache = if fs_cfg.dax { - let fs_cache = fs_cfg.cache_size; - // The memory needs to be 2MiB aligned in order to support - // hugepages. - let fs_guest_addr = self - .address_manager - .allocator - .lock() - .unwrap() - .allocate_mmio_addresses(None, fs_cache as GuestUsize, Some(0x0020_0000)) - .ok_or(DeviceManagerError::FsRangeAllocation)?; + let (cache_base, cache_size) = if let Some((base, size)) = cache_range { + // The memory needs to be 2MiB aligned in order to support + // hugepages. + self.address_manager + .allocator + .lock() + .unwrap() + .allocate_mmio_addresses( + Some(GuestAddress(base)), + size as GuestUsize, + Some(0x0020_0000), + ) + .ok_or(DeviceManagerError::FsRangeAllocation)?; + + (base, size) + } else { + let size = fs_cfg.cache_size; + // The memory needs to be 2MiB aligned in order to support + // hugepages. + let base = self + .address_manager + .allocator + .lock() + .unwrap() + .allocate_mmio_addresses(None, size as GuestUsize, Some(0x0020_0000)) + .ok_or(DeviceManagerError::FsRangeAllocation)?; + + (base.raw_value(), size) + }; + + // Update the device tree with correct resource information. + if let Some(node) = self.device_tree.get_mut(&id) { + node.resources.push(Resource::MmioAddressRange { + base: cache_base, + size: cache_size, + }); + } else { + return Err(DeviceManagerError::MissingNode); + } let mmap_region = MmapRegion::build( None, - fs_cache as usize, + cache_size as usize, libc::PROT_NONE, libc::MAP_ANONYMOUS | libc::MAP_PRIVATE, ) @@ -1561,27 +1622,21 @@ impl DeviceManager { .memory_manager .lock() .unwrap() - .create_userspace_mapping( - fs_guest_addr.raw_value(), - fs_cache, - host_addr, - false, - false, - ) + .create_userspace_mapping(cache_base, cache_size, host_addr, false, false) .map_err(DeviceManagerError::MemoryManager)?; let mut region_list = Vec::new(); region_list.push(VirtioSharedMemory { offset: 0, - len: fs_cache, + len: cache_size, }); Some(( VirtioSharedMemoryList { host_addr, mem_slot, - addr: fs_guest_addr, - len: fs_cache as GuestUsize, + addr: GuestAddress(cache_base), + len: cache_size as GuestUsize, region_list, }, mmap_region,