virtio-devices: Embed VirtioCommon in VhostUserCommon

Since vhost-user devices are always virtio devices it makes sense to
structure this struct inside the VhostUserCommon struct. This then also
makes some of the methods on VhostUserCommon cleaner since they can now
act directly on the common virtio bits (e.g. for kill_evt)

Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
Rob Bradford
2026-03-31 04:31:35 -07:00
parent db93c6fdc7
commit a0bbef3a76
5 changed files with 145 additions and 139 deletions

View File

@@ -39,7 +39,6 @@ struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}
pub struct Blk {
common: VirtioCommon,
vu_common: VhostUserCommon,
id: String,
config: VirtioBlockConfig,
@@ -170,17 +169,17 @@ impl Blk {
};
Ok(Blk {
common: VirtioCommon {
device_type: VirtioDeviceType::Block as u32,
queue_sizes: vec![vu_cfg.queue_size; num_queues],
avail_features,
acked_features,
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: DEFAULT_QUEUE_NUMBER as u16,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu_common: VhostUserCommon {
virtio_common: VirtioCommon {
device_type: VirtioDeviceType::Block as u32,
queue_sizes: vec![vu_cfg.queue_size; num_queues],
avail_features,
acked_features,
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: DEFAULT_QUEUE_NUMBER as u16,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu: Some(Arc::new(Mutex::new(vu))),
acked_protocol_features,
socket_path: vu_cfg.socket,
@@ -199,18 +198,18 @@ impl Blk {
}
fn state(&self) -> std::result::Result<State, MigratableError> {
self.vu_common.state(&self.common, self.config)
self.vu_common.state(self.config)
}
}
impl Drop for Blk {
fn drop(&mut self) {
if let Some(kill_evt) = self.common.kill_evt.take()
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take()
&& let Err(e) = kill_evt.write(1)
{
error!("failed to kill vhost-user-blk: {e:?}");
}
self.common.wait_for_epoll_threads();
self.vu_common.virtio_common.wait_for_epoll_threads();
if let Some(thread) = self.epoll_thread.take()
&& let Err(e) = thread.join()
{
@@ -221,15 +220,15 @@ impl Drop for Blk {
impl VirtioDevice for Blk {
fn device_type(&self) -> u32 {
self.common.device_type
self.vu_common.virtio_common.device_type
}
fn queue_max_sizes(&self) -> &[u16] {
&self.common.queue_sizes
&self.vu_common.virtio_common.queue_sizes
}
fn features(&self) -> u64 {
let mut features = self.common.avail_features;
let mut features = self.vu_common.virtio_common.avail_features;
if self.iommu {
features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
}
@@ -237,7 +236,7 @@ impl VirtioDevice for Blk {
}
fn ack_features(&mut self, value: u64) {
self.common.ack_features(value);
self.vu_common.virtio_common.ack_features(value);
}
fn read_config(&self, offset: u64, data: &mut [u8]) {
@@ -278,27 +277,29 @@ impl VirtioDevice for Blk {
queues,
..
} = context;
self.common.activate(&queues, interrupt_cb.clone())?;
self.vu_common
.virtio_common
.activate(&queues, interrupt_cb.clone())?;
self.guest_memory = Some(mem.clone());
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None;
// Run a dedicated thread for handling potential reconnections with
// the backend.
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let (kill_evt, pause_evt) = self.vu_common.virtio_common.dup_eventfds();
let mut handler = self.vu_common.activate(
mem,
&queues,
interrupt_cb,
self.common.acked_features,
self.vu_common.virtio_common.acked_features,
backend_req_handler,
kill_evt,
pause_evt,
)?;
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
let paused = self.vu_common.virtio_common.paused.clone();
let paused_sync = self.vu_common.virtio_common.paused_sync.clone();
let mut epoll_threads = Vec::new();
@@ -317,8 +318,8 @@ impl VirtioDevice for Blk {
fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
// We first must resume the virtio thread if it was paused.
if self.common.pause_evt.take().is_some() {
self.common.resume().ok()?;
if self.vu_common.virtio_common.pause_evt.take().is_some() {
self.vu_common.virtio_common.resume().ok()?;
}
if let Some(vu) = &self.vu_common.vu
@@ -328,7 +329,7 @@ impl VirtioDevice for Blk {
return None;
}
if let Some(kill_evt) = self.common.kill_evt.take() {
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take() {
// Ignore the result because there is nothing we can do about it.
let _ = kill_evt.write(1);
}
@@ -336,7 +337,7 @@ impl VirtioDevice for Blk {
event!("virtio-device", "reset", "id", &self.id);
// Return the interrupt
Some(self.common.interrupt_cb.take().unwrap())
Some(self.vu_common.virtio_common.interrupt_cb.take().unwrap())
}
fn shutdown(&mut self) {
@@ -354,11 +355,11 @@ impl VirtioDevice for Blk {
impl Pausable for Blk {
fn pause(&mut self) -> result::Result<(), MigratableError> {
self.vu_common.pause()?;
self.common.pause()
self.vu_common.virtio_common.pause()
}
fn resume(&mut self) -> result::Result<(), MigratableError> {
self.common.resume()?;
self.vu_common.virtio_common.resume()?;
if let Some(epoll_thread) = &self.epoll_thread {
epoll_thread.thread().unpark();
@@ -397,7 +398,6 @@ impl Migratable for Blk {
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common
.complete_migration(self.common.kill_evt.take())
self.vu_common.complete_migration()
}
}

View File

@@ -59,7 +59,6 @@ impl Default for VirtioFsConfig {
unsafe impl ByteValued for VirtioFsConfig {}
pub struct Fs {
common: VirtioCommon,
vu_common: VhostUserCommon,
id: String,
config: VirtioFsConfig,
@@ -178,17 +177,17 @@ impl Fs {
};
Ok(Fs {
common: VirtioCommon {
device_type: VirtioDeviceType::Fs as u32,
avail_features,
acked_features,
queue_sizes: vec![queue_size; num_queues],
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: 1,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu_common: VhostUserCommon {
virtio_common: VirtioCommon {
device_type: VirtioDeviceType::Fs as u32,
avail_features,
acked_features,
queue_sizes: vec![queue_size; num_queues],
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: 1,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu: Some(Arc::new(Mutex::new(vu))),
acked_protocol_features,
socket_path: path.to_string(),
@@ -208,17 +207,17 @@ impl Fs {
}
fn state(&self) -> std::result::Result<State, MigratableError> {
self.vu_common.state(&self.common, self.config)
self.vu_common.state(self.config)
}
}
impl Drop for Fs {
fn drop(&mut self) {
if let Some(kill_evt) = self.common.kill_evt.take() {
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take() {
// Ignore the result because there is nothing we can do about it.
let _ = kill_evt.write(1);
}
self.common.wait_for_epoll_threads();
self.vu_common.virtio_common.wait_for_epoll_threads();
if let Some(thread) = self.epoll_thread.take()
&& let Err(e) = thread.join()
{
@@ -229,15 +228,15 @@ impl Drop for Fs {
impl VirtioDevice for Fs {
fn device_type(&self) -> u32 {
self.common.device_type
self.vu_common.virtio_common.device_type
}
fn queue_max_sizes(&self) -> &[u16] {
&self.common.queue_sizes
&self.vu_common.virtio_common.queue_sizes
}
fn features(&self) -> u64 {
let mut features = self.common.avail_features;
let mut features = self.vu_common.virtio_common.avail_features;
if self.iommu {
features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
}
@@ -245,7 +244,7 @@ impl VirtioDevice for Fs {
}
fn ack_features(&mut self, value: u64) {
self.common.ack_features(value);
self.vu_common.virtio_common.ack_features(value);
}
fn read_config(&self, offset: u64, data: &mut [u8]) {
@@ -259,26 +258,28 @@ impl VirtioDevice for Fs {
queues,
..
} = context;
self.common.activate(&queues, interrupt_cb.clone())?;
self.vu_common
.virtio_common
.activate(&queues, interrupt_cb.clone())?;
self.guest_memory = Some(mem.clone());
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None;
// Run a dedicated thread for handling potential reconnections with
// the backend.
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let (kill_evt, pause_evt) = self.vu_common.virtio_common.dup_eventfds();
let mut handler = self.vu_common.activate(
mem,
&queues,
interrupt_cb,
self.common.acked_features,
self.vu_common.virtio_common.acked_features,
backend_req_handler,
kill_evt,
pause_evt,
)?;
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
let paused = self.vu_common.virtio_common.paused.clone();
let paused_sync = self.vu_common.virtio_common.paused_sync.clone();
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
@@ -297,8 +298,8 @@ impl VirtioDevice for Fs {
fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
// We first must resume the virtio thread if it was paused.
if self.common.pause_evt.take().is_some() {
self.common.resume().ok()?;
if self.vu_common.virtio_common.pause_evt.take().is_some() {
self.vu_common.virtio_common.resume().ok()?;
}
if let Some(vu) = &self.vu_common.vu
@@ -308,7 +309,7 @@ impl VirtioDevice for Fs {
return None;
}
if let Some(kill_evt) = self.common.kill_evt.take() {
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take() {
// Ignore the result because there is nothing we can do about it.
let _ = kill_evt.write(1);
}
@@ -316,7 +317,7 @@ impl VirtioDevice for Fs {
event!("virtio-device", "reset", "id", &self.id);
// Return the interrupt
Some(self.common.interrupt_cb.take().unwrap())
Some(self.vu_common.virtio_common.interrupt_cb.take().unwrap())
}
fn shutdown(&mut self) {
@@ -364,11 +365,11 @@ impl VirtioDevice for Fs {
impl Pausable for Fs {
fn pause(&mut self) -> result::Result<(), MigratableError> {
self.vu_common.pause()?;
self.common.pause()
self.vu_common.virtio_common.pause()
}
fn resume(&mut self) -> result::Result<(), MigratableError> {
self.common.resume()?;
self.vu_common.virtio_common.resume()?;
if let Some(epoll_thread) = &self.epoll_thread {
epoll_thread.thread().unpark();
@@ -407,7 +408,6 @@ impl Migratable for Fs {
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common
.complete_migration(self.common.kill_evt.take())
self.vu_common.complete_migration()
}
}

View File

@@ -34,7 +34,6 @@ pub type State = VhostUserState<()>;
struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}
pub struct GenericVhostUser {
common: VirtioCommon,
vu_common: VhostUserCommon,
id: String,
// Hold ownership of the memory that is allocated for the device
@@ -138,17 +137,17 @@ since the backend only supports {backend_num_queues}\n",
};
Ok(GenericVhostUser {
common: VirtioCommon {
device_type,
avail_features,
acked_features,
queue_sizes: request_queue_sizes,
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: 1,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu_common: VhostUserCommon {
virtio_common: VirtioCommon {
device_type,
avail_features,
acked_features,
queue_sizes: request_queue_sizes,
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: 1,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu: Some(Arc::new(Mutex::new(vu))),
acked_protocol_features,
socket_path: path.to_string(),
@@ -168,7 +167,7 @@ since the backend only supports {backend_num_queues}\n",
}
fn state(&self) -> std::result::Result<State, MigratableError> {
self.vu_common.state(&self.common, ())
self.vu_common.state(())
}
#[cold]
@@ -189,11 +188,11 @@ space access. Reads will return 0xFF and writes will be ignored."
impl Drop for GenericVhostUser {
fn drop(&mut self) {
if let Some(kill_evt) = self.common.kill_evt.take() {
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take() {
// Ignore the result because there is nothing we can do about it.
let _ = kill_evt.write(1);
}
self.common.wait_for_epoll_threads();
self.vu_common.virtio_common.wait_for_epoll_threads();
if let Some(thread) = self.epoll_thread.take()
&& let Err(e) = thread.join()
{
@@ -204,15 +203,15 @@ impl Drop for GenericVhostUser {
impl VirtioDevice for GenericVhostUser {
fn device_type(&self) -> u32 {
self.common.device_type
self.vu_common.virtio_common.device_type
}
fn queue_max_sizes(&self) -> &[u16] {
&self.common.queue_sizes
&self.vu_common.virtio_common.queue_sizes
}
fn features(&self) -> u64 {
let mut features = self.common.avail_features;
let mut features = self.vu_common.virtio_common.avail_features;
if self.iommu {
features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
}
@@ -220,7 +219,7 @@ impl VirtioDevice for GenericVhostUser {
}
fn ack_features(&mut self, value: u64) {
self.common.ack_features(value);
self.vu_common.virtio_common.ack_features(value);
}
fn read_config(&self, offset: u64, data: &mut [u8]) {
@@ -282,26 +281,28 @@ impl VirtioDevice for GenericVhostUser {
queues,
..
} = context;
self.common.activate(&queues, interrupt_cb.clone())?;
self.vu_common
.virtio_common
.activate(&queues, interrupt_cb.clone())?;
self.guest_memory = Some(mem.clone());
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None;
// Run a dedicated thread for handling potential reconnections with
// the backend.
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let (kill_evt, pause_evt) = self.vu_common.virtio_common.dup_eventfds();
let mut handler = self.vu_common.activate(
mem,
&queues,
interrupt_cb,
self.common.acked_features,
self.vu_common.virtio_common.acked_features,
backend_req_handler,
kill_evt,
pause_evt,
)?;
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
let paused = self.vu_common.virtio_common.paused.clone();
let paused_sync = self.vu_common.virtio_common.paused_sync.clone();
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
@@ -320,8 +321,8 @@ impl VirtioDevice for GenericVhostUser {
fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
// We first must resume the virtio thread if it was paused.
if self.common.pause_evt.take().is_some() {
self.common.resume().ok()?;
if self.vu_common.virtio_common.pause_evt.take().is_some() {
self.vu_common.virtio_common.resume().ok()?;
}
if let Some(vu) = &self.vu_common.vu
@@ -331,7 +332,7 @@ impl VirtioDevice for GenericVhostUser {
return None;
}
if let Some(kill_evt) = self.common.kill_evt.take() {
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take() {
// Ignore the result because there is nothing we can do about it.
let _ = kill_evt.write(1);
}
@@ -339,7 +340,7 @@ impl VirtioDevice for GenericVhostUser {
event!("virtio-device", "reset", "id", &self.id);
// Return the interrupt
Some(self.common.interrupt_cb.take().unwrap())
Some(self.vu_common.virtio_common.interrupt_cb.take().unwrap())
}
fn shutdown(&mut self) {
@@ -387,11 +388,11 @@ impl VirtioDevice for GenericVhostUser {
impl Pausable for GenericVhostUser {
fn pause(&mut self) -> result::Result<(), MigratableError> {
self.vu_common.pause()?;
self.common.pause()
self.vu_common.virtio_common.pause()
}
fn resume(&mut self) -> result::Result<(), MigratableError> {
self.common.resume()?;
self.vu_common.virtio_common.resume()?;
if let Some(epoll_thread) = &self.epoll_thread {
epoll_thread.thread().unpark();
@@ -430,7 +431,6 @@ impl Migratable for GenericVhostUser {
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common
.complete_migration(self.common.kill_evt.take())
self.vu_common.complete_migration()
}
}

View File

@@ -29,7 +29,7 @@ use crate::{
ActivateError, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
GuestMemoryMmap, GuestRegionMmap, VIRTIO_F_IN_ORDER, VIRTIO_F_NOTIFICATION_DATA,
VIRTIO_F_ORDER_PLATFORM, VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_RING_INDIRECT_DESC,
VIRTIO_F_VERSION_1, VirtioInterrupt,
VIRTIO_F_VERSION_1, VirtioCommon, VirtioInterrupt,
};
pub mod blk;
@@ -336,6 +336,7 @@ impl<C> VhostUserState<C> {
#[derive(Default)]
pub struct VhostUserCommon {
pub virtio_common: VirtioCommon,
pub vu: Option<Arc<Mutex<VhostUserHandle>>>,
pub acked_protocol_features: u64,
pub socket_path: String,
@@ -485,12 +486,11 @@ impl VhostUserCommon {
pub fn state<C: Default>(
&self,
common: &crate::VirtioCommon,
config: C,
) -> std::result::Result<VhostUserState<C>, MigratableError> {
let mut state = VhostUserState {
avail_features: common.avail_features,
acked_features: common.acked_features,
avail_features: self.virtio_common.avail_features,
acked_features: self.virtio_common.acked_features,
config,
acked_protocol_features: self.acked_protocol_features,
vu_num_queues: self.vu_num_queues,
@@ -586,15 +586,12 @@ impl VhostUserCommon {
Ok(())
}
pub fn complete_migration(
&mut self,
kill_evt: Option<EventFd>,
) -> std::result::Result<(), MigratableError> {
pub fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.migration_started = false;
// Make sure the device thread is killed in order to prevent from
// reconnections to the socket.
if let Some(kill_evt) = kill_evt {
if let Some(kill_evt) = self.virtio_common.kill_evt.take() {
kill_evt.write(1).map_err(|e| {
MigratableError::CompleteMigration(anyhow!(
"Error killing vhost-user thread: {e:?}"

View File

@@ -41,7 +41,6 @@ struct BackendReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {}
pub struct Net {
common: VirtioCommon,
vu_common: VhostUserCommon,
id: String,
config: VirtioNetConfig,
@@ -198,17 +197,17 @@ impl Net {
Ok(Net {
id,
common: VirtioCommon {
device_type: VirtioDeviceType::Net as u32,
queue_sizes: vec![vu_cfg.queue_size; num_queues],
avail_features,
acked_features,
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: DEFAULT_QUEUE_NUMBER as u16,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu_common: VhostUserCommon {
virtio_common: VirtioCommon {
device_type: VirtioDeviceType::Net as u32,
queue_sizes: vec![vu_cfg.queue_size; num_queues],
avail_features,
acked_features,
paused_sync: Some(Arc::new(Barrier::new(2))),
min_queues: DEFAULT_QUEUE_NUMBER as u16,
paused: Arc::new(AtomicBool::new(paused)),
..Default::default()
},
vu: Some(Arc::new(Mutex::new(vu))),
acked_protocol_features,
socket_path: vu_cfg.socket,
@@ -228,19 +227,19 @@ impl Net {
}
fn state(&self) -> std::result::Result<State, MigratableError> {
self.vu_common.state(&self.common, self.config)
self.vu_common.state(self.config)
}
}
impl Drop for Net {
fn drop(&mut self) {
if let Some(kill_evt) = self.common.kill_evt.take()
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take()
&& let Err(e) = kill_evt.write(1)
{
error!("failed to kill vhost-user-net: {e:?}");
}
self.common.wait_for_epoll_threads();
self.vu_common.virtio_common.wait_for_epoll_threads();
if let Some(thread) = self.epoll_thread.take()
&& let Err(e) = thread.join()
@@ -258,15 +257,15 @@ impl Drop for Net {
impl VirtioDevice for Net {
fn device_type(&self) -> u32 {
self.common.device_type
self.vu_common.virtio_common.device_type
}
fn queue_max_sizes(&self) -> &[u16] {
&self.common.queue_sizes
&self.vu_common.virtio_common.queue_sizes
}
fn features(&self) -> u64 {
let mut features = self.common.avail_features;
let mut features = self.vu_common.virtio_common.avail_features;
if self.iommu {
features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
}
@@ -274,7 +273,7 @@ impl VirtioDevice for Net {
}
fn ack_features(&mut self, value: u64) {
self.common.ack_features(value);
self.vu_common.virtio_common.ack_features(value);
}
fn read_config(&self, offset: u64, data: &mut [u8]) {
@@ -288,18 +287,28 @@ impl VirtioDevice for Net {
mut queues,
..
} = context;
self.common.activate(&queues, interrupt_cb.clone())?;
self.vu_common
.virtio_common
.activate(&queues, interrupt_cb.clone())?;
self.guest_memory = Some(mem.clone());
let num_queues = queues.len();
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
if self.common.feature_acked(VIRTIO_NET_F_CTRL_VQ.into()) && !num_queues.is_multiple_of(2) {
let event_idx = self
.vu_common
.virtio_common
.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
if self
.vu_common
.virtio_common
.feature_acked(VIRTIO_NET_F_CTRL_VQ.into())
&& !num_queues.is_multiple_of(2)
{
let ctrl_queue_index = num_queues - 1;
let (_, mut ctrl_queue, ctrl_queue_evt) = queues.remove(ctrl_queue_index);
ctrl_queue.set_event_idx(event_idx);
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let (kill_evt, pause_evt) = self.vu_common.virtio_common.dup_eventfds();
let mut ctrl_handler = NetCtrlEpollHandler {
mem: mem.clone(),
@@ -313,12 +322,12 @@ impl VirtioDevice for Net {
queue_index: ctrl_queue_index as u16,
};
let paused = self.common.paused.clone();
let paused = self.vu_common.virtio_common.paused.clone();
// Let's update the barrier as we need 1 for the control queue
// thread + 1 for the common vhost-user thread + 1 for the main
// thread signalling the pause.
self.common.paused_sync = Some(Arc::new(Barrier::new(3)));
let paused_sync = self.common.paused_sync.clone();
self.vu_common.virtio_common.paused_sync = Some(Arc::new(Barrier::new(3)));
let paused_sync = self.vu_common.virtio_common.paused_sync.clone();
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
@@ -336,11 +345,12 @@ impl VirtioDevice for Net {
// The backend acknowledged features must not contain VIRTIO_NET_F_MAC
// since we don't expect the backend to handle it.
let backend_acked_features = self.common.acked_features & !(1 << VIRTIO_NET_F_MAC);
let backend_acked_features =
self.vu_common.virtio_common.acked_features & !(1 << VIRTIO_NET_F_MAC);
// Run a dedicated thread for handling potential reconnections with
// the backend.
let (kill_evt, pause_evt) = self.common.dup_eventfds();
let (kill_evt, pause_evt) = self.vu_common.virtio_common.dup_eventfds();
let mut handler = self.vu_common.activate(
mem,
@@ -352,8 +362,8 @@ impl VirtioDevice for Net {
pause_evt,
)?;
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
let paused = self.vu_common.virtio_common.paused.clone();
let paused_sync = self.vu_common.virtio_common.paused_sync.clone();
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
@@ -371,8 +381,8 @@ impl VirtioDevice for Net {
fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
// We first must resume the virtio thread if it was paused.
if self.common.pause_evt.take().is_some() {
self.common.resume().ok()?;
if self.vu_common.virtio_common.pause_evt.take().is_some() {
self.vu_common.virtio_common.resume().ok()?;
}
if let Some(vu) = &self.vu_common.vu
@@ -382,7 +392,7 @@ impl VirtioDevice for Net {
return None;
}
if let Some(kill_evt) = self.common.kill_evt.take() {
if let Some(kill_evt) = self.vu_common.virtio_common.kill_evt.take() {
// Ignore the result because there is nothing we can do about it.
let _ = kill_evt.write(1);
}
@@ -390,7 +400,7 @@ impl VirtioDevice for Net {
event!("virtio-device", "reset", "id", &self.id);
// Return the interrupt
Some(self.common.interrupt_cb.take().unwrap())
Some(self.vu_common.virtio_common.interrupt_cb.take().unwrap())
}
fn shutdown(&mut self) {
@@ -408,11 +418,11 @@ impl VirtioDevice for Net {
impl Pausable for Net {
fn pause(&mut self) -> result::Result<(), MigratableError> {
self.vu_common.pause()?;
self.common.pause()
self.vu_common.virtio_common.pause()
}
fn resume(&mut self) -> result::Result<(), MigratableError> {
self.common.resume()?;
self.vu_common.virtio_common.resume()?;
if let Some(epoll_thread) = &self.epoll_thread {
epoll_thread.thread().unpark();
@@ -455,7 +465,6 @@ impl Migratable for Net {
}
fn complete_migration(&mut self) -> std::result::Result<(), MigratableError> {
self.vu_common
.complete_migration(self.common.kill_evt.take())
self.vu_common.complete_migration()
}
}