Skip to content

Commit 948c552

Browse files
committed
virtio: add kick() method in VirtioDevice trait
So that we don't have to downcast VirtioDevice trait objects to the actual device type before calling the logic to process events for each device. Signed-off-by: Babis Chalios <bchalios@amazon.es>
1 parent d2bb088 commit 948c552

File tree

7 files changed

+74
-79
lines changed

7 files changed

+74
-79
lines changed

src/vmm/src/device_manager/mod.rs

Lines changed: 13 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,8 @@ use crate::devices::legacy::RTCDevice;
3030
use crate::devices::legacy::serial::SerialOut;
3131
use crate::devices::legacy::{IER_RDA_BIT, IER_RDA_OFFSET, SerialDevice};
3232
use crate::devices::pseudo::BootTimer;
33-
use crate::devices::virtio::balloon::Balloon;
34-
use crate::devices::virtio::block::device::Block;
3533
use crate::devices::virtio::device::VirtioDevice;
36-
use crate::devices::virtio::net::Net;
37-
use crate::devices::virtio::rng::Entropy;
3834
use crate::devices::virtio::transport::mmio::{IrqTrigger, MmioTransport};
39-
use crate::devices::virtio::vsock::{TYPE_VSOCK, Vsock, VsockUnixBackend};
40-
use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_NET, TYPE_RNG};
4135
use crate::resources::VmResources;
4236
use crate::snapshot::Persist;
4337
use crate::vstate::memory::GuestMemoryMmap;
@@ -265,85 +259,28 @@ impl DeviceManager {
265259
self.pci_devices.attach_pci_segment(vm)
266260
}
267261

268-
fn do_kick_device(virtio_device: Arc<Mutex<dyn VirtioDevice>>) {
269-
let mut device = virtio_device.lock().expect("Poisoned lock");
270-
match device.device_type() {
271-
TYPE_BALLOON => {
272-
let balloon = device.as_mut_any().downcast_mut::<Balloon>().unwrap();
273-
// If device is activated, kick the balloon queue(s) to make up for any
274-
// pending or in-flight epoll events we may have not captured in snapshot.
275-
// Stats queue doesn't need kicking as it is notified via a `timer_fd`.
276-
if balloon.is_activated() {
277-
info!("kick balloon {}.", balloon.id());
278-
balloon.process_virtio_queues();
279-
}
280-
}
281-
TYPE_BLOCK => {
282-
// We only care about kicking virtio block.
283-
// If we need to kick vhost-user-block we can do nothing.
284-
if let Some(block) = device.as_mut_any().downcast_mut::<Block>() {
285-
// If device is activated, kick the block queue(s) to make up for any
286-
// pending or in-flight epoll events we may have not captured in
287-
// snapshot. No need to kick Ratelimiters
288-
// because they are restored 'unblocked' so
289-
// any inflight `timer_fd` events can be safely discarded.
290-
if block.is_activated() {
291-
info!("kick block {}.", block.id());
292-
block.process_virtio_queues();
293-
}
294-
}
295-
}
296-
TYPE_NET => {
297-
let net = device.as_mut_any().downcast_mut::<Net>().unwrap();
298-
// If device is activated, kick the net queue(s) to make up for any
299-
// pending or in-flight epoll events we may have not captured in snapshot.
300-
// No need to kick Ratelimiters because they are restored 'unblocked' so
301-
// any inflight `timer_fd` events can be safely discarded.
302-
if net.is_activated() {
303-
info!("kick net {}.", net.id());
304-
net.process_virtio_queues();
305-
}
306-
}
307-
TYPE_VSOCK => {
308-
// Vsock has complicated protocol that isn't resilient to any packet loss,
309-
// so for Vsock we don't support connection persistence through snapshot.
310-
// Any in-flight packets or events are simply lost.
311-
// Vsock is restored 'empty'.
312-
// The only reason we still `kick` it is to make guest process
313-
// `TRANSPORT_RESET_EVENT` event we sent during snapshot creation.
314-
let vsock = device
315-
.as_mut_any()
316-
.downcast_mut::<Vsock<VsockUnixBackend>>()
317-
.unwrap();
318-
if vsock.is_activated() {
319-
info!("kick vsock {}.", vsock.id());
320-
vsock.signal_used_queue(0).unwrap();
321-
}
322-
}
323-
TYPE_RNG => {
324-
let entropy = device.as_mut_any().downcast_mut::<Entropy>().unwrap();
325-
if entropy.is_activated() {
326-
info!("kick entropy {}.", entropy.id());
327-
entropy.process_virtio_queues();
328-
}
329-
}
330-
_ => (),
331-
}
332-
}
333-
334262
/// Artificially kick VirtIO devices as if they had external events.
335263
pub fn kick_virtio_devices(&self) {
336264
info!("Artificially kick devices");
337265
// Go through MMIO VirtIO devices
338266
let _: Result<(), MmioError> = self.mmio_devices.for_each_virtio_device(|_, _, device| {
339267
let mmio_transport_locked = device.inner.lock().expect("Poisoned lock");
340-
Self::do_kick_device(mmio_transport_locked.device());
268+
mmio_transport_locked
269+
.device()
270+
.lock()
271+
.expect("Poisoned lock")
272+
.kick();
341273
Ok(())
342274
});
343275
// Go through PCI VirtIO devices
344-
for device in self.pci_devices.virtio_devices.values() {
345-
let virtio_device = device.lock().expect("Poisoned lock").virtio_device();
346-
Self::do_kick_device(virtio_device);
276+
for virtio_pci_device in self.pci_devices.virtio_devices.values() {
277+
virtio_pci_device
278+
.lock()
279+
.expect("Poisoned lock")
280+
.virtio_device()
281+
.lock()
282+
.expect("Poisoned lock")
283+
.kick();
347284
}
348285
}
349286

src/vmm/src/devices/virtio/balloon/device.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::ops::Deref;
55
use std::sync::Arc;
66
use std::time::Duration;
77

8-
use log::error;
8+
use log::{error, info};
99
use serde::Serialize;
1010
use timerfd::{ClockId, SetTimeFlags, TimerFd, TimerState};
1111
use vmm_sys_util::eventfd::EventFd;
@@ -615,6 +615,16 @@ impl VirtioDevice for Balloon {
615615
fn is_activated(&self) -> bool {
616616
self.device_state.is_activated()
617617
}
618+
619+
fn kick(&mut self) {
620+
// If device is activated, kick the balloon queue(s) to make up for any
621+
// pending or in-flight epoll events we may have not captured in snapshot.
622+
// Stats queue doesn't need kicking as it is notified via a `timer_fd`.
623+
if self.is_activated() {
624+
info!("kick balloon {}.", self.id());
625+
self.process_virtio_queues();
626+
}
627+
}
618628
}
619629

620630
#[cfg(test)]

src/vmm/src/devices/virtio/block/device.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use std::sync::Arc;
55

66
use event_manager::{EventOps, Events, MutEventSubscriber};
7+
use log::info;
78
use vmm_sys_util::eventfd::EventFd;
89

910
use super::BlockError;
@@ -214,6 +215,18 @@ impl VirtioDevice for Block {
214215
Self::VhostUser(b) => b.device_state.is_activated(),
215216
}
216217
}
218+
219+
fn kick(&mut self) {
220+
// If device is activated, kick the block queue(s) to make up for any
221+
// pending or in-flight epoll events we may have not captured in
222+
// snapshot. No need to kick Ratelimiters
223+
// because they are restored 'unblocked' so
224+
// any inflight `timer_fd` events can be safely discarded.
225+
if self.is_activated() {
226+
info!("kick block {}.", self.id());
227+
self.process_virtio_queues();
228+
}
229+
}
217230
}
218231

