2019-10-31 15:54:53 +00:00
|
|
|
// Copyright 2019 Intel Corporation. All Rights Reserved.
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: (Apache-2.0 AND BSD-3-Clause)
|
|
|
|
|
|
|
|
#[macro_use(crate_version, crate_authors)]
|
|
|
|
extern crate clap;
|
|
|
|
extern crate log;
|
|
|
|
extern crate vhost_rs;
|
|
|
|
extern crate vhost_user_backend;
|
|
|
|
extern crate vm_virtio;
|
|
|
|
|
|
|
|
use clap::{App, Arg};
|
2020-03-12 13:31:11 +00:00
|
|
|
use futures::executor::{ThreadPool, ThreadPoolBuilder};
|
2019-10-31 15:54:53 +00:00
|
|
|
use libc::EFD_NONBLOCK;
|
|
|
|
use log::*;
|
2020-05-01 16:26:07 +00:00
|
|
|
use seccomp::SeccompAction;
|
2020-02-21 11:14:20 +00:00
|
|
|
use std::num::Wrapping;
|
2020-04-08 16:27:26 +00:00
|
|
|
use std::sync::{Arc, Mutex, RwLock};
|
2019-10-31 15:54:53 +00:00
|
|
|
use std::{convert, error, fmt, io, process};
|
|
|
|
|
|
|
|
use vhost_rs::vhost_user::message::*;
|
2020-04-24 11:33:00 +00:00
|
|
|
use vhost_rs::vhost_user::{Listener, SlaveFsCacheReq};
|
2019-10-31 15:54:53 +00:00
|
|
|
use vhost_user_backend::{VhostUserBackend, VhostUserDaemon, Vring};
|
2020-02-21 11:14:20 +00:00
|
|
|
use vhost_user_fs::descriptor_utils::Error as VufDescriptorError;
|
2019-10-31 15:54:53 +00:00
|
|
|
use vhost_user_fs::descriptor_utils::{Reader, Writer};
|
|
|
|
use vhost_user_fs::filesystem::FileSystem;
|
|
|
|
use vhost_user_fs::passthrough::{self, PassthroughFs};
|
2020-04-24 11:43:36 +00:00
|
|
|
use vhost_user_fs::sandbox::Sandbox;
|
2020-05-01 16:26:07 +00:00
|
|
|
use vhost_user_fs::seccomp::enable_seccomp;
|
2019-10-31 15:54:53 +00:00
|
|
|
use vhost_user_fs::server::Server;
|
|
|
|
use vhost_user_fs::Error as VhostUserFsError;
|
|
|
|
use virtio_bindings::bindings::virtio_net::*;
|
2020-02-21 11:14:20 +00:00
|
|
|
use virtio_bindings::bindings::virtio_ring::{
|
|
|
|
VIRTIO_RING_F_EVENT_IDX, VIRTIO_RING_F_INDIRECT_DESC,
|
|
|
|
};
|
2020-03-12 13:31:11 +00:00
|
|
|
use vm_memory::{GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
|
|
|
|
use vm_virtio::queue::DescriptorChain;
|
2019-10-31 15:54:53 +00:00
|
|
|
use vmm_sys_util::eventfd::EventFd;
|
|
|
|
|
|
|
|
const QUEUE_SIZE: usize = 1024;
|
|
|
|
const NUM_QUEUES: usize = 2;
|
2020-03-12 13:31:11 +00:00
|
|
|
const THREAD_POOL_SIZE: usize = 64;
|
2019-10-31 15:54:53 +00:00
|
|
|
|
|
|
|
// The guest queued an available buffer for the high priority queue.
|
|
|
|
const HIPRIO_QUEUE_EVENT: u16 = 0;
|
|
|
|
// The guest queued an available buffer for the request queue.
|
|
|
|
const REQ_QUEUE_EVENT: u16 = 1;
|
|
|
|
// The device has been dropped.
|
|
|
|
const KILL_EVENT: u16 = 2;
|
|
|
|
|
|
|
|
type Result<T> = std::result::Result<T, Error>;
|
|
|
|
type VhostUserBackendResult<T> = std::result::Result<T, std::io::Error>;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum Error {
|
|
|
|
/// Failed to create kill eventfd.
|
2020-01-24 07:50:30 +00:00
|
|
|
CreateKillEventFd(io::Error),
|
2020-03-12 13:31:11 +00:00
|
|
|
/// Failed to create thread pool.
|
|
|
|
CreateThreadPool(io::Error),
|
2019-10-31 15:54:53 +00:00
|
|
|
/// Failed to handle event other than input event.
|
|
|
|
HandleEventNotEpollIn,
|
|
|
|
/// Failed to handle unknown event.
|
|
|
|
HandleEventUnknownEvent,
|
|
|
|
/// No memory configured.
|
|
|
|
NoMemoryConfigured,
|
|
|
|
/// Processing queue failed.
|
|
|
|
ProcessQueue(VhostUserFsError),
|
2020-02-21 11:14:20 +00:00
|
|
|
/// Creating a queue reader failed.
|
|
|
|
QueueReader(VufDescriptorError),
|
|
|
|
/// Creating a queue writer failed.
|
|
|
|
QueueWriter(VufDescriptorError),
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Error {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(f, "vhost_user_fs_error: {:?}", self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl error::Error for Error {}
|
|
|
|
|
|
|
|
impl convert::From<Error> for io::Error {
|
|
|
|
fn from(e: Error) -> Self {
|
|
|
|
io::Error::new(io::ErrorKind::Other, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 16:27:26 +00:00
|
|
|
struct VhostUserFsThread<F: FileSystem + Send + Sync + 'static> {
|
2020-03-12 13:31:11 +00:00
|
|
|
mem: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
2019-10-31 15:54:53 +00:00
|
|
|
kill_evt: EventFd,
|
|
|
|
server: Arc<Server<F>>,
|
2020-02-12 23:15:04 +00:00
|
|
|
// handle request from slave to master
|
|
|
|
vu_req: Option<SlaveFsCacheReq>,
|
2020-02-21 11:14:20 +00:00
|
|
|
event_idx: bool,
|
2020-03-12 13:31:11 +00:00
|
|
|
pool: ThreadPool,
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
|
2020-04-08 16:27:26 +00:00
|
|
|
impl<F: FileSystem + Send + Sync + 'static> Clone for VhostUserFsThread<F> {
|
2019-10-31 15:54:53 +00:00
|
|
|
fn clone(&self) -> Self {
|
2020-04-08 16:27:26 +00:00
|
|
|
VhostUserFsThread {
|
2019-10-31 15:54:53 +00:00
|
|
|
mem: self.mem.clone(),
|
|
|
|
kill_evt: self.kill_evt.try_clone().unwrap(),
|
|
|
|
server: self.server.clone(),
|
2020-02-12 23:15:04 +00:00
|
|
|
vu_req: self.vu_req.clone(),
|
2020-02-21 11:14:20 +00:00
|
|
|
event_idx: self.event_idx,
|
2020-03-12 13:31:11 +00:00
|
|
|
pool: self.pool.clone(),
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 16:27:26 +00:00
|
|
|
impl<F: FileSystem + Send + Sync + 'static> VhostUserFsThread<F> {
|
2020-03-12 13:31:11 +00:00
|
|
|
fn new(fs: F, thread_pool_size: usize) -> Result<Self> {
|
2020-04-08 16:27:26 +00:00
|
|
|
Ok(VhostUserFsThread {
|
2019-10-31 15:54:53 +00:00
|
|
|
mem: None,
|
2020-01-24 07:50:30 +00:00
|
|
|
kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?,
|
2019-10-31 15:54:53 +00:00
|
|
|
server: Arc::new(Server::new(fs)),
|
2020-02-12 23:15:04 +00:00
|
|
|
vu_req: None,
|
2020-02-21 11:14:20 +00:00
|
|
|
event_idx: false,
|
2020-03-12 13:31:11 +00:00
|
|
|
pool: ThreadPoolBuilder::new()
|
|
|
|
.pool_size(thread_pool_size)
|
|
|
|
.create()
|
|
|
|
.map_err(Error::CreateThreadPool)?,
|
2019-10-31 15:54:53 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-03-12 13:31:11 +00:00
|
|
|
fn process_queue(&mut self, vring_lock: Arc<RwLock<Vring>>) -> Result<bool> {
|
2020-02-21 11:14:20 +00:00
|
|
|
let mut used_any = false;
|
2020-03-12 13:31:11 +00:00
|
|
|
let (atomic_mem, mem) = match &self.mem {
|
|
|
|
Some(m) => (m, m.memory()),
|
|
|
|
None => return Err(Error::NoMemoryConfigured),
|
|
|
|
};
|
|
|
|
let mut vring = vring_lock.write().unwrap();
|
2019-10-31 15:54:53 +00:00
|
|
|
|
|
|
|
while let Some(avail_desc) = vring.mut_queue().iter(&mem).next() {
|
2020-03-12 13:31:11 +00:00
|
|
|
used_any = true;
|
|
|
|
|
|
|
|
// Prepare a set of objects that can be moved to the worker thread.
|
|
|
|
let desc_head = avail_desc.get_head();
|
|
|
|
let atomic_mem = atomic_mem.clone();
|
|
|
|
let server = self.server.clone();
|
|
|
|
let mut vu_req = self.vu_req.clone();
|
|
|
|
let event_idx = self.event_idx;
|
|
|
|
let vring_lock = vring_lock.clone();
|
|
|
|
|
|
|
|
self.pool.spawn_ok(async move {
|
|
|
|
let mem = atomic_mem.memory();
|
|
|
|
let desc = DescriptorChain::new_from_head(&mem, desc_head).unwrap();
|
|
|
|
let head_index = desc.index;
|
|
|
|
|
|
|
|
let reader = Reader::new(&mem, desc.clone())
|
|
|
|
.map_err(Error::QueueReader)
|
|
|
|
.unwrap();
|
|
|
|
let writer = Writer::new(&mem, desc.clone())
|
|
|
|
.map_err(Error::QueueWriter)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
server
|
|
|
|
.handle_message(reader, writer, vu_req.as_mut())
|
|
|
|
.map_err(Error::ProcessQueue)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let mut vring = vring_lock.write().unwrap();
|
|
|
|
|
|
|
|
if event_idx {
|
2020-05-20 09:40:54 +00:00
|
|
|
let queue = vring.mut_queue();
|
|
|
|
if let Some(used_idx) = queue.add_used(&mem, head_index, 0) {
|
|
|
|
if queue.needs_notification(&mem, Wrapping(used_idx)) {
|
2020-03-12 13:31:11 +00:00
|
|
|
vring.signal_used_queue().unwrap();
|
|
|
|
}
|
2020-02-21 11:14:20 +00:00
|
|
|
}
|
2020-03-12 13:31:11 +00:00
|
|
|
} else {
|
|
|
|
vring.mut_queue().add_used(&mem, head_index, 0);
|
|
|
|
vring.signal_used_queue().unwrap();
|
2020-02-21 11:14:20 +00:00
|
|
|
}
|
2020-03-12 13:31:11 +00:00
|
|
|
});
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
|
2020-02-21 11:14:20 +00:00
|
|
|
Ok(used_any)
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 16:27:26 +00:00
|
|
|
struct VhostUserFsBackend<F: FileSystem + Send + Sync + 'static> {
|
|
|
|
thread: Mutex<VhostUserFsThread<F>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: FileSystem + Send + Sync + 'static> VhostUserFsBackend<F> {
|
|
|
|
fn new(fs: F, thread_pool_size: usize) -> Result<Self> {
|
|
|
|
let thread = Mutex::new(VhostUserFsThread::new(fs, thread_pool_size)?);
|
|
|
|
Ok(VhostUserFsBackend { thread })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 15:54:53 +00:00
|
|
|
impl<F: FileSystem + Send + Sync + 'static> VhostUserBackend for VhostUserFsBackend<F> {
|
|
|
|
fn num_queues(&self) -> usize {
|
|
|
|
NUM_QUEUES
|
|
|
|
}
|
|
|
|
|
|
|
|
fn max_queue_size(&self) -> usize {
|
|
|
|
QUEUE_SIZE
|
|
|
|
}
|
|
|
|
|
|
|
|
fn features(&self) -> u64 {
|
2020-02-21 10:54:35 +00:00
|
|
|
1 << VIRTIO_F_VERSION_1
|
|
|
|
| 1 << VIRTIO_RING_F_INDIRECT_DESC
|
2020-02-21 11:14:20 +00:00
|
|
|
| 1 << VIRTIO_RING_F_EVENT_IDX
|
2020-02-21 10:54:35 +00:00
|
|
|
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits()
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn protocol_features(&self) -> VhostUserProtocolFeatures {
|
2020-02-21 11:03:52 +00:00
|
|
|
VhostUserProtocolFeatures::MQ | VhostUserProtocolFeatures::SLAVE_REQ
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
|
2020-02-21 11:14:20 +00:00
|
|
|
fn set_event_idx(&mut self, enabled: bool) {
|
2020-04-08 16:27:26 +00:00
|
|
|
self.thread.lock().unwrap().event_idx = enabled;
|
2020-02-21 11:14:20 +00:00
|
|
|
}
|
2020-02-14 11:27:47 +00:00
|
|
|
|
2019-10-31 15:54:53 +00:00
|
|
|
fn update_memory(&mut self, mem: GuestMemoryMmap) -> VhostUserBackendResult<()> {
|
2020-04-08 16:27:26 +00:00
|
|
|
self.thread.lock().unwrap().mem = Some(GuestMemoryAtomic::new(mem));
|
2019-10-31 15:54:53 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_event(
|
2020-04-09 11:14:05 +00:00
|
|
|
&self,
|
2019-10-31 15:54:53 +00:00
|
|
|
device_event: u16,
|
|
|
|
evset: epoll::Events,
|
|
|
|
vrings: &[Arc<RwLock<Vring>>],
|
2020-04-09 16:20:38 +00:00
|
|
|
_thread_id: usize,
|
2019-10-31 15:54:53 +00:00
|
|
|
) -> VhostUserBackendResult<bool> {
|
|
|
|
if evset != epoll::Events::EPOLLIN {
|
|
|
|
return Err(Error::HandleEventNotEpollIn.into());
|
|
|
|
}
|
|
|
|
|
2020-04-08 16:27:26 +00:00
|
|
|
let mut thread = self.thread.lock().unwrap();
|
|
|
|
let mem = match &thread.mem {
|
2020-03-12 13:31:11 +00:00
|
|
|
Some(m) => m.memory(),
|
|
|
|
None => return Err(Error::NoMemoryConfigured.into()),
|
|
|
|
};
|
|
|
|
|
|
|
|
let vring_lock = match device_event {
|
2019-10-31 15:54:53 +00:00
|
|
|
HIPRIO_QUEUE_EVENT => {
|
|
|
|
debug!("HIPRIO_QUEUE_EVENT");
|
2020-03-12 13:31:11 +00:00
|
|
|
vrings[0].clone()
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
REQ_QUEUE_EVENT => {
|
2020-02-26 09:46:10 +00:00
|
|
|
debug!("QUEUE_EVENT");
|
2020-03-12 13:31:11 +00:00
|
|
|
vrings[1].clone()
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
_ => return Err(Error::HandleEventUnknownEvent.into()),
|
2020-02-26 09:46:10 +00:00
|
|
|
};
|
|
|
|
|
2020-04-08 16:27:26 +00:00
|
|
|
if thread.event_idx {
|
2020-02-26 09:46:10 +00:00
|
|
|
// vm-virtio's Queue implementation only checks avail_index
|
|
|
|
// once, so to properly support EVENT_IDX we need to keep
|
|
|
|
// calling process_queue() until it stops finding new
|
|
|
|
// requests on the queue.
|
|
|
|
loop {
|
2020-03-12 13:31:11 +00:00
|
|
|
{
|
|
|
|
let mut vring = vring_lock.write().unwrap();
|
|
|
|
vring.mut_queue().update_avail_event(&mem);
|
|
|
|
}
|
2020-04-08 16:27:26 +00:00
|
|
|
if !thread.process_queue(vring_lock.clone())? {
|
2020-02-26 09:46:10 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Without EVENT_IDX, a single call is enough.
|
2020-04-08 16:27:26 +00:00
|
|
|
thread.process_queue(vring_lock)?;
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(false)
|
|
|
|
}
|
2020-02-11 11:27:03 +00:00
|
|
|
|
2020-04-09 15:49:11 +00:00
|
|
|
fn exit_event(&self, _thread_index: usize) -> Option<(EventFd, Option<u16>)> {
|
2020-04-08 16:27:26 +00:00
|
|
|
Some((
|
|
|
|
self.thread.lock().unwrap().kill_evt.try_clone().unwrap(),
|
|
|
|
Some(KILL_EVENT),
|
|
|
|
))
|
2020-02-11 11:27:03 +00:00
|
|
|
}
|
2020-02-12 23:15:04 +00:00
|
|
|
|
|
|
|
fn set_slave_req_fd(&mut self, vu_req: SlaveFsCacheReq) {
|
2020-04-08 16:27:26 +00:00
|
|
|
self.thread.lock().unwrap().vu_req = Some(vu_req);
|
2020-02-12 23:15:04 +00:00
|
|
|
}
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let cmd_arguments = App::new("vhost-user-fs backend")
|
|
|
|
.version(crate_version!())
|
|
|
|
.author(crate_authors!())
|
|
|
|
.about("Launch a vhost-user-fs backend.")
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("shared-dir")
|
|
|
|
.long("shared-dir")
|
|
|
|
.help("Shared directory path")
|
|
|
|
.takes_value(true)
|
|
|
|
.min_values(1),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("sock")
|
|
|
|
.long("sock")
|
2020-06-04 22:10:42 +00:00
|
|
|
.help("vhost-user socket path (deprecated)")
|
|
|
|
.takes_value(true)
|
|
|
|
.min_values(1),
|
|
|
|
)
|
|
|
|
.arg(
|
|
|
|
Arg::with_name("socket")
|
|
|
|
.long("socket")
|
2019-10-31 15:54:53 +00:00
|
|
|
.help("vhost-user socket path")
|
|
|
|
.takes_value(true)
|
|
|
|
.min_values(1),
|
|
|
|
)
|
2020-03-12 13:31:11 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("thread-pool-size")
|
|
|
|
.long("thread-pool-size")
|
|
|
|
.help("thread pool size (default 64)")
|
|
|
|
.takes_value(true)
|
|
|
|
.min_values(1),
|
|
|
|
)
|
2020-03-12 14:22:06 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("disable-xattr")
|
|
|
|
.long("disable-xattr")
|
|
|
|
.help("Disable support for extended attributes"),
|
|
|
|
)
|
2020-04-24 11:43:36 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("disable-sandbox")
|
|
|
|
.long("disable-sandbox")
|
|
|
|
.help("Don't set up a sandbox for the daemon"),
|
|
|
|
)
|
2020-05-01 16:26:07 +00:00
|
|
|
.arg(
|
|
|
|
Arg::with_name("seccomp")
|
|
|
|
.long("seccomp")
|
|
|
|
.help("Disable/debug seccomp security")
|
|
|
|
.possible_values(&["kill", "log", "trap", "none"])
|
|
|
|
.default_value("kill"),
|
|
|
|
)
|
2019-10-31 15:54:53 +00:00
|
|
|
.get_matches();
|
|
|
|
|
|
|
|
// Retrieve arguments
|
2019-11-15 06:29:13 +00:00
|
|
|
let shared_dir = cmd_arguments
|
2019-10-31 15:54:53 +00:00
|
|
|
.value_of("shared-dir")
|
|
|
|
.expect("Failed to retrieve shared directory path");
|
2020-06-04 22:10:42 +00:00
|
|
|
let socket = match cmd_arguments.value_of("socket") {
|
|
|
|
Some(path) => path,
|
|
|
|
None => {
|
|
|
|
println!("warning: use of deprecated parameter '--sock': Please use the '--socket' option instead.");
|
|
|
|
cmd_arguments
|
|
|
|
.value_of("sock")
|
|
|
|
.expect("Failed to retrieve vhost-user socket path")
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-03-12 13:31:11 +00:00
|
|
|
let thread_pool_size: usize = match cmd_arguments.value_of("thread-pool-size") {
|
|
|
|
Some(size) => size.parse().expect("Invalid argument for thread-pool-size"),
|
|
|
|
None => THREAD_POOL_SIZE,
|
|
|
|
};
|
2020-03-12 14:22:06 +00:00
|
|
|
let xattr: bool = !cmd_arguments.is_present("disable-xattr");
|
2020-04-24 11:43:36 +00:00
|
|
|
let create_sandbox: bool = !cmd_arguments.is_present("disable-sandbox");
|
2020-05-01 16:26:07 +00:00
|
|
|
let seccomp_mode: SeccompAction = match cmd_arguments.value_of("seccomp").unwrap() {
|
|
|
|
"none" => SeccompAction::Allow, // i.e. no seccomp
|
|
|
|
"kill" => SeccompAction::Kill,
|
|
|
|
"log" => SeccompAction::Log,
|
|
|
|
"trap" => SeccompAction::Trap,
|
|
|
|
_ => unreachable!(), // We told Arg possible_values
|
|
|
|
};
|
2019-10-31 15:54:53 +00:00
|
|
|
|
2020-06-04 22:10:42 +00:00
|
|
|
let listener = Listener::new(socket, true).unwrap();
|
2019-10-31 15:54:53 +00:00
|
|
|
|
2020-04-24 11:43:36 +00:00
|
|
|
let fs_cfg = if create_sandbox {
|
|
|
|
let mut sandbox = Sandbox::new(shared_dir.to_string());
|
|
|
|
match sandbox.enter().unwrap() {
|
|
|
|
Some(child_pid) => {
|
|
|
|
unsafe { libc::waitpid(child_pid, std::ptr::null_mut(), 0) };
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
None => passthrough::Config {
|
|
|
|
root_dir: "/".to_string(),
|
|
|
|
xattr,
|
|
|
|
proc_sfd_rawfd: sandbox.get_proc_self_fd(),
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
passthrough::Config {
|
|
|
|
root_dir: shared_dir.to_string(),
|
|
|
|
xattr,
|
|
|
|
..Default::default()
|
|
|
|
}
|
2019-11-15 06:29:13 +00:00
|
|
|
};
|
2020-04-24 11:43:36 +00:00
|
|
|
|
2020-05-01 16:26:07 +00:00
|
|
|
// Must happen before we start the thread pool
|
|
|
|
if seccomp_mode != SeccompAction::Allow {
|
|
|
|
enable_seccomp(seccomp_mode).unwrap();
|
|
|
|
};
|
|
|
|
|
2019-11-15 06:29:13 +00:00
|
|
|
let fs = PassthroughFs::new(fs_cfg).unwrap();
|
2020-03-12 13:31:11 +00:00
|
|
|
let fs_backend = Arc::new(RwLock::new(
|
|
|
|
VhostUserFsBackend::new(fs, thread_pool_size).unwrap(),
|
|
|
|
));
|
2019-10-31 15:54:53 +00:00
|
|
|
|
2020-04-24 11:33:00 +00:00
|
|
|
let mut daemon =
|
|
|
|
VhostUserDaemon::new(String::from("vhost-user-fs-backend"), fs_backend.clone()).unwrap();
|
2019-10-31 15:54:53 +00:00
|
|
|
|
2020-04-24 11:33:00 +00:00
|
|
|
if let Err(e) = daemon.start(listener) {
|
2020-02-06 12:10:45 +00:00
|
|
|
error!("Failed to start daemon: {:?}", e);
|
2019-10-31 15:54:53 +00:00
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Err(e) = daemon.wait() {
|
2020-02-06 12:10:45 +00:00
|
|
|
error!("Waiting for daemon failed: {:?}", e);
|
2020-02-06 12:17:59 +00:00
|
|
|
}
|
|
|
|
|
2020-04-08 16:27:26 +00:00
|
|
|
let kill_evt = fs_backend
|
|
|
|
.read()
|
|
|
|
.unwrap()
|
|
|
|
.thread
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.kill_evt
|
|
|
|
.try_clone()
|
|
|
|
.unwrap();
|
2020-02-06 12:17:59 +00:00
|
|
|
if let Err(e) = kill_evt.write(1) {
|
|
|
|
error!("Error shutting down worker thread: {:?}", e)
|
2019-10-31 15:54:53 +00:00
|
|
|
}
|
|
|
|
}
|