mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vm-migration: improve debuggability on receiver for failed migrations
We cannot reliably send Request::abandon() on every kind of failure on the sender side, as we might be in the middle of a memory transmission. The receiver would not reliably know what to do with that. So instead, when the receiver cannot read from the socket, we log that the migration sender failed, which is the only likely cause of that failure. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This commit is contained in:
committed by
Bo Chen
parent
81022ab087
commit
013981b649
+14
-3
@@ -30,7 +30,7 @@ use event_monitor::event;
|
||||
use hypervisor::arch::x86;
|
||||
use landlock::LandlockError;
|
||||
use libc::{EFD_NONBLOCK, SIGINT, SIGTERM, TCSANOW, tcsetattr, termios};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use log::{debug, error, info, warn};
|
||||
use memory_manager::MemoryManagerSnapshotData;
|
||||
use pci::PciBdf;
|
||||
use seccompiler::{BpfProgram, SeccompAction, apply_filter};
|
||||
@@ -3040,9 +3040,20 @@ impl RequestHandler for Vmm {
|
||||
let mut state = ReceiveMigrationState::Established;
|
||||
|
||||
while !state.finished() {
|
||||
let req = Request::read_from(&mut socket)?;
|
||||
trace!("Command {:?} received", req.command());
|
||||
let req = Request::read_from(&mut socket).inspect_err(|error| {
|
||||
if matches!(
|
||||
error,
|
||||
MigratableError::MigrateSocket(io_error)
|
||||
if io_error.kind() == io::ErrorKind::UnexpectedEof
|
||||
) {
|
||||
error!("Failed to read migration request: sender likely failed, aborting");
|
||||
}
|
||||
})?;
|
||||
debug!("Command '{:?}' received", req.command());
|
||||
|
||||
// If sender-side migration causes any error propagated here, the
|
||||
// next loop iteration logs a helpful error when reading the next
|
||||
// request (which will fail as the sender closed the socket).
|
||||
let (response, new_state) = match self.vm_receive_migration_step(
|
||||
&mut socket,
|
||||
&listener,
|
||||
|
||||
@@ -557,10 +557,9 @@ impl ReceiveAdditionalConnections {
|
||||
// header. Each memory chunk is fully received and acked
|
||||
// before the worker loops back to Request::read_from(), so
|
||||
// EOF at this point means the sender finished sending
|
||||
// memory rather than dropping a chunk mid-transfer.
|
||||
debug!(
|
||||
"Connection closed by peer as expected (sender finished sending memory)"
|
||||
);
|
||||
// memory rather than dropping a chunk mid-transfer (happy
|
||||
// path) or the sender failed (error path).
|
||||
debug!("Connection closed by peer");
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
@@ -1115,7 +1114,9 @@ pub(crate) fn expect_ok_response(
|
||||
socket: &mut SocketStream,
|
||||
error: MigratableError,
|
||||
) -> Result<(), MigratableError> {
|
||||
Response::read_from(socket)?.ok_or_error(error).map(|_| ())
|
||||
Response::read_from(socket)?
|
||||
.ok_or_fatal_error(error)
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// Send a request and validate that the peer responds with OK.
|
||||
|
||||
+3
-3
@@ -3026,9 +3026,9 @@ impl Vm {
|
||||
.context("Error sending memory fd")
|
||||
.map_err(MigratableError::MigrateSend)?;
|
||||
|
||||
Response::read_from(socket)?.ok_or_error(MigratableError::MigrateSend(anyhow!(
|
||||
"Error during memory fd migration"
|
||||
)))?;
|
||||
Response::read_from(socket)?.ok_or_fatal_error(MigratableError::MigrateSend(
|
||||
anyhow!("Error during memory fd migration"),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user