219232
impl MutEventSubscriber for Block {

src/vmm/src/devices/virtio/device.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ pub trait VirtioDevice: AsAny + Send {
159159
}
160160
Ok(())
161161
}
162+
163+
/// Kick the device, as if it had received external events.
164+
fn kick(&mut self) {}
162165
}
163166

164167
impl fmt::Debug for dyn VirtioDevice {

src/vmm/src/devices/virtio/net/device.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::ops::Deref;
1313
use std::sync::{Arc, Mutex};
1414

1515
use libc::{EAGAIN, iovec};
16-
use log::error;
16+
use log::{error, info};
1717
use vmm_sys_util::eventfd::EventFd;
1818

1919
use super::NET_QUEUE_MAX_SIZE;
@@ -1053,6 +1053,17 @@ impl VirtioDevice for Net {
10531053
fn is_activated(&self) -> bool {
10541054
self.device_state.is_activated()
10551055
}
1056+
1057+
fn kick(&mut self) {
1058+
// If device is activated, kick the net queue(s) to make up for any
1059+
// pending or in-flight epoll events we may have not captured in snapshot.
1060+
// No need to kick Ratelimiters because they are restored 'unblocked' so
1061+
// any inflight `timer_fd` events can be safely discarded.
1062+
if self.is_activated() {
1063+
info!("kick net {}.", self.id());
1064+
self.process_virtio_queues();
1065+
}
1066+
}
10561067
}
10571068

10581069
#[cfg(test)]

src/vmm/src/devices/virtio/rng/device.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::ops::Deref;
66
use std::sync::Arc;
77

88
use aws_lc_rs::rand;
9+
use log::info;
910
use vm_memory::GuestMemoryError;
1011
use vmm_sys_util::eventfd::EventFd;
1112

@@ -309,6 +310,13 @@ impl VirtioDevice for Entropy {
309310
self.device_state = DeviceState::Activated(ActiveState { mem, interrupt });
310311
Ok(())
311312
}
313+
314+
fn kick(&mut self) {
315+
if self.is_activated() {
316+
info!("kick entropy {}.", self.id());
317+
self.process_virtio_queues();
318+
}
319+
}
312320
}
313321

314322
#[cfg(test)]

src/vmm/src/devices/virtio/vsock/device.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use std::fmt::Debug;
2424
use std::ops::Deref;
2525
use std::sync::Arc;
2626

27-
use log::{error, warn};
27+
use log::{error, info, warn};
2828
use vmm_sys_util::eventfd::EventFd;
2929

3030
use super::super::super::DeviceError;
@@ -370,6 +370,19 @@ where
370370
fn is_activated(&self) -> bool {
371371
self.device_state.is_activated()
372372
}
373+
374+
fn kick(&mut self) {
375+
// Vsock has complicated protocol that isn't resilient to any packet loss,
376+
// so for Vsock we don't support connection persistence through snapshot.
377+
// Any in-flight packets or events are simply lost.
378+
// Vsock is restored 'empty'.
379+
// The only reason we still `kick` it is to make guest process
380+
// `TRANSPORT_RESET_EVENT` event we sent during snapshot creation.
381+
if self.is_activated() {
382+
info!("kick vsock {}.", self.id());
383+
self.signal_used_queue(0).unwrap();
384+
}
385+
}
373386
}
374387

375388
#[cfg(test)]

0 commit comments

Comments
 (0)