Skip to content

Commit

Permalink
Change hot-plug API endpoint
Browse files Browse the repository at this point in the history
Change from `add` to `target`. The user now supplies the number of vCPUs
they would like to reach, rather than the number of vCPUs to add to the
system. Obviously to make this work, hot-unplug functionality is needed
as well.

Examples:
- Currently 1 vCPU, would like 16 vCPUs: target = 16
- Currently 32 vCPUs, would like 2 vCPUs: target = 2

Signed-off-by: James Curtis <[email protected]>
  • Loading branch information
JamesC1305 committed Aug 28, 2024
1 parent a541725 commit 2a87db8
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 23 deletions.
22 changes: 9 additions & 13 deletions src/vmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,31 +615,23 @@ impl Vmm {
config: HotplugVcpuConfig,
) -> Result<MachineConfigUpdate, HotplugVcpuError> {
use crate::logger::IncMetric;
if config.add < 1 {
return Err(HotplugVcpuError::VcpuCountTooLow);
} else if self
.vcpus_handles
.len()
.checked_add(config.add.into())
.ok_or(HotplugVcpuError::VcpuCountTooHigh)?
> MAX_SUPPORTED_VCPUS.into()
{
if config.target > MAX_SUPPORTED_VCPUS.into() {
return Err(HotplugVcpuError::VcpuCountTooHigh);
}

if let Some(kvm_config) = self.vcpu_config.as_mut() {
kvm_config.vcpu_count += config.add;
kvm_config.vcpu_count = config.target;
}
// Create and start new vcpus
let mut vcpus = Vec::with_capacity(config.add.into());
let mut vcpus = Vec::with_capacity(config.target.into());

#[allow(clippy::cast_possible_truncation)]
let start_idx = self.vcpus_handles.len().try_into().unwrap();
if let Some(devices::BusDevice::CpuContainer(cont)) =
self.get_bus_device(DeviceType::CpuContainer, "CpuContainer")
{
let mut locked_container = cont.lock().expect("Poisoned lock");
for cpu_idx in start_idx..(start_idx + config.add) {
for cpu_idx in start_idx..config.target {
let exit_evt = self
.vcpus_exit_evt
.try_clone()
Expand All @@ -666,7 +658,10 @@ impl Vmm {
.map_err(HotplugVcpuError::VcpuStart)?;

#[allow(clippy::cast_lossless)]
METRICS.hotplug.vcpus_added.add(config.add.into());
METRICS
.hotplug
.vcpus_added
.add(self.vcpus_handles.len() as u64 - config.target as u64);

// Update VM config to reflect new CPUs added
#[allow(clippy::cast_possible_truncation)]
Expand All @@ -686,6 +681,7 @@ impl Vmm {
Ok(new_machine_config)
}

/// Removes vCPUs from VMM.
/// Retrieves the KVM dirty bitmap for each of the guest's memory regions.
pub fn reset_dirty_bitmap(&self) {
self.guest_memory
Expand Down
16 changes: 8 additions & 8 deletions src/vmm/src/rpc_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1914,7 +1914,7 @@ mod tests {

#[cfg(target_arch = "x86_64")]
check_preboot_request_err(
VmmAction::HotplugRequest(HotplugRequestConfig::Vcpu(HotplugVcpuConfig { add: 4 })),
VmmAction::HotplugRequest(HotplugRequestConfig::Vcpu(HotplugVcpuConfig { target: 4 })),
VmmActionError::OperationNotSupportedPreBoot,
);
}
Expand Down Expand Up @@ -2166,37 +2166,37 @@ mod tests {
};

vmm.attach_vcpu_config(vcpu_config.clone());
let config = HotplugVcpuConfig { add: 4 };
let config = HotplugVcpuConfig { target: 4 };
let result = vmm.hotplug_vcpus(config);
assert_eq!(vmm.vcpus_handles.len(), 4);
result.unwrap();

// Case 2. Vcpu count too low
let mut vmm = default_vmm();
vmm.attach_vcpu_config(vcpu_config.clone());
vmm.hotplug_vcpus(HotplugVcpuConfig { add: 1 }).unwrap();
vmm.hotplug_vcpus(HotplugVcpuConfig { target: 1 }).unwrap();
assert_eq!(vmm.vcpus_handles.len(), 1);
let config = HotplugVcpuConfig { add: 0 };
let config = HotplugVcpuConfig { target: 0 };
let result = vmm.hotplug_vcpus(config);
result.unwrap_err();
assert_eq!(vmm.vcpus_handles.len(), 1);

// Case 3. Vcpu count too high
let mut vmm = default_vmm();
vmm.attach_vcpu_config(vcpu_config.clone());
vmm.hotplug_vcpus(HotplugVcpuConfig { add: 1 }).unwrap();
vmm.hotplug_vcpus(HotplugVcpuConfig { target: 1 }).unwrap();
assert_eq!(vmm.vcpus_handles.len(), 1);
let config = HotplugVcpuConfig { add: 33 };
let config = HotplugVcpuConfig { target: 33 };
let result = vmm.hotplug_vcpus(config);
result.unwrap_err();
assert_eq!(vmm.vcpus_handles.len(), 1);

// Case 4. Attempted overflow of vcpus
let mut vmm = default_vmm();
vmm.attach_vcpu_config(vcpu_config.clone());
vmm.hotplug_vcpus(HotplugVcpuConfig { add: 2 }).unwrap();
vmm.hotplug_vcpus(HotplugVcpuConfig { target: 2 }).unwrap();
assert_eq!(vmm.vcpus_handles.len(), 2);
let config = HotplugVcpuConfig { add: 255 };
let config = HotplugVcpuConfig { target: 255 };
let result = vmm.hotplug_vcpus(config);
result.unwrap_err();
assert_eq!(vmm.vcpus_handles.len(), 2);
Expand Down
4 changes: 2 additions & 2 deletions src/vmm/src/vmm_config/hotplug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ pub enum HotplugVcpuError {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct HotplugVcpuConfig {
/// Number of vcpus to start.
pub add: u8,
/// Number of vcpus after operation.
pub target: u8,
}

0 comments on commit 2a87db8

Please sign in to comment.