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 <rbradford@meta.com>
This commit is contained in:
Rob Bradford
2026-04-14 12:14:05 +01:00
parent 101c259051
commit 72fc0976f1
2 changed files with 10 additions and 25 deletions

View File

@@ -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::<Result<Vec<_>, _>>()?,
};
})
.collect::<Result<Vec<_>, _>>()?;
let kill_evt = EventFd::new(EFD_NONBLOCK).map_err(|e| {
error!("failed creating kill EventFd: {e}");

View File

@@ -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<AtomicU8>,
}
@@ -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(),
};