virtio-devices: Use a common method for spawning virtio threads

Introduce a common solution for spawning the virtio threads which will
make it easier to add the panic handling.

During this effort I discovered that there were no seccomp filters
registered for the vhost-user-net thread nor the vhost-user-block
thread. This change also incorporates basic seccomp filters for those as
part of the refactoring.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford
2021-09-03 11:43:30 +01:00
parent 4737679661
commit 54e523c302
17 changed files with 311 additions and 316 deletions
+25 -14
View File
@@ -1,15 +1,16 @@
// Copyright 2019 Intel Corporation. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use super::super::{
ActivateError, ActivateResult, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType,
};
use super::super::{ActivateResult, Queue, VirtioCommon, VirtioDevice, VirtioDeviceType};
use super::vu_common_ctrl::{VhostUserConfig, VhostUserHandle};
use super::{Error, Result, DEFAULT_VIRTIO_FEATURES};
use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::vhost_user::VhostUserCommon;
use crate::VirtioInterrupt;
use crate::{GuestMemoryMmap, GuestRegionMmap};
use block_util::VirtioBlockConfig;
use seccompiler::SeccompAction;
use std::mem;
use std::result;
use std::sync::{Arc, Barrier, Mutex};
@@ -57,11 +58,17 @@ pub struct Blk {
config: VirtioBlockConfig,
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
epoll_thread: Option<thread::JoinHandle<()>>,
seccomp_action: SeccompAction,
}
impl Blk {
/// Create a new vhost-user-blk device
pub fn new(id: String, vu_cfg: VhostUserConfig, restoring: bool) -> Result<Blk> {
pub fn new(
id: String,
vu_cfg: VhostUserConfig,
restoring: bool,
seccomp_action: SeccompAction,
) -> Result<Blk> {
let num_queues = vu_cfg.num_queues;
if restoring {
@@ -85,6 +92,7 @@ impl Blk {
config: VirtioBlockConfig::default(),
guest_memory: None,
epoll_thread: None,
seccomp_action,
});
}
@@ -171,6 +179,7 @@ impl Blk {
config,
guest_memory: None,
epoll_thread: None,
seccomp_action,
})
}
@@ -298,18 +307,20 @@ impl VirtioDevice for Blk {
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
thread::Builder::new()
.name(self.id.to_string())
.spawn(move || {
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
&self.id,
&self.seccomp_action,
Thread::VirtioVhostBlock,
&mut epoll_threads,
move || {
if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running vhost-user-blk worker: {:?}", e);
error!("Error running worker: {:?}", e);
}
})
.map(|thread| self.epoll_thread = Some(thread))
.map_err(|e| {
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
},
)?;
self.epoll_thread = Some(epoll_threads.remove(0));
Ok(())
}
+14 -22
View File
@@ -3,7 +3,8 @@
use super::vu_common_ctrl::VhostUserHandle;
use super::{Error, Result, DEFAULT_VIRTIO_FEATURES};
use crate::seccomp_filters::{get_seccomp_filter, Thread};
use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::vhost_user::VhostUserCommon;
use crate::{
ActivateError, ActivateResult, Queue, UserspaceMapping, VirtioCommon, VirtioDevice,
@@ -11,7 +12,7 @@ use crate::{
};
use crate::{GuestMemoryMmap, GuestRegionMmap, MmapRegion};
use libc::{self, c_void, off64_t, pread64, pwrite64};
use seccompiler::{apply_filter, SeccompAction};
use seccompiler::SeccompAction;
use std::io;
use std::os::unix::io::AsRawFd;
use std::result;
@@ -549,28 +550,19 @@ impl VirtioDevice for Fs {
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
let virtio_vhost_fs_seccomp_filter =
get_seccomp_filter(&self.seccomp_action, Thread::VirtioVhostFs)
.map_err(ActivateError::CreateSeccompFilter)?;
thread::Builder::new()
.name(self.id.to_string())
.spawn(move || {
if !virtio_vhost_fs_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_vhost_fs_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
&self.id,
&self.seccomp_action,
Thread::VirtioVhostFs,
&mut epoll_threads,
move || {
if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running vhost-user-fs worker: {:?}", e);
error!("Error running worker: {:?}", e);
}
})
.map(|thread| self.epoll_thread = Some(thread))
.map_err(|e| {
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
},
)?;
self.epoll_thread = Some(epoll_threads.remove(0));
event!("virtio-device", "activated", "id", &self.id);
Ok(())
+26 -33
View File
@@ -1,17 +1,18 @@
// Copyright 2019 Intel Corporation. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use crate::seccomp_filters::{get_seccomp_filter, Thread};
use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread;
use crate::vhost_user::vu_common_ctrl::{VhostUserConfig, VhostUserHandle};
use crate::vhost_user::{Error, Result, VhostUserCommon};
use crate::{
ActivateError, ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue,
VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterrupt, EPOLL_HELPER_EVENT_LAST,
ActivateResult, EpollHelper, EpollHelperError, EpollHelperHandler, Queue, VirtioCommon,
VirtioDevice, VirtioDeviceType, VirtioInterrupt, EPOLL_HELPER_EVENT_LAST,
VIRTIO_F_RING_EVENT_IDX, VIRTIO_F_VERSION_1,
};
use crate::{GuestMemoryMmap, GuestRegionMmap};
use net_util::{build_net_config_space, CtrlQueue, MacAddr, VirtioNetConfig};
use seccompiler::{apply_filter, SeccompAction};
use seccompiler::SeccompAction;
use std::os::unix::io::AsRawFd;
use std::result;
use std::sync::atomic::AtomicBool;
@@ -332,28 +333,19 @@ impl VirtioDevice for Net {
self.common.paused_sync = Some(Arc::new(Barrier::new(3)));
let paused_sync = self.common.paused_sync.clone();
// Retrieve seccomp filter for virtio_net_ctl thread
let virtio_vhost_net_ctl_seccomp_filter =
get_seccomp_filter(&self.seccomp_action, Thread::VirtioVhostNetCtl)
.map_err(ActivateError::CreateSeccompFilter)?;
thread::Builder::new()
.name(format!("{}_ctrl", self.id))
.spawn(move || {
if !virtio_vhost_net_ctl_seccomp_filter.is_empty() {
if let Err(e) = apply_filter(&virtio_vhost_net_ctl_seccomp_filter) {
error!("Error applying seccomp filter: {:?}", e);
return;
}
}
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
&format!("{}_ctrl", &self.id),
&self.seccomp_action,
Thread::VirtioVhostNetCtl,
&mut epoll_threads,
move || {
if let Err(e) = ctrl_handler.run_ctrl(paused, paused_sync.unwrap()) {
error!("Error running worker: {:?}", e);
}
})
.map(|thread| self.ctrl_queue_epoll_thread = Some(thread))
.map_err(|e| {
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
},
)?;
self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
}
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
@@ -383,18 +375,19 @@ impl VirtioDevice for Net {
let paused = self.common.paused.clone();
let paused_sync = self.common.paused_sync.clone();
thread::Builder::new()
.name(self.id.to_string())
.spawn(move || {
let mut epoll_threads = Vec::new();
spawn_virtio_thread(
&self.id,
&self.seccomp_action,
Thread::VirtioVhostNet,
&mut epoll_threads,
move || {
if let Err(e) = handler.run(paused, paused_sync.unwrap()) {
error!("Error running vhost-user-net worker: {:?}", e);
error!("Error running worker: {:?}", e);
}
})
.map(|thread| self.epoll_thread = Some(thread))
.map_err(|e| {
error!("failed to clone queue EventFd: {}", e);
ActivateError::BadActivate
})?;
},
)?;
self.epoll_thread = Some(epoll_threads.remove(0));
Ok(())
}