vmm: Reject resizing below the boot size with an error

This was already handled with user memory zones but not with the default
memory. Make a small refactoring to move the boot RAM check into
MemoryManager rather than split across Vm and MemoryManager.

Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
Rob Bradford
2026-06-18 13:43:55 +01:00
parent dbb33a5645
commit 6fee484715
2 changed files with 34 additions and 29 deletions

View File

@@ -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<Arc<GuestRegionMmap>> = 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 {

View File

@@ -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(());
}
}
}