virtio-devices: vhost_user: skip pause for disconnected backends

pause() returns DeviceDisconnected without calling into the backend when
VhostUserCommon already knows the socket is gone. DeviceManager treats
only that sentinel as log-and-continue, so one dead vhost-user device
does not abort the whole pause iteration.

Signed-off-by: Dylan Reid <dgreid@fb.com>
This commit is contained in:
Dylan Reid
2026-05-08 17:28:56 -07:00
committed by Bo Chen
parent db79150303
commit f56bfdaeb7
2 changed files with 28 additions and 7 deletions

View File

@@ -657,13 +657,28 @@ impl VhostUserCommon {
}
pub fn pause(&mut self) -> std::result::Result<(), MigratableError> {
if let Some(vu) = &self.vu {
vu.lock().unwrap().pause_vhost_user().map_err(|e| {
MigratableError::Pause(anyhow!("Error pausing vhost-user backend: {e:?}"))
})
} else {
Ok(())
if self.disconnected.load(Ordering::Relaxed) {
return Err(MigratableError::DeviceDisconnected(
self.socket_path.clone(),
));
}
if let Some(vu) = &self.vu
&& let Err(e) = vu.lock().unwrap().pause_vhost_user()
{
if e.is_transport_lost() {
self.disconnected.store(true, Ordering::Relaxed);
return Err(MigratableError::DeviceDisconnected(
self.socket_path.clone(),
));
}
return Err(MigratableError::Pause(anyhow!(
"Error pausing vhost-user backend for socket {}: {e:?}",
self.socket_path
)));
}
Ok(())
}
pub fn resume(&mut self) -> std::result::Result<(), MigratableError> {

View File

@@ -5526,7 +5526,13 @@ impl Pausable for DeviceManager {
fn pause(&mut self) -> result::Result<(), MigratableError> {
for (_, device_node) in self.device_tree.lock().unwrap().iter() {
if let Some(migratable) = &device_node.migratable {
migratable.lock().unwrap().pause()?;
match migratable.lock().unwrap().pause() {
Ok(()) => {}
Err(MigratableError::DeviceDisconnected(id)) => {
warn!("Skipping pause for disconnected device {id}");
}
Err(e) => return Err(e),
}
}
}
// On AArch64, the pause of device manager needs to trigger