From bfd4aa2fed5784445443110901e8dce18f7a9075 Mon Sep 17 00:00:00 2001 From: Jiachen Zhang Date: Thu, 10 Jun 2021 15:37:30 +0800 Subject: [PATCH] virtio-devices: vhost_user: Support inflight I/O tracking Vhost user INFLIGHT_SHMFD protocol feature supports inflight I/O tracking, this commit implement the vhost-user device (master) support of the feature. Till this commit, specific vhost-user devices (blk, fs, or net) have not enable this feature. Signed-off-by: Jiachen Zhang --- Cargo.lock | 2 +- fuzz/Cargo.lock | 2 +- vhost_user_backend/src/lib.rs | 18 ++++++++++++ virtio-devices/src/vhost_user/blk.rs | 2 ++ virtio-devices/src/vhost_user/fs.rs | 2 ++ virtio-devices/src/vhost_user/mod.rs | 14 ++++++++- virtio-devices/src/vhost_user/net.rs | 2 ++ .../src/vhost_user/vu_common_ctrl.rs | 29 ++++++++++++++++++- 8 files changed, 67 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4fc726b8d..b49085af9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1111,7 +1111,7 @@ dependencies = [ [[package]] name = "vhost" version = "0.1.0" -source = "git+https://github.com/rust-vmm/vhost?branch=master#30ba3e7bbe9e0542cf480f44bc6845a8dbd2a6ba" +source = "git+https://github.com/rust-vmm/vhost?branch=master#a8ff939161d41fc2f449b80e461d013c1e19f666" dependencies = [ "bitflags", "libc", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index dac1d13c1..1ec28a48b 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -652,7 +652,7 @@ dependencies = [ [[package]] name = "vhost" version = "0.1.0" -source = "git+https://github.com/rust-vmm/vhost?branch=master#e5b930b73a47cbdd79858e2e68bcb57123d1c1f3" +source = "git+https://github.com/rust-vmm/vhost?branch=master#a8ff939161d41fc2f449b80e461d013c1e19f666" dependencies = [ "bitflags", "libc", diff --git a/vhost_user_backend/src/lib.rs b/vhost_user_backend/src/lib.rs index 87af52f01..767a75fb8 100644 --- a/vhost_user_backend/src/lib.rs +++ b/vhost_user_backend/src/lib.rs @@ -959,6 +959,24 @@ impl VhostUserSlaveReqHandlerMut for VhostUserHandler { Ok(()) } + + fn get_inflight_fd( + &mut self, + _: &vhost::vhost_user::message::VhostUserInflight, + ) -> std::result::Result< + (vhost::vhost_user::message::VhostUserInflight, i32), + vhost::vhost_user::Error, + > { + std::unimplemented!() + } + + fn set_inflight_fd( + &mut self, + _: &vhost::vhost_user::message::VhostUserInflight, + _: std::fs::File, + ) -> std::result::Result<(), vhost::vhost_user::Error> { + std::unimplemented!() + } } impl Drop for VhostUserHandler { diff --git a/virtio-devices/src/vhost_user/blk.rs b/virtio-devices/src/vhost_user/blk.rs index 804265c2a..9ed931a5e 100644 --- a/virtio-devices/src/vhost_user/blk.rs +++ b/virtio-devices/src/vhost_user/blk.rs @@ -231,6 +231,7 @@ impl VirtioDevice for Blk { &interrupt_cb, backend_acked_features, &slave_req_handler, + None, ) .map_err(ActivateError::VhostUserBlkSetup)?; @@ -251,6 +252,7 @@ impl VirtioDevice for Blk { socket_path: self.socket_path.clone(), server: false, slave_req_handler: None, + inflight: None, }; let paused = self.common.paused.clone(); diff --git a/virtio-devices/src/vhost_user/fs.rs b/virtio-devices/src/vhost_user/fs.rs index 9d27e12fc..328fcc932 100644 --- a/virtio-devices/src/vhost_user/fs.rs +++ b/virtio-devices/src/vhost_user/fs.rs @@ -452,6 +452,7 @@ impl VirtioDevice for Fs { &interrupt_cb, backend_acked_features, &slave_req_handler, + None, ) .map_err(ActivateError::VhostUserFsSetup)?; @@ -471,6 +472,7 @@ impl VirtioDevice for Fs { socket_path: self.socket_path.clone(), server: false, slave_req_handler, + inflight: None, }; let paused = self.common.paused.clone(); diff --git a/virtio-devices/src/vhost_user/mod.rs b/virtio-devices/src/vhost_user/mod.rs index dca7b2fe1..c2763b720 100644 --- a/virtio-devices/src/vhost_user/mod.rs +++ b/virtio-devices/src/vhost_user/mod.rs @@ -11,7 +11,7 @@ use std::io; use std::ops::Deref; use std::os::unix::io::AsRawFd; use std::sync::{atomic::AtomicBool, Arc, Barrier, Mutex}; -use vhost::vhost_user::message::VhostUserVirtioFeatures; +use vhost::vhost_user::message::{VhostUserInflight, VhostUserVirtioFeatures}; use vhost::vhost_user::{Master, MasterReqHandler, VhostUserMasterReqHandler}; use vhost::Error as VhostError; use vm_memory::{Error as MmapError, GuestAddressSpace, GuestMemoryAtomic}; @@ -103,6 +103,10 @@ pub enum Error { VhostUserGetConfig(VhostError), /// Failed setting the configuration. VhostUserSetConfig(VhostError), + /// Failed getting inflight shm log. + VhostUserGetInflight(VhostError), + /// Failed setting inflight shm log. + VhostUserSetInflight(VhostError), /// Invalid used address. UsedAddress, /// Invalid features provided from vhost-user backend @@ -128,6 +132,12 @@ pub const DEFAULT_VIRTIO_FEATURES: u64 = 1 << VIRTIO_F_RING_INDIRECT_DESC const HUP_CONNECTION_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1; const SLAVE_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2; +#[derive(Default)] +pub struct Inflight { + pub info: VhostUserInflight, + pub fd: Option, +} + pub struct VhostUserEpollHandler { pub vu: Arc>, pub mem: GuestMemoryAtomic, @@ -141,6 +151,7 @@ pub struct VhostUserEpollHandler { pub socket_path: String, pub server: bool, pub slave_req_handler: Option>, + pub inflight: Option, } impl VhostUserEpollHandler { @@ -198,6 +209,7 @@ impl VhostUserEpollHandler { self.acked_features, self.acked_protocol_features, &self.slave_req_handler, + self.inflight.as_mut(), ) .map_err(|e| { EpollHelperError::IoError(std::io::Error::new( diff --git a/virtio-devices/src/vhost_user/net.rs b/virtio-devices/src/vhost_user/net.rs index cc023a659..d555ab9c6 100644 --- a/virtio-devices/src/vhost_user/net.rs +++ b/virtio-devices/src/vhost_user/net.rs @@ -300,6 +300,7 @@ impl VirtioDevice for Net { &interrupt_cb, backend_acked_features, &slave_req_handler, + None, ) .map_err(ActivateError::VhostUserNetSetup)?; @@ -320,6 +321,7 @@ impl VirtioDevice for Net { socket_path: self.socket_path.clone(), server: self.server, slave_req_handler: None, + inflight: None, }; let paused = self.common.paused.clone(); diff --git a/virtio-devices/src/vhost_user/vu_common_ctrl.rs b/virtio-devices/src/vhost_user/vu_common_ctrl.rs index 08d6e4c02..fc4612093 100644 --- a/virtio-devices/src/vhost_user/vu_common_ctrl.rs +++ b/virtio-devices/src/vhost_user/vu_common_ctrl.rs @@ -3,6 +3,7 @@ use super::super::{Descriptor, Queue}; use super::{Error, Result}; +use crate::vhost_user::Inflight; use crate::{get_host_address_range, VirtioInterrupt, VirtioInterruptType}; use crate::{GuestMemoryMmap, GuestRegionMmap}; use std::convert::TryInto; @@ -12,7 +13,9 @@ use std::sync::Arc; use std::thread::sleep; use std::time::{Duration, Instant}; use std::vec::Vec; -use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures}; +use vhost::vhost_user::message::{ + VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures, +}; use vhost::vhost_user::{Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler}; use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData}; use vm_memory::{Address, Error as MmapError, GuestMemory, GuestMemoryRegion}; @@ -100,6 +103,7 @@ pub fn negotiate_features_vhost_user( Ok((acked_features, acked_protocol_features)) } +#[allow(clippy::too_many_arguments)] pub fn setup_vhost_user( vu: &mut Master, mem: &GuestMemoryMmap, @@ -108,6 +112,7 @@ pub fn setup_vhost_user( virtio_interrupt: &Arc, acked_features: u64, slave_req_handler: &Option>, + inflight: Option<&mut Inflight>, ) -> Result<()> { vu.set_features(acked_features) .map_err(Error::VhostUserSetFeatures)?; @@ -115,6 +120,26 @@ pub fn setup_vhost_user( // Let's first provide the memory table to the backend. update_mem_table(vu, mem)?; + // Setup for inflight I/O tracking shared memory. + if let Some(inflight) = inflight { + if inflight.fd.is_none() { + let inflight_req_info = VhostUserInflight { + mmap_size: 0, + mmap_offset: 0, + num_queues: queues.len() as u16, + queue_size: queues[0].actual_size(), + }; + let (info, fd) = vu + .get_inflight_fd(&inflight_req_info) + .map_err(Error::VhostUserGetInflight)?; + inflight.info = info; + inflight.fd = Some(fd); + } + // Unwrapping the inflight fd is safe here since we know it can't be None. + vu.set_inflight_fd(&inflight.info, inflight.fd.as_ref().unwrap().as_raw_fd()) + .map_err(Error::VhostUserSetInflight)?; + } + for (queue_index, queue) in queues.into_iter().enumerate() { let actual_size: usize = queue.actual_size().try_into().unwrap(); @@ -194,6 +219,7 @@ pub fn reinitialize_vhost_user( acked_features: u64, acked_protocol_features: u64, slave_req_handler: &Option>, + inflight: Option<&mut Inflight>, ) -> Result<()> { vu.set_owner().map_err(Error::VhostUserSetOwner)?; vu.get_features().map_err(Error::VhostUserGetFeatures)?; @@ -215,6 +241,7 @@ pub fn reinitialize_vhost_user( virtio_interrupt, acked_features, slave_req_handler, + inflight, ) }