From db7915030372887d9333d455668ba39241a08fc5 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Fri, 8 May 2026 17:28:29 -0700 Subject: [PATCH] virtio-devices: vhost_user: memory update error handling For add memory region, if the backend is disconnected or returns an error, forward the appropriate error type to the caller. If the error indicates that the vhost user backend has disconnected, mark it as such. Signed-off-by: Dylan Reid --- virtio-devices/src/vhost_user/mod.rs | 66 +++++++++++++++++++++------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/virtio-devices/src/vhost_user/mod.rs b/virtio-devices/src/vhost_user/mod.rs index bf28fec92..1eee637d4 100644 --- a/virtio-devices/src/vhost_user/mod.rs +++ b/virtio-devices/src/vhost_user/mod.rs @@ -569,6 +569,15 @@ impl VhostUserCommon { self.virtio_common.interrupt_cb = None; } + fn memory_update_error(&self, source: Error) -> crate::Error { + if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits() != 0 + { + crate::Error::VhostUserAddMemoryRegion(source) + } else { + crate::Error::VhostUserUpdateMemory(source) + } + } + pub fn shutdown(&mut self) { // Signal the epoll thread to exit, unpause it (it may be parked // if the VM was paused for migration), then wait for it to finish. @@ -595,27 +604,54 @@ impl VhostUserCommon { self.vu = None; } + fn add_memory_region_internal( + &self, + guest_memory: &Option>, + region: &Arc, + ) -> Result<()> { + if let Some(vu) = &self.vu { + if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits() + != 0 + { + return vu.lock().unwrap().add_memory_region(region); + } else if let Some(guest_memory) = guest_memory { + return vu + .lock() + .unwrap() + .update_mem_table(guest_memory.memory().deref()); + } + } + + Ok(()) + } + pub fn add_memory_region( &mut self, guest_memory: &Option>, region: &Arc, ) -> std::result::Result<(), crate::Error> { - if let Some(vu) = &self.vu { - if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits() - != 0 - { - return vu - .lock() - .unwrap() - .add_memory_region(region) - .map_err(crate::Error::VhostUserAddMemoryRegion); - } else if let Some(guest_memory) = guest_memory { - return vu - .lock() - .unwrap() - .update_mem_table(guest_memory.memory().deref()) - .map_err(crate::Error::VhostUserUpdateMemory); + if self.disconnected.load(Ordering::Relaxed) { + warn!( + "Skipping add memory region on disconnected dev with socket: {}", + self.socket_path + ); + } + + if let Err(e) = self.add_memory_region_internal(guest_memory, region) { + if e.is_transport_lost() { + warn!( + "Failed updating memory on vhost-user backend for socket {}: {e:?}; \ + marking device as disconnected", + self.socket_path + ); + self.disconnected.store(true, Ordering::Relaxed); + } else { + warn!( + "Failed updating memory on vhost-user backend for socket {}: {e:?}", + self.socket_path + ); } + return Err(self.memory_update_error(e)); } Ok(()) }