mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Update memory configuration upon virtio-mem resizing
Based on all the preparatory work achieved through previous commits, this patch updates the 'hotplugged_size' field for both MemoryConfig and MemoryZoneConfig structures when either the whole memory is resized, or simply when a memory zone is resized. This fixes the lack of support for rebooting a VM with the right amount of memory plugged in. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
@@ -664,8 +664,8 @@ impl MemoryManager {
|
|||||||
mergeable: config.mergeable,
|
mergeable: config.mergeable,
|
||||||
allocator: allocator.clone(),
|
allocator: allocator.clone(),
|
||||||
hotplug_method: config.hotplug_method.clone(),
|
hotplug_method: config.hotplug_method.clone(),
|
||||||
boot_ram: config.size,
|
boot_ram: ram_size,
|
||||||
current_ram: config.size,
|
current_ram: ram_size,
|
||||||
next_hotplug_slot: 0,
|
next_hotplug_slot: 0,
|
||||||
snapshot: Mutex::new(None),
|
snapshot: Mutex::new(None),
|
||||||
shared: config.shared,
|
shared: config.shared,
|
||||||
@@ -1268,12 +1268,7 @@ impl MemoryManager {
|
|||||||
Ok(region)
|
Ok(region)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize_zone(
|
pub fn resize_zone(&mut self, id: &str, virtio_mem_size: u64) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
id: &str,
|
|
||||||
desired_ram: u64,
|
|
||||||
config: &MemoryConfig,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if !self.user_provided_zones {
|
if !self.user_provided_zones {
|
||||||
error!(
|
error!(
|
||||||
"Not allowed to resize guest memory zone when no zone is \
|
"Not allowed to resize guest memory zone when no zone is \
|
||||||
@@ -1282,25 +1277,7 @@ impl MemoryManager {
|
|||||||
return Err(Error::ResizeZone);
|
return Err(Error::ResizeZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(zones) = &config.zones {
|
self.virtio_mem_resize(id, virtio_mem_size)
|
||||||
for zone in zones.iter() {
|
|
||||||
if zone.id == id {
|
|
||||||
if desired_ram >= zone.size {
|
|
||||||
return self.virtio_mem_resize(id, desired_ram - zone.size);
|
|
||||||
} else {
|
|
||||||
error!(
|
|
||||||
"Invalid to ask less ({}) than boot RAM ({}) for \
|
|
||||||
this memory zone",
|
|
||||||
desired_ram, zone.size,
|
|
||||||
);
|
|
||||||
return Err(Error::ResizeZone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error!("Could not find the memory zone {} for the resize", id);
|
|
||||||
Err(Error::ResizeZone)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
|||||||
@@ -209,6 +209,9 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Cannot apply seccomp filter
|
/// Cannot apply seccomp filter
|
||||||
ApplySeccompFilter(seccomp::Error),
|
ApplySeccompFilter(seccomp::Error),
|
||||||
|
|
||||||
|
/// Failed resizing a memory zone.
|
||||||
|
ResizeZone,
|
||||||
}
|
}
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
@@ -884,6 +887,8 @@ impl Vm {
|
|||||||
.resize(desired_memory)
|
.resize(desired_memory)
|
||||||
.map_err(Error::MemoryManager)?;
|
.map_err(Error::MemoryManager)?;
|
||||||
|
|
||||||
|
let mut memory_config = &mut self.config.lock().unwrap().memory;
|
||||||
|
|
||||||
if let Some(new_region) = &new_region {
|
if let Some(new_region) = &new_region {
|
||||||
self.device_manager
|
self.device_manager
|
||||||
.lock()
|
.lock()
|
||||||
@@ -891,7 +896,6 @@ impl Vm {
|
|||||||
.update_memory(&new_region)
|
.update_memory(&new_region)
|
||||||
.map_err(Error::DeviceManager)?;
|
.map_err(Error::DeviceManager)?;
|
||||||
|
|
||||||
let memory_config = &self.config.lock().unwrap().memory;
|
|
||||||
match memory_config.hotplug_method {
|
match memory_config.hotplug_method {
|
||||||
HotplugMethod::Acpi => {
|
HotplugMethod::Acpi => {
|
||||||
self.device_manager
|
self.device_manager
|
||||||
@@ -907,7 +911,16 @@ impl Vm {
|
|||||||
// We update the VM config regardless of the actual guest resize
|
// We update the VM config regardless of the actual guest resize
|
||||||
// operation result (happened or not), so that if the VM reboots
|
// operation result (happened or not), so that if the VM reboots
|
||||||
// it will be running with the last configure memory size.
|
// it will be running with the last configure memory size.
|
||||||
self.config.lock().unwrap().memory.size = desired_memory;
|
match memory_config.hotplug_method {
|
||||||
|
HotplugMethod::Acpi => memory_config.size = desired_memory,
|
||||||
|
HotplugMethod::VirtioMem => {
|
||||||
|
if desired_memory > memory_config.size {
|
||||||
|
memory_config.hotplugged_size = Some(desired_memory - memory_config.size);
|
||||||
|
} else {
|
||||||
|
memory_config.hotplugged_size = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(desired_ram_w_balloon) = desired_ram_w_balloon {
|
if let Some(desired_ram_w_balloon) = desired_ram_w_balloon {
|
||||||
@@ -925,11 +938,39 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize_zone(&mut self, id: String, desired_memory: u64) -> Result<()> {
|
pub fn resize_zone(&mut self, id: String, desired_memory: u64) -> Result<()> {
|
||||||
self.memory_manager
|
let memory_config = &mut self.config.lock().unwrap().memory;
|
||||||
.lock()
|
|
||||||
.unwrap()
|
if let Some(zones) = &mut memory_config.zones {
|
||||||
.resize_zone(&id, desired_memory, &self.config.lock().unwrap().memory)
|
for zone in zones.iter_mut() {
|
||||||
.map_err(Error::MemoryManager)
|
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);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Invalid to ask less ({}) than boot RAM ({}) for \
|
||||||
|
this memory zone",
|
||||||
|
desired_memory, zone.size,
|
||||||
|
);
|
||||||
|
return Err(Error::ResizeZone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error!("Could not find the memory zone {} for the resize", id);
|
||||||
|
Err(Error::ResizeZone)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pci_support"))]
|
#[cfg(not(feature = "pci_support"))]
|
||||||
|
|||||||
Reference in New Issue
Block a user