From 30b69549e10a08270686545da0efa16976f91cab Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Mon, 9 Mar 2020 16:45:45 +0000 Subject: [PATCH] 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 --- vm-virtio/src/block.rs | 2 ++ vm-virtio/src/console.rs | 2 ++ vm-virtio/src/iommu.rs | 2 ++ vm-virtio/src/net.rs | 2 ++ vm-virtio/src/net_util.rs | 2 ++ vm-virtio/src/pmem.rs | 2 ++ vm-virtio/src/rng.rs | 2 ++ vm-virtio/src/vhost_user/handler.rs | 2 ++ vm-virtio/src/vsock/device.rs | 2 ++ 9 files changed, 18 insertions(+) diff --git a/vm-virtio/src/block.rs b/vm-virtio/src/block.rs index 7aebfc2ee..2653dbb58 100755 --- a/vm-virtio/src/block.rs +++ b/vm-virtio/src/block.rs @@ -745,6 +745,8 @@ impl BlockEpollHandler { 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 diff --git a/vm-virtio/src/console.rs b/vm-virtio/src/console.rs index b4ec7ecc8..26247daf0 100755 --- a/vm-virtio/src/console.rs +++ b/vm-virtio/src/console.rs @@ -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 diff --git a/vm-virtio/src/iommu.rs b/vm-virtio/src/iommu.rs index f952a446e..3340ddf62 100644 --- a/vm-virtio/src/iommu.rs +++ b/vm-virtio/src/iommu.rs @@ -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 diff --git a/vm-virtio/src/net.rs b/vm-virtio/src/net.rs index 0f02cc7ea..4187b7406 100644 --- a/vm-virtio/src/net.rs +++ b/vm-virtio/src/net.rs @@ -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 diff --git a/vm-virtio/src/net_util.rs b/vm-virtio/src/net_util.rs index c9bbd6267..43e0f3dd9 100644 --- a/vm-virtio/src/net_util.rs +++ b/vm-virtio/src/net_util.rs @@ -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 diff --git a/vm-virtio/src/pmem.rs b/vm-virtio/src/pmem.rs index a7ee9a088..c40200dd6 100644 --- a/vm-virtio/src/pmem.rs +++ b/vm-virtio/src/pmem.rs @@ -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 diff --git a/vm-virtio/src/rng.rs b/vm-virtio/src/rng.rs index 8d2b675a1..917b84adf 100755 --- a/vm-virtio/src/rng.rs +++ b/vm-virtio/src/rng.rs @@ -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 diff --git a/vm-virtio/src/vhost_user/handler.rs b/vm-virtio/src/vhost_user/handler.rs index b5d5fa311..c7fa06ddd 100644 --- a/vm-virtio/src/vhost_user/handler.rs +++ b/vm-virtio/src/vhost_user/handler.rs @@ -153,6 +153,8 @@ impl VhostUserEpollHandler { 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 diff --git a/vm-virtio/src/vsock/device.rs b/vm-virtio/src/vsock/device.rs index a7efe6a68..2dfeae3b2 100644 --- a/vm-virtio/src/vsock/device.rs +++ b/vm-virtio/src/vsock/device.rs @@ -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