vm-virtio: Consume pause events to prevent infinite epoll_wait calls

When a virtio device is paused an event is written to the appropriate
"pause" EventFd for the device. This will be noticed by the the device's
epoll_wait(), an atomic bool checked an if true then the thread is
parked(). When resuming the bool is reset and the thread is unpark()ed.
However the event triggering the pause is still in the EventFd so the
epoll_wait() will continue to return but because the boolean is not set
the thread will not be park()ed but instead we will busy loop around an
event that is not being consumed.

The solution is to drain the "pause" EventFd when the event is first
received and thus the epoll_wait() will only return for the pause event
once. This resolves the infinite epoll_wait() wake-ups.

Fixes: #869

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2020-03-09 16:45:45 +00:00 committed by Sebastien Boeuf
parent 16fd506bb8
commit 30b69549e1
9 changed files with 18 additions and 0 deletions

View File

@ -745,6 +745,8 @@ impl<T: DiskFile> BlockEpollHandler<T> {
break 'epoll;
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing virtio-block epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -275,6 +275,8 @@ impl ConsoleEpollHandler {
break 'epoll;
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing virtio-console epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -729,6 +729,8 @@ impl IommuEpollHandler {
break 'epoll;
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing virtio-iommu epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -272,6 +272,8 @@ impl NetEpollHandler {
break 'epoll;
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing virtio-net epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -269,6 +269,8 @@ impl NetCtrlEpollHandler {
break 'epoll;
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing vhost-user epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -290,6 +290,8 @@ impl PmemEpollHandler {
break 'epoll;
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing virtio-pmem epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -155,6 +155,8 @@ impl RngEpollHandler {
break 'epoll;
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing virtio-rng epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -153,6 +153,8 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
break 'poll;
}
x if pause_evt_index == x => {
// Drain pause event
let _ = self.vu_epoll_cfg.pause_evt.read();
debug!("PAUSE_EVENT received, pausing vhost-user epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will

View File

@ -351,6 +351,8 @@ where
return Ok(true);
}
PAUSE_EVENT => {
// Drain pause event
let _ = self.pause_evt.read();
debug!("PAUSE_EVENT received, pausing virtio-vsock epoll loop");
// We loop here to handle spurious park() returns.
// Until we have not resumed, the paused boolean will