diff --git a/virtio-devices/src/vhost_user/mod.rs b/virtio-devices/src/vhost_user/mod.rs index 3858c5c05..86a774737 100644 --- a/virtio-devices/src/vhost_user/mod.rs +++ b/virtio-devices/src/vhost_user/mod.rs @@ -156,6 +156,8 @@ pub enum Error { SaveRestoreBackendState(#[source] io::Error), #[error("Vring bases count ({0}) does not match queue count ({1})")] VringBasesCountMismatch(usize, usize), + #[error("Backend state and vring bases must both be present or both be absent")] + InconsistentBackendState, } type Result = std::result::Result; @@ -323,6 +325,15 @@ pub struct VhostUserState { pub backend_state: Option>, } +impl VhostUserState { + pub fn validate(&self) -> Result<()> { + if self.backend_state.is_some() != self.vring_bases.is_some() { + return Err(Error::InconsistentBackendState); + } + Ok(()) + } +} + #[derive(Default)] pub struct VhostUserCommon { pub vu: Option>>, diff --git a/virtio-devices/src/vhost_user/vu_common_ctrl.rs b/virtio-devices/src/vhost_user/vu_common_ctrl.rs index 0e59e2399..b2ee2ae5d 100644 --- a/virtio-devices/src/vhost_user/vu_common_ctrl.rs +++ b/virtio-devices/src/vhost_user/vu_common_ctrl.rs @@ -28,7 +28,7 @@ use vm_memory::{Address, FileOffset, GuestAddress, GuestMemory, GuestMemoryRegio use vm_migration::protocol::MemoryRangeTable; use vmm_sys_util::eventfd::EventFd; -use super::{Error, Result}; +use super::{Error, Result, VhostUserState}; use crate::vhost_user::Inflight; use crate::{ GuestMemoryMmap, GuestRegionMmap, MmapRegion, VirtioInterrupt, VirtioInterruptType, @@ -512,6 +512,14 @@ impl VhostUserHandle { Ok((state, vring_bases)) } + pub fn restore_state(&mut self, state: &VhostUserState) -> Result<()> { + state.validate()?; + if let Some(backend_state) = &state.backend_state { + self.restore_backend_state(backend_state)?; + } + Ok(()) + } + /// Restore backend device state via the SET_DEVICE_STATE_FD protocol. /// Sends the saved opaque state blob to the backend via a socket. pub fn restore_backend_state(&mut self, state: &[u8]) -> Result<()> {