From 02688993a0fd5334803077f17f7c4bf2995ee041 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Thu, 26 Mar 2026 13:41:38 -0700 Subject: [PATCH] virtio-devices: vhost_user: Fetch and store the backend state/vring Fetch the opaque device state from the backend and store it along with the last vring used in the state used for the snapshot. Signed-off-by: Rob Bradford --- virtio-devices/src/vhost_user/mod.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/virtio-devices/src/vhost_user/mod.rs b/virtio-devices/src/vhost_user/mod.rs index 92e1b73d8..3858c5c05 100644 --- a/virtio-devices/src/vhost_user/mod.rs +++ b/virtio-devices/src/vhost_user/mod.rs @@ -317,6 +317,10 @@ pub struct VhostUserState { pub vu_num_queues: usize, #[serde(default)] pub backend_req_support: bool, + #[serde(default)] + pub vring_bases: Option>, + #[serde(default)] + pub backend_state: Option>, } #[derive(Default)] @@ -328,6 +332,7 @@ pub struct VhostUserCommon { pub migration_started: bool, pub server: bool, pub interrupt_cb: Option>, + pub vring_bases: Option>, } impl VhostUserCommon { @@ -359,6 +364,7 @@ impl VhostUserCommon { .iter() .map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap())) .collect::>(); + let vring_bases = self.vring_bases.take(); vu.lock() .unwrap() .setup_vhost_user( @@ -368,7 +374,7 @@ impl VhostUserCommon { acked_features, &backend_req_handler, inflight.as_mut(), - None, + vring_bases.as_deref(), ) .map_err(ActivateError::VhostUserSetup)?; @@ -471,7 +477,7 @@ impl VhostUserCommon { common: &crate::VirtioCommon, config: C, ) -> std::result::Result, MigratableError> { - let state = VhostUserState { + let mut state = VhostUserState { avail_features: common.avail_features, acked_features: common.acked_features, config, @@ -480,6 +486,17 @@ impl VhostUserCommon { ..Default::default() }; + if let Some(vu) = &self.vu { + let mut vu_locked = vu.lock().unwrap(); + if vu_locked.supports_device_state() { + let (backend_state, vring_bases) = vu_locked.save_backend_state().map_err(|e| { + MigratableError::Snapshot(anyhow!("Failed saving backend state: {e:?}")) + })?; + state.backend_state = Some(backend_state); + state.vring_bases = Some(vring_bases); + } + } + Ok(state) }