mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: add guest exit event path
Introduce a dedicated guest_exit_evt and a matching epoll dispatch path for guest-triggered shutdowns. This series is needed because managment software such as libvirt may still need the Cloud Hypervisor process to stay alive after the guest has shut down. Today a guest-triggered shutdown can make the VMM disappear immediately, which means the managment software can lose track of the VM run-state. This must only apply to guest-triggered shutdowns. Fatal error paths and other internal exit paths must keep using the existing VMM exit handling. For now GuestExit still calls vmm_shutdown(), so this commit only adds the separate plumbing and keeps the current behavior unchanged. On-behalf-of: SAP leander.kohler@sap.com Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
This commit is contained in:
committed by
Rob Bradford
parent
dc0e003be0
commit
c698075157
@@ -250,6 +250,7 @@ pub enum EpollDispatch {
|
||||
Api = 2,
|
||||
ActivateVirtioDevices = 3,
|
||||
Debug = 4,
|
||||
GuestExit = 5,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
@@ -262,6 +263,7 @@ impl From<u64> for EpollDispatch {
|
||||
2 => Api,
|
||||
3 => ActivateVirtioDevices,
|
||||
4 => Debug,
|
||||
5 => GuestExit,
|
||||
_ => Unknown,
|
||||
}
|
||||
}
|
||||
@@ -608,6 +610,7 @@ pub struct Vmm {
|
||||
epoll: EpollContext,
|
||||
exit_evt: EventFd,
|
||||
reset_evt: EventFd,
|
||||
guest_exit_evt: EventFd,
|
||||
api_evt: EventFd,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_evt: EventFd,
|
||||
@@ -781,6 +784,7 @@ impl Vmm {
|
||||
) -> Result<Self> {
|
||||
let mut epoll = EpollContext::new().map_err(Error::Epoll)?;
|
||||
let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
let guest_exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
let activate_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
|
||||
epoll
|
||||
@@ -791,6 +795,10 @@ impl Vmm {
|
||||
.add_event(&reset_evt, EpollDispatch::Reset)
|
||||
.map_err(Error::Epoll)?;
|
||||
|
||||
epoll
|
||||
.add_event(&guest_exit_evt, EpollDispatch::GuestExit)
|
||||
.map_err(Error::Epoll)?;
|
||||
|
||||
epoll
|
||||
.add_event(&activate_evt, EpollDispatch::ActivateVirtioDevices)
|
||||
.map_err(Error::Epoll)?;
|
||||
@@ -808,6 +816,7 @@ impl Vmm {
|
||||
epoll,
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
guest_exit_evt,
|
||||
api_evt,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_evt,
|
||||
@@ -1109,6 +1118,9 @@ impl Vmm {
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!("Error cloning reset EventFd: {e}"))
|
||||
})?;
|
||||
let guest_exit_evt = self.guest_exit_evt.try_clone().map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!("Error cloning guest exit EventFd: {e}"))
|
||||
})?;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let debug_evt = self.vm_debug_evt.try_clone().map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!("Error cloning debug EventFd: {e}"))
|
||||
@@ -1128,6 +1140,7 @@ impl Vmm {
|
||||
hypervisor_vm,
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
guest_exit_evt,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_evt,
|
||||
&self.seccomp_action,
|
||||
@@ -1569,6 +1582,10 @@ impl Vmm {
|
||||
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let guest_exit_evt = self
|
||||
.guest_exit_evt
|
||||
.try_clone()
|
||||
.map_err(VmError::EventFdClone)?;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let debug_evt = self
|
||||
.vm_debug_evt
|
||||
@@ -1583,6 +1600,7 @@ impl Vmm {
|
||||
vm_config,
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
guest_exit_evt,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_evt,
|
||||
&self.seccomp_action,
|
||||
@@ -1667,6 +1685,13 @@ impl Vmm {
|
||||
self.reset_evt.read().map_err(Error::EventFdRead)?;
|
||||
self.vm_reboot().map_err(Error::VmReboot)?;
|
||||
}
|
||||
EpollDispatch::GuestExit => {
|
||||
info!("VM guest exit event");
|
||||
self.guest_exit_evt.read().map_err(Error::EventFdRead)?;
|
||||
self.vmm_shutdown().map_err(Error::VmmShutdown)?;
|
||||
|
||||
break 'outer;
|
||||
}
|
||||
EpollDispatch::ActivateVirtioDevices => {
|
||||
if let Some(ref vm) = self.vm {
|
||||
let count = self.activate_evt.read().map_err(Error::EventFdRead)?;
|
||||
@@ -1775,6 +1800,10 @@ impl RequestHandler for Vmm {
|
||||
if self.vm.is_none() {
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let guest_exit_evt = self
|
||||
.guest_exit_evt
|
||||
.try_clone()
|
||||
.map_err(VmError::EventFdClone)?;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let vm_debug_evt = self
|
||||
.vm_debug_evt
|
||||
@@ -1790,6 +1819,7 @@ impl RequestHandler for Vmm {
|
||||
Arc::clone(vm_config),
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
guest_exit_evt,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
vm_debug_evt,
|
||||
&self.seccomp_action,
|
||||
@@ -1955,6 +1985,10 @@ impl RequestHandler for Vmm {
|
||||
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let guest_exit_evt = self
|
||||
.guest_exit_evt
|
||||
.try_clone()
|
||||
.map_err(VmError::EventFdClone)?;
|
||||
#[cfg(feature = "guest_debug")]
|
||||
let debug_evt = self
|
||||
.vm_debug_evt
|
||||
@@ -1980,6 +2014,7 @@ impl RequestHandler for Vmm {
|
||||
config,
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
guest_exit_evt,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
debug_evt,
|
||||
&self.seccomp_action,
|
||||
|
||||
Reference in New Issue
Block a user