From b5053ae4dededfda406bc36c8c1956c4fc0ed704 Mon Sep 17 00:00:00 2001 From: Peter Oskolkov Date: Thu, 12 Mar 2026 09:55:03 -0700 Subject: [PATCH] virtio-devices: wire driver_status to EpollHandler Signed-off-by: Peter Oskolkov --- fuzz/fuzz_targets/balloon.rs | 1 + fuzz/fuzz_targets/block.rs | 1 + fuzz/fuzz_targets/console.rs | 1 + fuzz/fuzz_targets/iommu.rs | 1 + fuzz/fuzz_targets/mem.rs | 1 + fuzz/fuzz_targets/net.rs | 1 + fuzz/fuzz_targets/pmem.rs | 1 + fuzz/fuzz_targets/rng.rs | 1 + fuzz/fuzz_targets/vsock.rs | 1 + fuzz/fuzz_targets/watchdog.rs | 1 + virtio-devices/src/block.rs | 9 ++++++++- virtio-devices/src/device.rs | 3 ++- virtio-devices/src/net.rs | 9 ++++++++- virtio-devices/src/transport/pci_device.rs | 5 ++++- virtio-devices/src/vsock/device.rs | 2 ++ 15 files changed, 34 insertions(+), 4 deletions(-) diff --git a/fuzz/fuzz_targets/balloon.rs b/fuzz/fuzz_targets/balloon.rs index edb4f0cf1..58b9b3058 100644 --- a/fuzz/fuzz_targets/balloon.rs +++ b/fuzz/fuzz_targets/balloon.rs @@ -103,6 +103,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { (1, deflate_q, deflate_evt), (2, reporting_q, reporting_evt), ], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/fuzz/fuzz_targets/block.rs b/fuzz/fuzz_targets/block.rs index 19b875f04..51007fe38 100644 --- a/fuzz/fuzz_targets/block.rs +++ b/fuzz/fuzz_targets/block.rs @@ -95,6 +95,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, q, evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/fuzz/fuzz_targets/console.rs b/fuzz/fuzz_targets/console.rs index 7f5fafaeb..e27331ed0 100644 --- a/fuzz/fuzz_targets/console.rs +++ b/fuzz/fuzz_targets/console.rs @@ -132,6 +132,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, input_queue, input_evt), (1, output_queue, output_evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .unwrap(); diff --git a/fuzz/fuzz_targets/iommu.rs b/fuzz/fuzz_targets/iommu.rs index 791ab6b00..a10640487 100644 --- a/fuzz/fuzz_targets/iommu.rs +++ b/fuzz/fuzz_targets/iommu.rs @@ -114,6 +114,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { (0, request_queue, request_evt), (0, _event_queue, _event_evt), ], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/fuzz/fuzz_targets/mem.rs b/fuzz/fuzz_targets/mem.rs index 46627e931..73ec11b02 100644 --- a/fuzz/fuzz_targets/mem.rs +++ b/fuzz/fuzz_targets/mem.rs @@ -109,6 +109,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, q, evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/fuzz/fuzz_targets/net.rs b/fuzz/fuzz_targets/net.rs index 0af835ac0..df9a1dce5 100644 --- a/fuzz/fuzz_targets/net.rs +++ b/fuzz/fuzz_targets/net.rs @@ -147,6 +147,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, input_queue, input_evt), (1, output_queue, output_evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .unwrap(); diff --git a/fuzz/fuzz_targets/pmem.rs b/fuzz/fuzz_targets/pmem.rs index b42c20dae..0bd083a1c 100644 --- a/fuzz/fuzz_targets/pmem.rs +++ b/fuzz/fuzz_targets/pmem.rs @@ -65,6 +65,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, q, evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/fuzz/fuzz_targets/rng.rs b/fuzz/fuzz_targets/rng.rs index d9cd11f09..13548664a 100644 --- a/fuzz/fuzz_targets/rng.rs +++ b/fuzz/fuzz_targets/rng.rs @@ -103,6 +103,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, q, evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/fuzz/fuzz_targets/vsock.rs b/fuzz/fuzz_targets/vsock.rs index 72bdeb4d6..33ebe7888 100644 --- a/fuzz/fuzz_targets/vsock.rs +++ b/fuzz/fuzz_targets/vsock.rs @@ -112,6 +112,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, q, evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/fuzz/fuzz_targets/watchdog.rs b/fuzz/fuzz_targets/watchdog.rs index 8736f8af3..31361755d 100644 --- a/fuzz/fuzz_targets/watchdog.rs +++ b/fuzz/fuzz_targets/watchdog.rs @@ -68,6 +68,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus { mem: guest_memory, interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: vec![(0, q, evt)], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .ok(); diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs index 82eca6182..ee05b6e8d 100644 --- a/virtio-devices/src/block.rs +++ b/virtio-devices/src/block.rs @@ -13,7 +13,7 @@ use std::num::Wrapping; use std::ops::Deref; use std::os::unix::io::AsRawFd; use std::path::PathBuf; -use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU64, Ordering}; use std::sync::{Arc, Barrier}; use std::{io, result}; @@ -161,6 +161,8 @@ struct BlockEpollHandler { host_cpus: Option>, acked_features: u64, disable_sector0_writes: bool, + #[allow(unused)] + device_status: Arc, } fn has_feature(features: u64, feature_flag: u64) -> bool { @@ -666,6 +668,7 @@ pub struct Block { queue_affinity: BTreeMap>, disable_sector0_writes: bool, lock_granularity_choice: LockGranularityChoice, + device_status: Arc, } #[derive(Serialize, Deserialize)] @@ -813,6 +816,7 @@ impl Block { queue_affinity, disable_sector0_writes, lock_granularity_choice: lock_granularity, + device_status: Arc::new(AtomicU8::new(0)), }) } @@ -1013,7 +1017,9 @@ impl VirtioDevice for Block { mem, interrupt_cb, mut queues, + device_status, } = context; + self.device_status = device_status; // See if the guest didn't ack the device being read-only. // If so, warn and pretend it did. let original_acked_features = self.common.acked_features; @@ -1069,6 +1075,7 @@ impl VirtioDevice for Block { host_cpus: self.queue_affinity.get(&queue_idx).cloned(), acked_features: self.common.acked_features, disable_sector0_writes: self.disable_sector0_writes, + device_status: self.device_status.clone(), }; let paused = self.common.paused.clone(); diff --git a/virtio-devices/src/device.rs b/virtio-devices/src/device.rs index d5e873bf4..4b5cdaf03 100644 --- a/virtio-devices/src/device.rs +++ b/virtio-devices/src/device.rs @@ -9,7 +9,7 @@ use std::collections::HashMap; use std::io::Write; use std::num::Wrapping; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use std::sync::{Arc, Barrier}; use std::thread; @@ -57,6 +57,7 @@ pub struct ActivationContext { pub mem: GuestMemoryAtomic, pub interrupt_cb: Arc, pub queues: Vec<(usize, Queue, EventFd)>, + pub device_status: Arc, } /// Trait for virtio devices to be driven by a virtio transport. diff --git a/virtio-devices/src/net.rs b/virtio-devices/src/net.rs index 2e3aa02ea..9f72b9310 100644 --- a/virtio-devices/src/net.rs +++ b/virtio-devices/src/net.rs @@ -10,7 +10,7 @@ use std::net::IpAddr; use std::num::Wrapping; use std::ops::Deref; use std::os::unix::io::{AsRawFd, RawFd}; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use std::sync::{Arc, Barrier}; use std::{result, thread}; @@ -179,6 +179,8 @@ struct NetEpollHandler { // 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, + #[allow(unused)] + device_status: Arc, } impl NetEpollHandler { @@ -414,6 +416,7 @@ pub struct Net { seccomp_action: SeccompAction, rate_limiter_config: Option, exit_evt: EventFd, + device_status: Arc, } #[derive(Serialize, Deserialize)] @@ -535,6 +538,7 @@ impl Net { seccomp_action, rate_limiter_config, exit_evt, + device_status: Arc::new(AtomicU8::new(0)), }) } @@ -698,7 +702,9 @@ impl VirtioDevice for Net { mem, interrupt_cb, mut queues, + device_status, } = context; + self.device_status = device_status; self.common.activate(&queues, interrupt_cb.clone())?; let num_queues = queues.len(); @@ -803,6 +809,7 @@ impl VirtioDevice for Net { kill_evt, pause_evt, driver_awake: false, + device_status: self.device_status.clone(), }; let paused = self.common.paused.clone(); diff --git a/virtio-devices/src/transport/pci_device.rs b/virtio-devices/src/transport/pci_device.rs index 1a8d3da96..7f049070d 100644 --- a/virtio-devices/src/transport/pci_device.rs +++ b/virtio-devices/src/transport/pci_device.rs @@ -10,7 +10,7 @@ use std::any::Any; use std::cmp; use std::io::Write; use std::ops::Deref; -use std::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU16, AtomicUsize, Ordering}; use std::sync::{Arc, Barrier, Mutex}; use anyhow::anyhow; @@ -306,6 +306,7 @@ pub struct VirtioPciDeviceActivator { queues: Option>, barrier: Option>, id: String, + status: Arc, } impl VirtioPciDeviceActivator { @@ -315,6 +316,7 @@ impl VirtioPciDeviceActivator { mem: self.memory.take().unwrap(), interrupt_cb: self.interrupt.take().unwrap(), queues: self.queues.take().unwrap(), + device_status: self.status, })?; self.device_activated.store(true, Ordering::SeqCst); @@ -820,6 +822,7 @@ impl VirtioPciDevice { device_activated: self.device_activated.clone(), barrier, id: self.id.clone(), + status: self.common_config.driver_status.clone(), } } diff --git a/virtio-devices/src/vsock/device.rs b/virtio-devices/src/vsock/device.rs index 5b215c359..6d38ecf39 100644 --- a/virtio-devices/src/vsock/device.rs +++ b/virtio-devices/src/vsock/device.rs @@ -598,6 +598,7 @@ mod unit_tests { mem: memory.clone(), interrupt_cb: Arc::new(NoopVirtioInterrupt {}), queues: Vec::new(), + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }); match bad_activate { Err(ActivateError::BadActivate) => (), @@ -626,6 +627,7 @@ mod unit_tests { EventFd::new(EFD_NONBLOCK).unwrap(), ), ], + device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)), }) .unwrap(); }