dragonball: make the resize_vcpu api support sync

Let dragonball's resize_vcpu api support synchronization, and only
return after the hot-plug of the CPU is successfully executed in the
guest kernel. This ensures that the subsequent device hot-plug operation
can also proceed smoothly.

Signed-off-by: Fupan Li <fupan.lfp@antgroup.com>
This commit is contained in:
Fupan Li 2025-07-03 11:54:26 +08:00 committed by Fupan Li
parent 210844ce6b
commit 72a38457f0
4 changed files with 15 additions and 10 deletions

View File

@ -9,8 +9,9 @@
use std::fs::File; use std::fs::File;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crossbeam_channel::{unbounded, Receiver, Sender, TryRecvError}; use crossbeam_channel::{Receiver, Sender, TryRecvError};
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use std::sync::mpsc;
use tracing::instrument; use tracing::instrument;
use crate::error::{Result, StartMicroVmError, StopMicrovmError}; use crate::error::{Result, StartMicroVmError, StopMicrovmError};
@ -284,7 +285,7 @@ pub enum VmmData {
/// Return vfio device's slot number in guest. /// Return vfio device's slot number in guest.
VfioDeviceData(Option<u8>), VfioDeviceData(Option<u8>),
/// Sync Hotplug /// Sync Hotplug
SyncHotplug((Sender<Option<i32>>, Receiver<Option<i32>>)), SyncHotplug((mpsc::Sender<Option<i32>>, mpsc::Receiver<Option<i32>>)),
} }
/// Request data type used to communicate between the API and the VMM. /// Request data type used to communicate between the API and the VMM.
@ -900,7 +901,7 @@ impl VmmService {
} }
})?; })?;
let (sender, receiver) = unbounded(); let (sender, receiver) = mpsc::channel();
// It is safe because we don't expect poison lock. // It is safe because we don't expect poison lock.
let vfio_manager = vm.device_manager.vfio_manager.lock().unwrap(); let vfio_manager = vm.device_manager.vfio_manager.lock().unwrap();
@ -965,15 +966,17 @@ impl VmmService {
)); ));
} }
let (sender, revceiver) = mpsc::channel();
#[cfg(feature = "dbs-upcall")] #[cfg(feature = "dbs-upcall")]
vm.resize_vcpu(config, None).map_err(|e| { vm.resize_vcpu(config, Some(sender.clone())).map_err(|e| {
if let VcpuResizeError::UpcallServerNotReady = e { if let VcpuResizeError::UpcallServerNotReady = e {
return VmmActionError::UpcallServerNotReady; return VmmActionError::UpcallServerNotReady;
} }
VmmActionError::ResizeVcpu(e) VmmActionError::ResizeVcpu(e)
})?; })?;
Ok(VmmData::Empty) Ok(VmmData::SyncHotplug((sender, revceiver)))
} }
#[cfg(feature = "virtio-mem")] #[cfg(feature = "virtio-mem")]

View File

@ -16,9 +16,9 @@ use std::collections::HashMap;
use std::ops::Deref; use std::ops::Deref;
use std::os::fd::RawFd; use std::os::fd::RawFd;
use std::path::Path; use std::path::Path;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use crossbeam_channel::Sender;
use dbs_device::resources::Resource::LegacyIrq; use dbs_device::resources::Resource::LegacyIrq;
use dbs_device::resources::{DeviceResources, Resource, ResourceConstraint}; use dbs_device::resources::{DeviceResources, Resource, ResourceConstraint};
use dbs_device::DeviceIo; use dbs_device::DeviceIo;

View File

@ -225,7 +225,7 @@ pub struct VcpuManager {
vm_as: GuestAddressSpaceImpl, vm_as: GuestAddressSpaceImpl,
pub(crate) vm_fd: Arc<VmFd>, pub(crate) vm_fd: Arc<VmFd>,
action_sycn_tx: Option<Sender<bool>>, action_sycn_tx: Option<Sender<Option<i32>>>,
vcpus_in_action: (VcpuAction, Vec<u8>), vcpus_in_action: (VcpuAction, Vec<u8>),
pub(crate) reset_event_fd: Option<EventFd>, pub(crate) reset_event_fd: Option<EventFd>,
@ -756,7 +756,9 @@ impl VcpuManager {
fn sync_action_finish(&mut self, got_error: bool) { fn sync_action_finish(&mut self, got_error: bool) {
if let Some(tx) = self.action_sycn_tx.take() { if let Some(tx) = self.action_sycn_tx.take() {
if let Err(e) = tx.send(got_error) { let result = if got_error { 0 } else { -1 };
if let Err(e) = tx.send(Some(result)) {
debug!("cpu sync action send to closed channel {}", e); debug!("cpu sync action send to closed channel {}", e);
} }
} }
@ -856,7 +858,7 @@ mod hotplug {
pub fn resize_vcpu( pub fn resize_vcpu(
&mut self, &mut self,
vcpu_count: u8, vcpu_count: u8,
sync_tx: Option<Sender<bool>>, sync_tx: Option<Sender<Option<i32>>>,
) -> std::result::Result<(), VcpuResizeError> { ) -> std::result::Result<(), VcpuResizeError> {
if self.get_vcpus_action() != VcpuAction::None { if self.get_vcpus_action() != VcpuAction::None {
return Err(VcpuResizeError::VcpuIsHotplugging); return Err(VcpuResizeError::VcpuIsHotplugging);

View File

@ -832,7 +832,7 @@ impl Vm {
pub fn resize_vcpu( pub fn resize_vcpu(
&mut self, &mut self,
config: VcpuResizeInfo, config: VcpuResizeInfo,
sync_tx: Option<Sender<bool>>, sync_tx: Option<Sender<Option<i32>>>,
) -> std::result::Result<(), VcpuResizeError> { ) -> std::result::Result<(), VcpuResizeError> {
if self.upcall_client().is_none() { if self.upcall_client().is_none() {
Err(VcpuResizeError::UpcallClientMissing) Err(VcpuResizeError::UpcallClientMissing)