diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 7250c2c34..fa83533c7 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -356,6 +356,11 @@ pub enum Error { #[error("Impossible to resize guest memory if it is backed by user defined memory regions")] InvalidResizeWithMemoryZones, + /// Forbidden operation. Impossible to resize guest memory below the boot + /// RAM as it is not removable with virtio-mem. + #[error("Invalid resize request: desired_size = {0} below boot size = {1}")] + InvalidResizeBelowBootSize(u64, u64), + /// It's invalid to try applying a NUMA policy to a memory zone that is /// memory mapped with MAP_SHARED. #[error( @@ -2583,14 +2588,19 @@ impl MemoryManager { let mut region: Option> = None; match self.hotplug_method { HotplugMethod::VirtioMem => { - if desired_ram >= self.boot_ram { - if !self.dynamic { - return Ok(region); - } - - self.virtio_mem_resize(DEFAULT_MEMORY_ZONE, desired_ram - self.boot_ram)?; - self.current_ram = desired_ram; + if desired_ram < self.boot_ram { + return Err(Error::InvalidResizeBelowBootSize( + desired_ram, + self.boot_ram, + )); } + + if !self.dynamic { + return Ok(region); + } + + self.virtio_mem_resize(DEFAULT_MEMORY_ZONE, desired_ram - self.boot_ram)?; + self.current_ram = desired_ram; } HotplugMethod::Acpi => { if desired_ram > self.current_ram { @@ -2607,7 +2617,7 @@ impl MemoryManager { Ok(region) } - pub fn resize_zone(&mut self, id: &str, virtio_mem_size: u64) -> Result<(), Error> { + pub fn resize_zone(&mut self, zone: &MemoryZoneConfig, desired_ram: u64) -> Result<(), Error> { if !self.user_provided_zones { error!( "Not allowed to resize guest memory zone when no zone is \ @@ -2616,7 +2626,11 @@ impl MemoryManager { return Err(Error::ResizeZone); } - self.virtio_mem_resize(id, virtio_mem_size) + if desired_ram < zone.size { + return Err(Error::InvalidResizeBelowBootSize(desired_ram, zone.size)); + } + + self.virtio_mem_resize(&zone.id, desired_ram - zone.size) } pub fn is_hardlink(f: &File) -> bool { diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 67d3aec08..b756b6ac2 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -2158,27 +2158,18 @@ impl Vm { if let Some(zones) = &mut memory_config.zones { for zone in zones.iter_mut() { if zone.id == id { - if desired_memory >= zone.size { - let hotplugged_size = desired_memory - zone.size; - self.memory_manager - .lock() - .unwrap() - .resize_zone(id, desired_memory - zone.size) - .map_err(Error::MemoryManager)?; - // We update the memory zone config regardless of the - // actual 'resize-zone' operation result (happened or - // not), so that if the VM reboots it will be running - // with the last configured memory zone size. - zone.hotplugged_size = Some(hotplugged_size); + self.memory_manager + .lock() + .unwrap() + .resize_zone(zone, desired_memory) + .map_err(Error::MemoryManager)?; + // We update the memory zone config regardless of the + // actual 'resize-zone' operation result (happened or + // not), so that if the VM reboots it will be running + // with the last configured memory zone size. + zone.hotplugged_size = Some(desired_memory - zone.size); - return Ok(()); - } - error!( - "Invalid to ask less ({}) than boot RAM ({}) for \ - this memory zone", - desired_memory, zone.size, - ); - return Err(Error::ResizeZone); + return Ok(()); } } }