vhost_user_fs: add the ability to set slave req fd

This adds the missing part of supporting virtiofs dax on the slave end,
that is, receiving a socket pair fd from the master end to set up a
communication channel for sending setupmapping & removemapping messages.

Signed-off-by: Liu Bo <bo.liu@linux.alibaba.com>
This commit is contained in:
Liu Bo 2020-02-12 15:15:04 -08:00 committed by Rob Bradford
parent 3f09eff6c5
commit 59958f0a61
3 changed files with 52 additions and 3 deletions

View File

@ -17,6 +17,7 @@ use std::sync::{Arc, RwLock};
use std::{convert, error, fmt, io, process}; use std::{convert, error, fmt, io, process};
use vhost_rs::vhost_user::message::*; use vhost_rs::vhost_user::message::*;
use vhost_rs::vhost_user::SlaveFsCacheReq;
use vhost_user_backend::{VhostUserBackend, VhostUserDaemon, Vring}; use vhost_user_backend::{VhostUserBackend, VhostUserDaemon, Vring};
use vhost_user_fs::descriptor_utils::{Reader, Writer}; use vhost_user_fs::descriptor_utils::{Reader, Writer};
use vhost_user_fs::filesystem::FileSystem; use vhost_user_fs::filesystem::FileSystem;
@ -72,6 +73,8 @@ struct VhostUserFsBackend<F: FileSystem + Send + Sync + 'static> {
mem: Option<GuestMemoryMmap>, mem: Option<GuestMemoryMmap>,
kill_evt: EventFd, kill_evt: EventFd,
server: Arc<Server<F>>, server: Arc<Server<F>>,
// handle request from slave to master
vu_req: Option<SlaveFsCacheReq>,
} }
impl<F: FileSystem + Send + Sync + 'static> Clone for VhostUserFsBackend<F> { impl<F: FileSystem + Send + Sync + 'static> Clone for VhostUserFsBackend<F> {
@ -80,6 +83,7 @@ impl<F: FileSystem + Send + Sync + 'static> Clone for VhostUserFsBackend<F> {
mem: self.mem.clone(), mem: self.mem.clone(),
kill_evt: self.kill_evt.try_clone().unwrap(), kill_evt: self.kill_evt.try_clone().unwrap(),
server: self.server.clone(), server: self.server.clone(),
vu_req: self.vu_req.clone(),
} }
} }
} }
@ -90,6 +94,7 @@ impl<F: FileSystem + Send + Sync + 'static> VhostUserFsBackend<F> {
mem: None, mem: None,
kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?, kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?,
server: Arc::new(Server::new(fs)), server: Arc::new(Server::new(fs)),
vu_req: None,
}) })
} }
@ -105,7 +110,7 @@ impl<F: FileSystem + Send + Sync + 'static> VhostUserFsBackend<F> {
let total = self let total = self
.server .server
.handle_message(reader, writer) .handle_message(reader, writer, self.vu_req.as_mut())
.map_err(Error::ProcessQueue)?; .map_err(Error::ProcessQueue)?;
used_desc_heads[used_count] = (head_index, total); used_desc_heads[used_count] = (head_index, total);
@ -173,6 +178,10 @@ impl<F: FileSystem + Send + Sync + 'static> VhostUserBackend for VhostUserFsBack
fn exit_event(&self) -> Option<(EventFd, Option<u16>)> { fn exit_event(&self) -> Option<(EventFd, Option<u16>)> {
Some((self.kill_evt.try_clone().unwrap(), Some(KILL_EVENT))) Some((self.kill_evt.try_clone().unwrap(), Some(KILL_EVENT)))
} }
fn set_slave_req_fd(&mut self, vu_req: SlaveFsCacheReq) {
self.vu_req = Some(vu_req);
}
} }
fn main() { fn main() {

View File

@ -4,12 +4,14 @@
//! Traits and Structs to handle vhost-user requests from the master to the slave. //! Traits and Structs to handle vhost-user requests from the master to the slave.
use std::mem; use std::mem;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::net::UnixStream;
use std::slice; use std::slice;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use super::connection::Endpoint; use super::connection::Endpoint;
use super::message::*; use super::message::*;
use super::slave_fs_cache::SlaveFsCacheReq;
use super::{Error, Result}; use super::{Error, Result};
/// Trait to handle vhost-user requests from the master to the slave. /// Trait to handle vhost-user requests from the master to the slave.
@ -47,6 +49,7 @@ pub trait VhostUserSlaveReqHandler {
flags: VhostUserConfigFlags, flags: VhostUserConfigFlags,
) -> Result<Vec<u8>>; ) -> Result<Vec<u8>>;
fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>; fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>;
fn set_slave_req_fd(&mut self, _vu_req: SlaveFsCacheReq) {}
} }
/// A vhost-user slave endpoint which relays all received requests from the /// A vhost-user slave endpoint which relays all received requests from the
@ -274,6 +277,14 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
self.check_request_size(&hdr, size, hdr.get_size() as usize)?; self.check_request_size(&hdr, size, hdr.get_size() as usize)?;
self.set_config(&hdr, size, &buf)?; self.set_config(&hdr, size, &buf)?;
} }
MasterReq::SET_SLAVE_REQ_FD => {
if self.acked_protocol_features & VhostUserProtocolFeatures::SLAVE_SEND_FD.bits()
== 0
{
return Err(Error::InvalidOperation);
}
self.set_slave_req_fd(&hdr, rfds)?;
}
_ => { _ => {
return Err(Error::InvalidMessage); return Err(Error::InvalidMessage);
} }
@ -405,6 +416,25 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
Ok(()) Ok(())
} }
fn set_slave_req_fd(
&mut self,
hdr: &VhostUserMsgHeader<MasterReq>,
rfds: Option<Vec<RawFd>>,
) -> Result<()> {
if let Some(fds) = rfds {
if fds.len() == 1 {
let sock = unsafe { UnixStream::from_raw_fd(fds[0]) };
let vu_req = SlaveFsCacheReq::from_stream(sock);
self.backend.lock().unwrap().set_slave_req_fd(vu_req);
self.send_ack_message(&hdr, Ok(()))
} else {
Err(Error::InvalidMessage)
}
} else {
Err(Error::InvalidMessage)
}
}
fn handle_vring_fd_request( fn handle_vring_fd_request(
&mut self, &mut self,
buf: &[u8], buf: &[u8],

View File

@ -20,7 +20,8 @@ use vhost_rs::vhost_user::message::{
VhostUserVirtioFeatures, VhostUserVringAddrFlags, VhostUserVringState, VhostUserVirtioFeatures, VhostUserVringAddrFlags, VhostUserVringState,
}; };
use vhost_rs::vhost_user::{ use vhost_rs::vhost_user::{
Error as VhostUserError, Result as VhostUserResult, SlaveListener, VhostUserSlaveReqHandler, Error as VhostUserError, Result as VhostUserResult, SlaveFsCacheReq, SlaveListener,
VhostUserSlaveReqHandler,
}; };
use vm_memory::guest_memory::FileOffset; use vm_memory::guest_memory::FileOffset;
use vm_memory::{GuestAddress, GuestMemoryMmap}; use vm_memory::{GuestAddress, GuestMemoryMmap};
@ -103,6 +104,11 @@ pub trait VhostUserBackend: Send + Sync + 'static {
fn exit_event(&self) -> Option<(EventFd, Option<u16>)> { fn exit_event(&self) -> Option<(EventFd, Option<u16>)> {
None None
} }
/// Set slave fd.
/// A default implementation is provided as we cannot expect all backends
/// to implement this function.
fn set_slave_req_fd(&mut self, _vu_req: SlaveFsCacheReq) {}
} }
/// This structure is the public API the backend is allowed to interact with /// This structure is the public API the backend is allowed to interact with
@ -779,6 +785,10 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandler for VhostUserHandler<S> {
.set_config(offset, buf) .set_config(offset, buf)
.map_err(VhostUserError::ReqHandlerError) .map_err(VhostUserError::ReqHandlerError)
} }
fn set_slave_req_fd(&mut self, vu_req: SlaveFsCacheReq) {
self.backend.write().unwrap().set_slave_req_fd(vu_req);
}
} }
impl<S: VhostUserBackend> Drop for VhostUserHandler<S> { impl<S: VhostUserBackend> Drop for VhostUserHandler<S> {