virtio-devices: Test activator failure releases barrier

Feed BadActivate into VirtioPciDeviceActivator and assert that the
error propagates, device_activated stays false, DEVICE_NEEDS_RESET is
set in status, a single Config interrupt is delivered, and a thread
waiting on the activation barrier unblocks. The barrier release is
the deadlock fixed by the NEEDS_RESET on activation failure change.

Assisted-by: Claude:Opus-4.7
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-05-27 09:29:51 +02:00
committed by Rob Bradford
parent 7cdb724346
commit 64c552cc96

View File

@@ -1365,6 +1365,7 @@ mod unit_tests {
use vm_device::interrupt::InterruptSourceConfig;
use super::*;
use crate::{ActivateError, DEVICE_NEEDS_RESET};
struct TestInterruptSourceGroup {
event_fd: EventFd,
@@ -1594,4 +1595,30 @@ mod unit_tests {
};
(activator, status, device_activated, interrupt, barrier)
}
#[test]
fn activate_failure_marks_needs_reset_and_releases_barrier() {
let (activator, status, device_activated, interrupt, barrier) =
make_activator(Err(ActivateError::BadActivate));
// Simulate the vCPU thread blocked on the activation
// barrier after writing DRIVER_OK.
let waiter = std::thread::spawn(move || barrier.wait());
let result = activator.activate();
assert!(matches!(result, Err(ActivateError::BadActivate)));
assert!(!device_activated.load(Ordering::SeqCst));
assert_ne!(
status.load(Ordering::SeqCst) & (DEVICE_NEEDS_RESET as u8),
0
);
let triggers = interrupt.triggers.lock().unwrap();
assert_eq!(triggers.len(), 1);
assert!(matches!(triggers[0], VirtioInterruptType::Config));
// The barrier waiter must complete, showing the activator
// did not deadlock the vCPU thread.
waiter.join().expect("barrier waiter deadlocked");
}
}