diff options
author | Liu Jiang <gerry@linux.alibaba.com> | 2021-02-22 14:08:04 +0800 |
---|---|---|
committer | Sergio Lopez <slp@sinrega.org> | 2021-03-01 12:50:56 +0100 |
commit | e543bf2a8defadae534cfe757829a9377663e5ad (patch) | |
tree | 12ed601664702e8152a9e25453b03dc7b88067a7 | |
parent | ec6eae722ef7c6fcecbb8acddf1d9905083dc3de (diff) | |
download | vmm_vhost-e543bf2a8defadae534cfe757829a9377663e5ad.tar.gz |
vhost_user: add more negative unit test cases
Add more negative unit test cases to improve code coverage.
Also add two helper functions to simplify code.
Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
-rw-r--r-- | coverage_config_x86_64.json | 2 | ||||
-rw-r--r-- | src/vhost_user/master.rs | 257 | ||||
-rw-r--r-- | src/vhost_user/mod.rs | 11 | ||||
-rw-r--r-- | src/vhost_user/slave_fs_cache.rs | 65 |
4 files changed, 295 insertions, 40 deletions
diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index 075255b..a4ed64f 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1 +1 @@ -{"coverage_score": 78.9, "exclude_path": "src/vhost_kern/", "crate_features": "vhost-user-master,vhost-user-slave"} +{"coverage_score": 81.3, "exclude_path": "src/vhost_kern/", "crate_features": "vhost-user-master,vhost-user-slave"}
\ No newline at end of file diff --git a/src/vhost_user/master.rs b/src/vhost_user/master.rs index cc754b5..be2892e 100644 --- a/src/vhost_user/master.rs +++ b/src/vhost_user/master.rs @@ -6,7 +6,7 @@ use std::mem; use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::net::UnixStream; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, MutexGuard}; use vmm_sys_util::eventfd::EventFd; @@ -78,6 +78,10 @@ impl Master { } } + fn node(&self) -> MutexGuard<MasterInternal> { + self.node.lock().unwrap() + } + /// Create a new instance from a Unix stream socket. pub fn from_stream(sock: UnixStream, max_queue_num: u64) -> Self { Self::new(Endpoint::<MasterReq>::from_stream(sock), max_queue_num) @@ -116,7 +120,7 @@ impl Master { impl VhostBackend for Master { /// Get from the underlying vhost implementation the feature bitmask. fn get_features(&self) -> Result<u64> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let hdr = node.send_request_header(MasterReq::GET_FEATURES, None)?; let val = node.recv_reply::<VhostUserU64>(&hdr)?; node.virtio_features = val.value; @@ -125,7 +129,7 @@ impl VhostBackend for Master { /// Enable features in the underlying vhost implementation using a bitmask. fn set_features(&self, features: u64) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let val = VhostUserU64::new(features); let _ = node.send_request_with_body(MasterReq::SET_FEATURES, &val, None)?; // Don't wait for ACK here because the protocol feature negotiation process hasn't been @@ -138,7 +142,7 @@ impl VhostBackend for Master { fn set_owner(&self) -> Result<()> { // We unwrap() the return value to assert that we are not expecting threads to ever fail // while holding the lock. - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let _ = node.send_request_header(MasterReq::SET_OWNER, None)?; // Don't wait for ACK here because the protocol feature negotiation process hasn't been // completed yet. @@ -146,7 +150,7 @@ impl VhostBackend for Master { } fn reset_owner(&self) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let _ = node.send_request_header(MasterReq::RESET_OWNER, None)?; // Don't wait for ACK here because the protocol feature negotiation process hasn't been // completed yet. @@ -174,7 +178,7 @@ impl VhostBackend for Master { ctx.append(®, region.mmap_handle); } - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let body = VhostUserMemory::new(ctx.regions.len() as u32); let (_, payload, _) = unsafe { ctx.regions.align_to::<u8>() }; let hdr = node.send_request_with_payload( @@ -189,7 +193,7 @@ impl VhostBackend for Master { // Clippy doesn't seem to know that if let with && is still experimental #[allow(clippy::unnecessary_unwrap)] fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let val = VhostUserU64::new(base); if node.acked_protocol_features & VhostUserProtocolFeatures::LOG_SHMFD.bits() != 0 @@ -204,7 +208,7 @@ impl VhostBackend for Master { } fn set_log_fd(&self, fd: RawFd) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let fds = [fd]; node.send_request_header(MasterReq::SET_LOG_FD, Some(&fds))?; Ok(()) @@ -212,7 +216,7 @@ impl VhostBackend for Master { /// Set the size of the queue. fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } @@ -224,7 +228,7 @@ impl VhostBackend for Master { /// Sets the addresses of the different aspects of the vring. fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if queue_index as u64 >= node.max_queue_num || config_data.flags & !(VhostUserVringAddrFlags::all().bits()) != 0 { @@ -238,7 +242,7 @@ impl VhostBackend for Master { /// Sets the base offset in the available vring. fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } @@ -249,7 +253,7 @@ impl VhostBackend for Master { } fn get_vring_base(&self, queue_index: usize) -> Result<u32> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } @@ -265,7 +269,7 @@ impl VhostBackend for Master { /// is set when there is no file descriptor in the ancillary data. This signals that polling /// will be used instead of waiting for the call. fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } @@ -278,7 +282,7 @@ impl VhostBackend for Master { /// is set when there is no file descriptor in the ancillary data. This signals that polling /// should be used instead of waiting for a kick. fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } @@ -290,7 +294,7 @@ impl VhostBackend for Master { /// Bits (0-7) of the payload contain the vring index. Bit 8 is the invalid FD flag. This flag /// is set when there is no file descriptor in the ancillary data. fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if queue_index as u64 >= node.max_queue_num { return error_code(VhostUserError::InvalidParam); } @@ -301,7 +305,7 @@ impl VhostBackend for Master { impl VhostUserMaster for Master { fn get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let flag = VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(); if node.virtio_features & flag == 0 || node.acked_virtio_features & flag == 0 { return error_code(VhostUserError::InvalidOperation); @@ -318,7 +322,7 @@ impl VhostUserMaster for Master { } fn set_protocol_features(&mut self, features: VhostUserProtocolFeatures) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); let flag = VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(); if node.virtio_features & flag == 0 || node.acked_virtio_features & flag == 0 { return error_code(VhostUserError::InvalidOperation); @@ -333,7 +337,7 @@ impl VhostUserMaster for Master { } fn get_queue_num(&mut self) -> Result<u64> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if !node.is_feature_mq_available() { return error_code(VhostUserError::InvalidOperation); } @@ -348,7 +352,7 @@ impl VhostUserMaster for Master { } fn set_vring_enable(&mut self, queue_index: usize, enable: bool) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); // set_vring_enable() is supported only when PROTOCOL_FEATURES has been enabled. if node.acked_virtio_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits() == 0 { return error_code(VhostUserError::InvalidOperation); @@ -374,7 +378,7 @@ impl VhostUserMaster for Master { return error_code(VhostUserError::InvalidParam); } - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); // depends on VhostUserProtocolFeatures::CONFIG if node.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 { return error_code(VhostUserError::InvalidOperation); @@ -409,7 +413,7 @@ impl VhostUserMaster for Master { return error_code(VhostUserError::InvalidParam); } - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); // depends on VhostUserProtocolFeatures::CONFIG if node.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 { return error_code(VhostUserError::InvalidOperation); @@ -420,7 +424,7 @@ impl VhostUserMaster for Master { } fn set_slave_request_fd(&mut self, fd: RawFd) -> Result<()> { - let mut node = self.node.lock().unwrap(); + let mut node = self.node(); if node.acked_protocol_features & VhostUserProtocolFeatures::SLAVE_REQ.bits() == 0 { return error_code(VhostUserError::InvalidOperation); } @@ -433,7 +437,7 @@ impl VhostUserMaster for Master { impl AsRawFd for Master { fn as_raw_fd(&self) -> RawFd { - let node = self.node.lock().unwrap(); + let node = self.node(); node.main_sock.as_raw_fd() } } @@ -783,4 +787,211 @@ mod tests { peer.send_message(&hdr, &msg, None).unwrap(); assert!(master.get_protocol_features().is_err()); } + + #[test] + fn test_master_set_config_negative() { + let path = temp_path(); + let (mut master, _peer) = create_pair(&path); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + master + .set_config(0x100, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .unwrap_err(); + + { + let mut node = master.node(); + node.virtio_features = 0xffff_ffff; + node.acked_virtio_features = 0xffff_ffff; + node.protocol_features = 0xffff_ffff; + node.acked_protocol_features = 0xffff_ffff; + } + + master + .set_config(0x100, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .unwrap(); + master + .set_config(0x0, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .unwrap_err(); + master + .set_config(0x1000, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .unwrap_err(); + master + .set_config( + 0x100, + unsafe { VhostUserConfigFlags::from_bits_unchecked(0xffff_ffff) }, + &buf[0..4], + ) + .unwrap_err(); + master + .set_config(0x100, VhostUserConfigFlags::WRITABLE, &buf) + .unwrap_err(); + master + .set_config(0x100, VhostUserConfigFlags::WRITABLE, &[]) + .unwrap_err(); + } + + fn create_pair2() -> (Master, Endpoint<MasterReq>) { + let path = temp_path(); + let (master, peer) = create_pair(&path); + + { + let mut node = master.node(); + node.virtio_features = 0xffff_ffff; + node.acked_virtio_features = 0xffff_ffff; + node.protocol_features = 0xffff_ffff; + node.acked_protocol_features = 0xffff_ffff; + } + + (master, peer) + } + + #[test] + fn test_master_get_config_negative0() { + let (mut master, mut peer) = create_pair2(); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + let mut hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_ok()); + + hdr.set_code(MasterReq::GET_FEATURES); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_err()); + hdr.set_code(MasterReq::GET_CONFIG); + } + + #[test] + fn test_master_get_config_negative1() { + let (mut master, mut peer) = create_pair2(); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + let mut hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_ok()); + + hdr.set_reply(false); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_err()); + } + + #[test] + fn test_master_get_config_negative2() { + let (mut master, mut peer) = create_pair2(); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_ok()); + } + + #[test] + fn test_master_get_config_negative3() { + let (mut master, mut peer) = create_pair2(); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_ok()); + + msg.offset = 0; + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_err()); + } + + #[test] + fn test_master_get_config_negative4() { + let (mut master, mut peer) = create_pair2(); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_ok()); + + msg.offset = 0x101; + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_err()); + } + + #[test] + fn test_master_get_config_negative5() { + let (mut master, mut peer) = create_pair2(); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_ok()); + + msg.offset = (MAX_MSG_SIZE + 1) as u32; + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_err()); + } + + #[test] + fn test_master_get_config_negative6() { + let (mut master, mut peer) = create_pair2(); + let buf = vec![0x0; MAX_MSG_SIZE + 1]; + + let hdr = VhostUserMsgHeader::new(MasterReq::GET_CONFIG, 0x4, 16); + let mut msg = VhostUserConfig::new(0x100, 4, VhostUserConfigFlags::empty()); + peer.send_message_with_payload(&hdr, &msg, &buf[0..4], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_ok()); + + msg.size = 6; + peer.send_message_with_payload(&hdr, &msg, &buf[0..6], None) + .unwrap(); + assert!(master + .get_config(0x100, 4, VhostUserConfigFlags::WRITABLE, &buf[0..4]) + .is_err()); + } + + #[test] + fn test_maset_set_mem_table_failure() { + let (master, _peer) = create_pair2(); + + master.set_mem_table(&[]).unwrap_err(); + let tables = vec![VhostUserMemoryRegionInfo::default(); MAX_ATTACHED_FD_ENTRIES + 1]; + master.set_mem_table(&tables).unwrap_err(); + } } diff --git a/src/vhost_user/mod.rs b/src/vhost_user/mod.rs index bf0a261..bc21b44 100644 --- a/src/vhost_user/mod.rs +++ b/src/vhost_user/mod.rs @@ -210,7 +210,7 @@ mod tests { #[test] fn create_dummy_slave() { - let mut slave = DummySlaveReqHandler::new(); + let slave = Arc::new(Mutex::new(DummySlaveReqHandler::new())); slave.set_owner().unwrap(); assert!(slave.set_owner().is_err()); @@ -319,11 +319,9 @@ mod tests { // set_vring_enable slave.handle_request().unwrap(); - /* // set_log_base,set_log_fd() - slave.handle_request().unwrap(); - slave.handle_request().unwrap(); - */ + slave.handle_request().unwrap_err(); + slave.handle_request().unwrap_err(); // set_vring_xxx slave.handle_request().unwrap(); @@ -375,10 +373,9 @@ mod tests { master.set_slave_request_fd(eventfd.as_raw_fd()).unwrap(); master.set_vring_enable(0, true).unwrap(); - /* + // unimplemented yet master.set_log_base(0, Some(eventfd.as_raw_fd())).unwrap(); master.set_log_fd(eventfd.as_raw_fd()).unwrap(); - */ master.set_vring_num(0, 256).unwrap(); master.set_vring_base(0, 0).unwrap(); diff --git a/src/vhost_user/slave_fs_cache.rs b/src/vhost_user/slave_fs_cache.rs index 32b2b8e..1e2ef61 100644 --- a/src/vhost_user/slave_fs_cache.rs +++ b/src/vhost_user/slave_fs_cache.rs @@ -5,7 +5,7 @@ use std::io; use std::mem; use std::os::unix::io::RawFd; use std::os::unix::net::UnixStream; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, MutexGuard}; use super::connection::Endpoint; use super::message::*; @@ -92,15 +92,17 @@ impl SlaveFsCacheReq { } } + fn node(&self) -> MutexGuard<SlaveFsCacheReqInternal> { + self.node.lock().unwrap() + } + fn send_message( &self, request: SlaveReq, fs: &VhostUserFSSlaveMsg, fds: Option<&[RawFd]>, ) -> io::Result<u64> { - self.node - .lock() - .unwrap() + self.node() .send_message(request, fs, fds) .or_else(|e| Err(io::Error::new(io::ErrorKind::Other, format!("{}", e)))) } @@ -116,12 +118,12 @@ impl SlaveFsCacheReq { /// the "REPLY_ACK" flag will be set in the message header for every slave to master request /// message. pub fn set_reply_ack_flag(&self, enable: bool) { - self.node.lock().unwrap().reply_ack_negotiated = enable; + self.node().reply_ack_negotiated = enable; } /// Mark endpoint as failed with specified error code. pub fn set_failed(&self, error: i32) { - self.node.lock().unwrap().error = Some(error); + self.node().error = Some(error); } } @@ -148,9 +150,9 @@ mod tests { let (p1, _p2) = UnixStream::pair().unwrap(); let fs_cache = SlaveFsCacheReq::from_stream(p1); - assert!(fs_cache.node.lock().unwrap().error.is_none()); + assert!(fs_cache.node().error.is_none()); fs_cache.set_failed(libc::EAGAIN); - assert_eq!(fs_cache.node.lock().unwrap().error, Some(libc::EAGAIN)); + assert_eq!(fs_cache.node().error, Some(libc::EAGAIN)); } #[test] @@ -166,7 +168,7 @@ mod tests { fs_cache .fs_slave_unmap(&VhostUserFSSlaveMsg::default()) .unwrap_err(); - fs_cache.node.lock().unwrap().error = None; + fs_cache.node().error = None; drop(p2); fs_cache @@ -176,4 +178,49 @@ mod tests { .fs_slave_unmap(&VhostUserFSSlaveMsg::default()) .unwrap_err(); } + + #[test] + fn test_slave_fs_cache_recv_negative() { + let (p1, p2) = UnixStream::pair().unwrap(); + let fd = p2.as_raw_fd(); + let fs_cache = SlaveFsCacheReq::from_stream(p1); + let mut master = Endpoint::<SlaveReq>::from_stream(p2); + + let len = mem::size_of::<VhostUserFSSlaveMsg>(); + let mut hdr = VhostUserMsgHeader::new( + SlaveReq::FS_MAP, + VhostUserHeaderFlag::REPLY.bits(), + len as u32, + ); + let body = VhostUserU64::new(0); + + master.send_message(&hdr, &body, Some(&[fd])).unwrap(); + fs_cache + .fs_slave_map(&VhostUserFSSlaveMsg::default(), fd) + .unwrap(); + + fs_cache.set_reply_ack_flag(true); + fs_cache + .fs_slave_map(&VhostUserFSSlaveMsg::default(), fd) + .unwrap_err(); + + hdr.set_code(SlaveReq::FS_UNMAP); + master.send_message(&hdr, &body, None).unwrap(); + fs_cache + .fs_slave_map(&VhostUserFSSlaveMsg::default(), fd) + .unwrap_err(); + hdr.set_code(SlaveReq::FS_MAP); + + let body = VhostUserU64::new(1); + master.send_message(&hdr, &body, None).unwrap(); + fs_cache + .fs_slave_map(&VhostUserFSSlaveMsg::default(), fd) + .unwrap_err(); + + let body = VhostUserU64::new(0); + master.send_message(&hdr, &body, None).unwrap(); + fs_cache + .fs_slave_map(&VhostUserFSSlaveMsg::default(), fd) + .unwrap(); + } } |