From e4934de3c9ad6714eec5da54c7ee974259bb5f65 Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Fri, 24 Apr 2026 01:14:58 +0000 Subject: [PATCH] ch-remote: Support FD-based VFIO devices Signed-off-by: Bo Chen Assisted-by: Claude:Opus-4.7 --- cloud-hypervisor/src/bin/ch-remote.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cloud-hypervisor/src/bin/ch-remote.rs b/cloud-hypervisor/src/bin/ch-remote.rs index 3c1b32606..4f553418a 100644 --- a/cloud-hypervisor/src/bin/ch-remote.rs +++ b/cloud-hypervisor/src/bin/ch-remote.rs @@ -371,14 +371,14 @@ fn rest_api_do_command(matches: &ArgMatches, socket: &mut UnixStream) -> ApiResu .map_err(Error::HttpApiClient) } Some("add-device") => { - let device_config = add_device_config( + let (device_config, fds) = add_device_config( matches .subcommand_matches("add-device") .unwrap() .get_one::("device_config") .unwrap(), )?; - simple_api_command(socket, "PUT", "add-device", Some(&device_config)) + simple_api_command_with_fds(socket, "PUT", "add-device", Some(&device_config), &fds) .map_err(Error::HttpApiClient) } Some("remove-device") => { @@ -609,7 +609,7 @@ fn dbus_api_do_command(matches: &ArgMatches, proxy: &DBusApi1ProxyBlocking<'_>) proxy.api_vm_resize_zone(&resize_zone) } Some("add-device") => { - let device_config = add_device_config( + let (device_config, _fds) = add_device_config( matches .subcommand_matches("add-device") .unwrap() @@ -835,11 +835,21 @@ fn resize_zone_config(id: &str, size: &str) -> Result { Ok(serde_json::to_string(&resize_zone).unwrap()) } -fn add_device_config(config: &str) -> Result { - let device_config = DeviceConfig::parse(config).map_err(Error::AddDeviceConfig)?; +fn add_device_config(config: &str) -> Result<(String, Vec), Error> { + let mut device_config = DeviceConfig::parse(config).map_err(Error::AddDeviceConfig)?; + + // DeviceConfig is modified on purpose here by taking the file + // descriptor out. Keeping it and sending it over to the server side + // process would not make any sense since the file descriptor may be + // represented with different values. + let fds = device_config + .fd + .take() + .map(|fd| vec![fd]) + .unwrap_or_default(); let device_config = serde_json::to_string(&device_config).unwrap(); - Ok(device_config) + Ok((device_config, fds)) } fn add_user_device_config(config: &str) -> Result {