diff --git a/src/bin/vhost_user_fs.rs b/src/bin/vhost_user_fs.rs index 63b7db888..947e66ad2 100644 --- a/src/bin/vhost_user_fs.rs +++ b/src/bin/vhost_user_fs.rs @@ -17,6 +17,7 @@ use std::sync::{Arc, RwLock}; use std::{convert, error, fmt, io, process}; use vhost_rs::vhost_user::message::*; +use vhost_rs::vhost_user::SlaveFsCacheReq; use vhost_user_backend::{VhostUserBackend, VhostUserDaemon, Vring}; use vhost_user_fs::descriptor_utils::{Reader, Writer}; use vhost_user_fs::filesystem::FileSystem; @@ -72,6 +73,8 @@ struct VhostUserFsBackend { mem: Option, kill_evt: EventFd, server: Arc>, + // handle request from slave to master + vu_req: Option, } impl Clone for VhostUserFsBackend { @@ -80,6 +83,7 @@ impl Clone for VhostUserFsBackend { mem: self.mem.clone(), kill_evt: self.kill_evt.try_clone().unwrap(), server: self.server.clone(), + vu_req: self.vu_req.clone(), } } } @@ -90,6 +94,7 @@ impl VhostUserFsBackend { mem: None, kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?, server: Arc::new(Server::new(fs)), + vu_req: None, }) } @@ -105,7 +110,7 @@ impl VhostUserFsBackend { let total = self .server - .handle_message(reader, writer) + .handle_message(reader, writer, self.vu_req.as_mut()) .map_err(Error::ProcessQueue)?; used_desc_heads[used_count] = (head_index, total); @@ -173,6 +178,10 @@ impl VhostUserBackend for VhostUserFsBack fn exit_event(&self) -> Option<(EventFd, Option)> { 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() { diff --git a/vhost_rs/src/vhost_user/slave_req_handler.rs b/vhost_rs/src/vhost_user/slave_req_handler.rs index 480689f7f..50b8414db 100644 --- a/vhost_rs/src/vhost_user/slave_req_handler.rs +++ b/vhost_rs/src/vhost_user/slave_req_handler.rs @@ -4,12 +4,14 @@ //! Traits and Structs to handle vhost-user requests from the master to the slave. 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::sync::{Arc, Mutex}; use super::connection::Endpoint; use super::message::*; +use super::slave_fs_cache::SlaveFsCacheReq; use super::{Error, Result}; /// Trait to handle vhost-user requests from the master to the slave. @@ -47,6 +49,7 @@ pub trait VhostUserSlaveReqHandler { 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 @@ -274,6 +277,14 @@ impl SlaveReqHandler { self.check_request_size(&hdr, size, hdr.get_size() as usize)?; 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); } @@ -405,6 +416,25 @@ impl SlaveReqHandler { Ok(()) } + fn set_slave_req_fd( + &mut self, + hdr: &VhostUserMsgHeader, + rfds: Option>, + ) -> 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( &mut self, buf: &[u8], diff --git a/vhost_user_backend/src/lib.rs b/vhost_user_backend/src/lib.rs index 06ddcf7e3..7df006939 100644 --- a/vhost_user_backend/src/lib.rs +++ b/vhost_user_backend/src/lib.rs @@ -20,7 +20,8 @@ use vhost_rs::vhost_user::message::{ VhostUserVirtioFeatures, VhostUserVringAddrFlags, VhostUserVringState, }; 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::{GuestAddress, GuestMemoryMmap}; @@ -103,6 +104,11 @@ pub trait VhostUserBackend: Send + Sync + 'static { fn exit_event(&self) -> Option<(EventFd, Option)> { 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 @@ -779,6 +785,10 @@ impl VhostUserSlaveReqHandler for VhostUserHandler { .set_config(offset, buf) .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 Drop for VhostUserHandler {