mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm, ch-remote: Allow VFIO fd substitution at receive-migration
The VmConfig that arrives over the migration stream carries the source's device paths and stale FDs, none of which are usable on the destination. A received VFIO device therefore needs fresh descriptors supplied with the request. VmReceiveMigrationData gains vfio_fds, pairing each device id with a cdev FD, and iommufd_fd for the backing iommufd, both arriving over SCM_RIGHTS. Once the received VmConfig is available, each named device's path or FD is swapped for the received one and the iommufd is installed before the VM is built, so the device comes up FD backed. The request is rejected when a substituted device lacks the iommufd backend, when an id is unknown or repeated, or when a device names no replacement in vfio_fds. These checks run against the migrated VmConfig once it has been received. ch-remote gains the vfio_fds and iommufd_fd options and forwards the descriptors over SCM_RIGHTS. The D-Bus transport cannot carry file descriptors and drops them. Signed-off-by: Saravanan D <saravanand@crusoe.ai>
This commit is contained in:
@@ -52,8 +52,8 @@ use crate::api::{
|
||||
AddDisk, ApiAction, ApiError, ApiRequest, DeviceConfig, NetConfig, VmAddDevice, VmAddFs,
|
||||
VmAddGenericVhostUser, VmAddNet, VmAddPmem, VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot,
|
||||
VmConfig, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration,
|
||||
VmRemoveDevice, VmResize, VmResizeDisk, VmResizeZone, VmRestore, VmResume, VmSendMigration,
|
||||
VmShutdown, VmSnapshot,
|
||||
VmReceiveMigrationData, VmRemoveDevice, VmResize, VmResizeDisk, VmResizeZone, VmRestore,
|
||||
VmResume, VmSendMigration, VmShutdown, VmSnapshot,
|
||||
};
|
||||
use crate::config::RestoreConfig;
|
||||
use crate::cpu::Error as CpuError;
|
||||
@@ -484,7 +484,6 @@ vm_action_put_handler_body!(VmRemoveDevice);
|
||||
vm_action_put_handler_body!(VmResizeDisk);
|
||||
vm_action_put_handler_body!(VmResizeZone);
|
||||
vm_action_put_handler_body!(VmSnapshot);
|
||||
vm_action_put_handler_body!(VmReceiveMigration);
|
||||
vm_action_put_handler_body!(VmSendMigration);
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
@@ -626,6 +625,54 @@ impl PutHandler for VmRestore {
|
||||
|
||||
impl GetHandler for VmRestore {}
|
||||
|
||||
// Custom handler so the SCM_RIGHTS file pool can be split the same way
|
||||
// VmRestore does, cdev FDs for the vfio_fds entries then the iommufd FD.
|
||||
impl PutHandler for VmReceiveMigration {
|
||||
fn handle_request(
|
||||
&'static self,
|
||||
api_notifier: EventFd,
|
||||
api_sender: Sender<ApiRequest>,
|
||||
body: &Option<Body>,
|
||||
files: Vec<File>,
|
||||
) -> result::Result<Option<Body>, HttpError> {
|
||||
if let Some(body) = body {
|
||||
let mut data: VmReceiveMigrationData = serde_json::from_slice(body.raw())?;
|
||||
|
||||
let vfio_total = data.vfio_fds.as_ref().map_or(0, |c| c.len());
|
||||
let expected = if data.vfio_fds.is_some() {
|
||||
vfio_total + 1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
if files.len() != expected {
|
||||
error!(
|
||||
"Expected {expected} FDs in VmReceiveMigration request, received {}",
|
||||
files.len()
|
||||
);
|
||||
return Err(HttpError::BadRequest);
|
||||
}
|
||||
|
||||
// Split in the order vfio_fds, then the iommufd FD.
|
||||
let mut files = files;
|
||||
if let Some(cfgs) = data.vfio_fds.as_mut() {
|
||||
let vfio_files: Vec<File> = files.drain(..vfio_total).collect();
|
||||
let mut cfgs = cfgs.iter_mut().collect::<Vec<&mut _>>();
|
||||
attach_fds_to_cfgs(vfio_files, cfgs.as_mut_slice())?;
|
||||
}
|
||||
if data.vfio_fds.is_some() {
|
||||
data.iommufd_fd = Some(files.remove(0).into_raw_fd());
|
||||
}
|
||||
|
||||
self.send(api_notifier, api_sender, data)
|
||||
.map_err(HttpError::ApiError)
|
||||
} else {
|
||||
Err(HttpError::BadRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetHandler for VmReceiveMigration {}
|
||||
|
||||
// Common handler for boot, shutdown and reboot
|
||||
pub struct VmActionHandler {
|
||||
action: &'static dyn HttpVmAction,
|
||||
|
||||
Reference in New Issue
Block a user