mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 05:35:20 +00:00
vmm: Cleanup VM being created when VM restore fails
When VM restore fails, the VMM state is left with some side-effects, such as a VM being created. It would prevent the VMM from creating and booting a new VM or restoring from a VM snapshot. To fix this issue, this patch explicitly handles the side effects to the VMM state when VM restore fails, e.g. clear the VmConfig and shutdown the VM being created. Fixes: #6869 Signed-off-by: Bo Chen <bo.arvin.chen@gmail.com>
This commit is contained in:
parent
cff0d8bbe0
commit
de35b44da4
139
vmm/src/lib.rs
139
vmm/src/lib.rs
@ -1125,6 +1125,76 @@ impl Vmm {
|
||||
})
|
||||
}
|
||||
|
||||
fn vm_restore(
|
||||
&mut self,
|
||||
source_url: &str,
|
||||
vm_config: Arc<Mutex<VmConfig>>,
|
||||
prefault: bool,
|
||||
) -> std::result::Result<(), VmError> {
|
||||
let snapshot = recv_vm_state(source_url).map_err(VmError::Restore)?;
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
let vm_snapshot = get_vm_snapshot(&snapshot).map_err(VmError::Restore)?;
|
||||
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
self.vm_check_cpuid_compatibility(&vm_config, &vm_snapshot.common_cpuid)
|
||||
.map_err(VmError::Restore)?;
|
||||
|
||||
self.vm_config = Some(Arc::clone(&vm_config));
|
||||
|
||||
// Always re-populate the 'console_info' based on the new 'vm_config'
|
||||
self.console_info =
|
||||
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
||||
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let debug_evt = self
|
||||
.vm_debug_evt
|
||||
.try_clone()
|
||||
.map_err(VmError::EventFdClone)?;
|
||||
let activate_evt = self
|
||||
.activate_evt
|
||||
.try_clone()
|
||||
.map_err(VmError::EventFdClone)?;
|
||||
|
||||
let vm = Vm::new(
|
||||
vm_config,
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_evt,
|
||||
&self.seccomp_action,
|
||||
self.hypervisor.clone(),
|
||||
activate_evt,
|
||||
self.console_info.clone(),
|
||||
self.console_resize_pipe.clone(),
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Some(snapshot),
|
||||
Some(source_url),
|
||||
Some(prefault),
|
||||
)?;
|
||||
self.vm = Some(vm);
|
||||
|
||||
if self
|
||||
.vm_config
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.landlock_enable
|
||||
{
|
||||
apply_landlock(self.vm_config.as_ref().unwrap().clone())
|
||||
.map_err(VmError::ApplyLandlock)?;
|
||||
}
|
||||
|
||||
// Now we can restore the rest of the VM.
|
||||
if let Some(ref mut vm) = self.vm {
|
||||
vm.restore()
|
||||
} else {
|
||||
Err(VmError::VmNotCreated)
|
||||
}
|
||||
}
|
||||
|
||||
fn control_loop(
|
||||
&mut self,
|
||||
api_receiver: Rc<Receiver<ApiRequest>>,
|
||||
@ -1398,68 +1468,17 @@ impl RequestHandler for Vmm {
|
||||
}
|
||||
}
|
||||
|
||||
let snapshot = recv_vm_state(source_url).map_err(VmError::Restore)?;
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
let vm_snapshot = get_vm_snapshot(&snapshot).map_err(VmError::Restore)?;
|
||||
self.vm_restore(source_url, vm_config, restore_cfg.prefault)
|
||||
.map_err(|vm_restore_err| {
|
||||
error!("VM Restore failed: {:?}", vm_restore_err);
|
||||
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
self.vm_check_cpuid_compatibility(&vm_config, &vm_snapshot.common_cpuid)
|
||||
.map_err(VmError::Restore)?;
|
||||
// Cleanup the VM being created while vm restore
|
||||
if let Err(e) = self.vm_delete() {
|
||||
return e;
|
||||
}
|
||||
|
||||
self.vm_config = Some(Arc::clone(&vm_config));
|
||||
|
||||
// Always re-populate the 'console_info' based on the new 'vm_config'
|
||||
self.console_info =
|
||||
Some(pre_create_console_devices(self).map_err(VmError::CreateConsoleDevices)?);
|
||||
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let debug_evt = self
|
||||
.vm_debug_evt
|
||||
.try_clone()
|
||||
.map_err(VmError::EventFdClone)?;
|
||||
let activate_evt = self
|
||||
.activate_evt
|
||||
.try_clone()
|
||||
.map_err(VmError::EventFdClone)?;
|
||||
|
||||
let vm = Vm::new(
|
||||
vm_config,
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_evt,
|
||||
&self.seccomp_action,
|
||||
self.hypervisor.clone(),
|
||||
activate_evt,
|
||||
self.console_info.clone(),
|
||||
self.console_resize_pipe.clone(),
|
||||
Arc::clone(&self.original_termios_opt),
|
||||
Some(snapshot),
|
||||
Some(source_url),
|
||||
Some(restore_cfg.prefault),
|
||||
)?;
|
||||
self.vm = Some(vm);
|
||||
|
||||
if self
|
||||
.vm_config
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.landlock_enable
|
||||
{
|
||||
apply_landlock(self.vm_config.as_ref().unwrap().clone())
|
||||
.map_err(VmError::ApplyLandlock)?;
|
||||
}
|
||||
|
||||
// Now we can restore the rest of the VM.
|
||||
if let Some(ref mut vm) = self.vm {
|
||||
vm.restore()
|
||||
} else {
|
||||
Err(VmError::VmNotCreated)
|
||||
}
|
||||
vm_restore_err
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
|
Loading…
Reference in New Issue
Block a user