From d46dd4b31f82f487706db9a1be9b1c3f6a10be3e Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Thu, 10 Aug 2023 11:34:09 +0800 Subject: [PATCH] vmm: cpu: Add pending removed vcpu check to avoid resize vcpu hang Add pending removed vcpu check according to VcpuState.removing, which can avoid cloud hypervisor hangup during continual vcpu resize. Fix #5419 Signed-off-by: Yi Wang --- vmm/src/cpu.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 95cfa18e2..be7d45e3a 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -124,6 +124,9 @@ pub enum Error { #[error("Error configuring vCPU: {0}")] VcpuConfiguration(#[source] arch::Error), + #[error("Still pending removed vcpu")] + VcpuPendingRemovedVcpu, + #[cfg(target_arch = "aarch64")] #[error("Error fetching preferred target: {0}")] VcpuArmPreferredTarget(#[source] hypervisor::HypervisorVmError), @@ -549,6 +552,7 @@ impl BusDevice for CpuManager { struct VcpuState { inserting: bool, removing: bool, + pending_removal: Arc, handle: Option>, kill: Arc, vcpu_run_interrupted: Arc, @@ -1138,9 +1142,21 @@ impl CpuManager { // Mark vCPUs for removal, actual removal happens on ejection for cpu_id in desired_vcpus..self.present_vcpus() { self.vcpu_states[usize::from(cpu_id)].removing = true; + self.vcpu_states[usize::from(cpu_id)] + .pending_removal + .store(true, Ordering::SeqCst); } } + pub fn check_pending_removed_vcpu(&mut self) -> bool { + for state in self.vcpu_states.iter() { + if state.active() && state.pending_removal.load(Ordering::SeqCst) { + return true; + } + } + false + } + fn remove_vcpu(&mut self, cpu_id: u8) -> Result<()> { info!("Removing vCPU: cpu_id = {}", cpu_id); let state = &mut self.vcpu_states[usize::from(cpu_id)]; @@ -1151,6 +1167,7 @@ impl CpuManager { // Once the thread has exited, clear the "kill" so that it can reused state.kill.store(false, Ordering::SeqCst); + state.pending_removal.store(false, Ordering::SeqCst); Ok(()) } @@ -1187,6 +1204,10 @@ impl CpuManager { return Ok(false); } + if self.check_pending_removed_vcpu() { + return Err(Error::VcpuPendingRemovedVcpu); + } + match desired_vcpus.cmp(&self.present_vcpus()) { cmp::Ordering::Greater => { let vcpus = self.create_vcpus(desired_vcpus, None)?;