From 72fc0976f113284ee229bc657926d3b712f74e6a Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 14 Apr 2026 12:14:05 +0100 Subject: [PATCH] virtio-devices: net: Remove "driver_awake" workaround for restore Now on the generic restore path the worker thread is notified on the events and also the guest is notified via the interrupt. This avoids the same "livelock" situation that required this "driver_awake" workaround when restoring the net device. Signed-off-by: Rob Bradford --- virtio-devices/src/device.rs | 21 ++++++++------------- virtio-devices/src/net.rs | 14 ++------------ 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/virtio-devices/src/device.rs b/virtio-devices/src/device.rs index 0bab70313..d1b925799 100644 --- a/virtio-devices/src/device.rs +++ b/virtio-devices/src/device.rs @@ -254,20 +254,15 @@ impl VirtioCommon { return Err(ActivateError::BadActivate); } - // Do not retain virtio-net queue eventfds here. Signaling them on - // resume would break its `driver_awake` workaround. - self.queue_evts = match VirtioDeviceType::from(self.device_type) { - VirtioDeviceType::Net => Vec::new(), - _ => queues - .iter() - .map(|(_, _, queue_evt)| { - queue_evt.try_clone().map_err(|e| { - error!("failed cloning queue EventFd: {e}"); - ActivateError::BadActivate - }) + self.queue_evts = queues + .iter() + .map(|(_, _, queue_evt)| { + queue_evt.try_clone().map_err(|e| { + error!("failed cloning queue EventFd: {e}"); + ActivateError::BadActivate }) - .collect::, _>>()?, - }; + }) + .collect::, _>>()?; let kill_evt = EventFd::new(EFD_NONBLOCK).map_err(|e| { error!("failed creating kill EventFd: {e}"); diff --git a/virtio-devices/src/net.rs b/virtio-devices/src/net.rs index 3bb360c64..ed8c05eeb 100644 --- a/virtio-devices/src/net.rs +++ b/virtio-devices/src/net.rs @@ -174,11 +174,6 @@ struct NetEpollHandler { queue_index_base: u16, queue_pair: (Queue, Queue), queue_evt_pair: (EventFd, EventFd), - // Always generate interrupts until the driver has signalled to the device. - // This mitigates a problem with interrupts from tap events being "lost" upon - // a restore as the vCPU thread isn't ready to handle the interrupt. This causes - // issues when combined with VIRTIO_RING_F_EVENT_IDX interrupt suppression. - driver_awake: bool, device_status: Arc, } @@ -260,7 +255,7 @@ Setting device status to 'NEEDS_RESET' and stopping processing queues until rese return Ok(()); } - if res.map_err(DeviceError::NetQueuePair)? || !self.driver_awake { + if res.map_err(DeviceError::NetQueuePair)? { self.signal_used_queue(self.queue_index_base + 1)?; debug!("Signalling TX queue"); } else { @@ -296,7 +291,7 @@ Setting device status to 'NEEDS_RESET' and stopping processing queues until rese return Ok(()); } - if res.map_err(DeviceError::NetQueuePair)? || !self.driver_awake { + if res.map_err(DeviceError::NetQueuePair)? { self.signal_used_queue(self.queue_index_base)?; debug!("Signalling RX queue"); } else { @@ -361,7 +356,6 @@ impl EpollHelperHandler for NetEpollHandler { let ev_type = event.data as u16; match ev_type { RX_QUEUE_EVENT => { - self.driver_awake = true; self.handle_rx_event().map_err(|e| { EpollHelperError::HandleEvent(anyhow!("Error processing RX queue: {e:?}")) })?; @@ -371,7 +365,6 @@ impl EpollHelperHandler for NetEpollHandler { if let Err(e) = queue_evt.read() { error!("Failed to get tx queue event: {e:?}"); } - self.driver_awake = true; self.handle_tx_event().map_err(|e| { EpollHelperError::HandleEvent(anyhow!("Error processing TX queue: {e:?}")) })?; @@ -428,8 +421,6 @@ impl EpollHelperHandler for NetEpollHandler { "Error from 'rate_limiter.event_handler()': {e:?}" )) })?; - - self.driver_awake = true; self.process_tx().map_err(|e| { EpollHelperError::HandleEvent(anyhow!("Error processing TX queue: {e:?}")) })?; @@ -855,7 +846,6 @@ impl VirtioDevice for Net { interrupt_cb: interrupt_cb.clone(), kill_evt, pause_evt, - driver_awake: false, device_status: self.device_status.clone(), };