vm-migration: Add start_migration() to Migratable trait

In order to clearly decouple when the migration is started compared to
when the dirty logging is started, we introduce a new method to the
Migratable trait. This clarifies the semantics as we don't end up using
start_dirty_log() for identifying when the migration has been started.
And similarly, we rely on the already existing complete_migration()
method to know when the migration has been ended.

A bug was reported when running a local migration with a vhost-user-net
device in server mode. The reason was because the migration_started
variable was never set to "true", since the start_dirty_log() function
was never invoked.

Signed-off-by: lizhaoxin1 <Lxiaoyouling@163.com>
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
lizhaoxin1 2022-01-29 10:53:58 +08:00 committed by Sebastien Boeuf
parent a061bc32e4
commit a45e458c50
8 changed files with 40 additions and 2 deletions

View File

@ -417,6 +417,10 @@ impl Migratable for Blk {
self.vu_common.dirty_log(&self.guest_memory)
}
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common.start_migration()
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common
.complete_migration(self.common.kill_evt.take())

View File

@ -698,6 +698,10 @@ impl Migratable for Fs {
self.vu_common.dirty_log(&self.guest_memory)
}
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common.start_migration()
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common
.complete_migration(self.common.kill_evt.take())

View File

@ -451,7 +451,6 @@ impl VhostUserCommon {
&mut self,
guest_memory: &Option<GuestMemoryAtomic<GuestMemoryMmap>>,
) -> std::result::Result<(), MigratableError> {
self.migration_started = true;
if let Some(vu) = &self.vu {
if let Some(guest_memory) = guest_memory {
let last_ram_addr = guest_memory.memory().last_addr().raw_value();
@ -475,7 +474,6 @@ impl VhostUserCommon {
}
pub fn stop_dirty_log(&mut self) -> std::result::Result<(), MigratableError> {
self.migration_started = false;
if let Some(vu) = &self.vu {
vu.lock().unwrap().stop_dirty_log().map_err(|e| {
MigratableError::StopDirtyLog(anyhow!(
@ -509,10 +507,17 @@ impl VhostUserCommon {
}
}
pub fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.migration_started = true;
Ok(())
}
pub fn complete_migration(
&mut self,
kill_evt: Option<EventFd>,
) -> std::result::Result<(), MigratableError> {
self.migration_started = false;
// Make sure the device thread is killed in order to prevent from
// reconnections to the socket.
if let Some(kill_evt) = kill_evt {

View File

@ -488,6 +488,10 @@ impl Migratable for Net {
self.vu_common.dirty_log(&self.guest_memory)
}
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common.start_migration()
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common
.complete_migration(self.common.kill_evt.take())

View File

@ -305,6 +305,10 @@ pub trait Migratable: Send + Pausable + Snapshottable + Transportable {
Ok(MemoryRangeTable::default())
}
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
Ok(())
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
Ok(())
}

View File

@ -4221,6 +4221,15 @@ impl Migratable for DeviceManager {
Ok(MemoryRangeTable::new_from_tables(tables))
}
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
for (_, device_node) in self.device_tree.lock().unwrap().iter() {
if let Some(migratable) = &device_node.migratable {
migratable.lock().unwrap().start_migration()?;
}
}
Ok(())
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
for (_, device_node) in self.device_tree.lock().unwrap().iter() {
if let Some(migratable) = &device_node.migratable {

View File

@ -1100,6 +1100,9 @@ impl Vmm {
)));
}
// Let every Migratable object know about the migration being started.
vm.start_migration()?;
if send_data_migration.local {
// Now pause VM
vm.pause()?;

View File

@ -2675,6 +2675,11 @@ impl Migratable for Vm {
]))
}
fn start_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.memory_manager.lock().unwrap().start_migration()?;
self.device_manager.lock().unwrap().start_migration()
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.memory_manager.lock().unwrap().complete_migration()?;
self.device_manager.lock().unwrap().complete_migration()