virtio-devices: generic-vhost-user: Config change notification

Add support for backend that is connected via the vhost-user-generic
frontend to generate an interrupt into the guest when it has made a
change to the configuration. This is useful for devices that can change
the exposed configuration at runtime.

Assisted-by: Claude:Opus-4.7
Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
Rob Bradford
2026-04-25 10:32:38 +01:00
parent abef0e5b69
commit 8d62133383

View File

@@ -26,13 +26,27 @@ use crate::thread_helper::spawn_virtio_thread;
use crate::vhost_user::{VhostUserCommon, VhostUserState};
use crate::{
ActivateResult, GuestMemoryMmap, GuestRegionMmap, MmapRegion, VIRTIO_F_ACCESS_PLATFORM,
VirtioCommon, VirtioDevice, VirtioSharedMemoryList,
VirtioCommon, VirtioDevice, VirtioInterrupt, VirtioInterruptType, VirtioSharedMemoryList,
};
pub type State = VhostUserState<()>;
struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}
struct BackendReqHandler {
interrupt_cb: Arc<dyn VirtioInterrupt>,
}
impl VhostUserFrontendReqHandler for BackendReqHandler {
fn handle_config_change(&self) -> std::io::Result<u64> {
self.interrupt_cb
.trigger(VirtioInterruptType::Config)
.map_err(|e| {
error!("Failed to signal config change: {e:?}");
std::io::Error::other(e)
})?;
Ok(0)
}
}
pub struct GenericVhostUser {
vu_common: VhostUserCommon,
id: String,
@@ -97,7 +111,8 @@ impl GenericVhostUser {
| VhostUserProtocolFeatures::REPLY_ACK
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
| VhostUserProtocolFeatures::LOG_SHMFD
| VhostUserProtocolFeatures::DEVICE_STATE;
| VhostUserProtocolFeatures::DEVICE_STATE
| VhostUserProtocolFeatures::BACKEND_REQ;
let avail_features = super::DEFAULT_VIRTIO_FEATURES;
@@ -275,7 +290,22 @@ impl VirtioDevice for GenericVhostUser {
.activate(&queues, interrupt_cb.clone())?;
self.guest_memory = Some(mem.clone());
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None;
let has_backend_req = self.vu_common.acked_protocol_features
& VhostUserProtocolFeatures::BACKEND_REQ.bits()
!= 0;
let backend_req_handler = has_backend_req
.then(|| {
FrontendReqHandler::new(Arc::new(BackendReqHandler {
interrupt_cb: interrupt_cb.clone(),
}))
.map_err(|e| {
crate::ActivateError::VhostUserSetup(Error::FrontendReqHandlerCreation(e))
})
})
// Return inner Err early, keep Option of `Ok` value
.transpose()?;
// Run a dedicated thread for handling potential reconnections with
// the backend.
let (kill_evt, pause_evt) = self.vu_common.virtio_common.dup_eventfds();