mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-21 15:31:15 +00:00
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 <zhangjiachen.jaycee@bytedance.com>
This commit is contained in:
parent
f060ecd705
commit
bfd4aa2fed
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1111,7 +1111,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
|
2
fuzz/Cargo.lock
generated
2
fuzz/Cargo.lock
generated
@ -652,7 +652,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -959,6 +959,24 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
|
|||||||
|
|
||||||
Ok(())
|
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<S: VhostUserBackend> Drop for VhostUserHandler<S> {
|
impl<S: VhostUserBackend> Drop for VhostUserHandler<S> {
|
||||||
|
@ -231,6 +231,7 @@ impl VirtioDevice for Blk {
|
|||||||
&interrupt_cb,
|
&interrupt_cb,
|
||||||
backend_acked_features,
|
backend_acked_features,
|
||||||
&slave_req_handler,
|
&slave_req_handler,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.map_err(ActivateError::VhostUserBlkSetup)?;
|
.map_err(ActivateError::VhostUserBlkSetup)?;
|
||||||
|
|
||||||
@ -251,6 +252,7 @@ impl VirtioDevice for Blk {
|
|||||||
socket_path: self.socket_path.clone(),
|
socket_path: self.socket_path.clone(),
|
||||||
server: false,
|
server: false,
|
||||||
slave_req_handler: None,
|
slave_req_handler: None,
|
||||||
|
inflight: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.common.paused.clone();
|
let paused = self.common.paused.clone();
|
||||||
|
@ -452,6 +452,7 @@ impl VirtioDevice for Fs {
|
|||||||
&interrupt_cb,
|
&interrupt_cb,
|
||||||
backend_acked_features,
|
backend_acked_features,
|
||||||
&slave_req_handler,
|
&slave_req_handler,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.map_err(ActivateError::VhostUserFsSetup)?;
|
.map_err(ActivateError::VhostUserFsSetup)?;
|
||||||
|
|
||||||
@ -471,6 +472,7 @@ impl VirtioDevice for Fs {
|
|||||||
socket_path: self.socket_path.clone(),
|
socket_path: self.socket_path.clone(),
|
||||||
server: false,
|
server: false,
|
||||||
slave_req_handler,
|
slave_req_handler,
|
||||||
|
inflight: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.common.paused.clone();
|
let paused = self.common.paused.clone();
|
||||||
|
@ -11,7 +11,7 @@ use std::io;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::sync::{atomic::AtomicBool, Arc, Barrier, Mutex};
|
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::vhost_user::{Master, MasterReqHandler, VhostUserMasterReqHandler};
|
||||||
use vhost::Error as VhostError;
|
use vhost::Error as VhostError;
|
||||||
use vm_memory::{Error as MmapError, GuestAddressSpace, GuestMemoryAtomic};
|
use vm_memory::{Error as MmapError, GuestAddressSpace, GuestMemoryAtomic};
|
||||||
@ -103,6 +103,10 @@ pub enum Error {
|
|||||||
VhostUserGetConfig(VhostError),
|
VhostUserGetConfig(VhostError),
|
||||||
/// Failed setting the configuration.
|
/// Failed setting the configuration.
|
||||||
VhostUserSetConfig(VhostError),
|
VhostUserSetConfig(VhostError),
|
||||||
|
/// Failed getting inflight shm log.
|
||||||
|
VhostUserGetInflight(VhostError),
|
||||||
|
/// Failed setting inflight shm log.
|
||||||
|
VhostUserSetInflight(VhostError),
|
||||||
/// Invalid used address.
|
/// Invalid used address.
|
||||||
UsedAddress,
|
UsedAddress,
|
||||||
/// Invalid features provided from vhost-user backend
|
/// 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 HUP_CONNECTION_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
|
||||||
const SLAVE_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
|
const SLAVE_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Inflight {
|
||||||
|
pub info: VhostUserInflight,
|
||||||
|
pub fd: Option<std::fs::File>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct VhostUserEpollHandler<S: VhostUserMasterReqHandler> {
|
pub struct VhostUserEpollHandler<S: VhostUserMasterReqHandler> {
|
||||||
pub vu: Arc<Mutex<Master>>,
|
pub vu: Arc<Mutex<Master>>,
|
||||||
pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
@ -141,6 +151,7 @@ pub struct VhostUserEpollHandler<S: VhostUserMasterReqHandler> {
|
|||||||
pub socket_path: String,
|
pub socket_path: String,
|
||||||
pub server: bool,
|
pub server: bool,
|
||||||
pub slave_req_handler: Option<MasterReqHandler<S>>,
|
pub slave_req_handler: Option<MasterReqHandler<S>>,
|
||||||
|
pub inflight: Option<Inflight>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
|
impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
|
||||||
@ -198,6 +209,7 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
|
|||||||
self.acked_features,
|
self.acked_features,
|
||||||
self.acked_protocol_features,
|
self.acked_protocol_features,
|
||||||
&self.slave_req_handler,
|
&self.slave_req_handler,
|
||||||
|
self.inflight.as_mut(),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
EpollHelperError::IoError(std::io::Error::new(
|
EpollHelperError::IoError(std::io::Error::new(
|
||||||
|
@ -300,6 +300,7 @@ impl VirtioDevice for Net {
|
|||||||
&interrupt_cb,
|
&interrupt_cb,
|
||||||
backend_acked_features,
|
backend_acked_features,
|
||||||
&slave_req_handler,
|
&slave_req_handler,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.map_err(ActivateError::VhostUserNetSetup)?;
|
.map_err(ActivateError::VhostUserNetSetup)?;
|
||||||
|
|
||||||
@ -320,6 +321,7 @@ impl VirtioDevice for Net {
|
|||||||
socket_path: self.socket_path.clone(),
|
socket_path: self.socket_path.clone(),
|
||||||
server: self.server,
|
server: self.server,
|
||||||
slave_req_handler: None,
|
slave_req_handler: None,
|
||||||
|
inflight: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.common.paused.clone();
|
let paused = self.common.paused.clone();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use super::super::{Descriptor, Queue};
|
use super::super::{Descriptor, Queue};
|
||||||
use super::{Error, Result};
|
use super::{Error, Result};
|
||||||
|
use crate::vhost_user::Inflight;
|
||||||
use crate::{get_host_address_range, VirtioInterrupt, VirtioInterruptType};
|
use crate::{get_host_address_range, VirtioInterrupt, VirtioInterruptType};
|
||||||
use crate::{GuestMemoryMmap, GuestRegionMmap};
|
use crate::{GuestMemoryMmap, GuestRegionMmap};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@ -12,7 +13,9 @@ use std::sync::Arc;
|
|||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::vec::Vec;
|
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::vhost_user::{Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
|
||||||
use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
|
use vhost::{VhostBackend, VhostUserMemoryRegionInfo, VringConfigData};
|
||||||
use vm_memory::{Address, Error as MmapError, GuestMemory, GuestMemoryRegion};
|
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))
|
Ok((acked_features, acked_protocol_features))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
|
pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
|
||||||
vu: &mut Master,
|
vu: &mut Master,
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
@ -108,6 +112,7 @@ pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
|
|||||||
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
||||||
acked_features: u64,
|
acked_features: u64,
|
||||||
slave_req_handler: &Option<MasterReqHandler<S>>,
|
slave_req_handler: &Option<MasterReqHandler<S>>,
|
||||||
|
inflight: Option<&mut Inflight>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
vu.set_features(acked_features)
|
vu.set_features(acked_features)
|
||||||
.map_err(Error::VhostUserSetFeatures)?;
|
.map_err(Error::VhostUserSetFeatures)?;
|
||||||
@ -115,6 +120,26 @@ pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
|
|||||||
// Let's first provide the memory table to the backend.
|
// Let's first provide the memory table to the backend.
|
||||||
update_mem_table(vu, mem)?;
|
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() {
|
for (queue_index, queue) in queues.into_iter().enumerate() {
|
||||||
let actual_size: usize = queue.actual_size().try_into().unwrap();
|
let actual_size: usize = queue.actual_size().try_into().unwrap();
|
||||||
|
|
||||||
@ -194,6 +219,7 @@ pub fn reinitialize_vhost_user<S: VhostUserMasterReqHandler>(
|
|||||||
acked_features: u64,
|
acked_features: u64,
|
||||||
acked_protocol_features: u64,
|
acked_protocol_features: u64,
|
||||||
slave_req_handler: &Option<MasterReqHandler<S>>,
|
slave_req_handler: &Option<MasterReqHandler<S>>,
|
||||||
|
inflight: Option<&mut Inflight>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
vu.set_owner().map_err(Error::VhostUserSetOwner)?;
|
vu.set_owner().map_err(Error::VhostUserSetOwner)?;
|
||||||
vu.get_features().map_err(Error::VhostUserGetFeatures)?;
|
vu.get_features().map_err(Error::VhostUserGetFeatures)?;
|
||||||
@ -215,6 +241,7 @@ pub fn reinitialize_vhost_user<S: VhostUserMasterReqHandler>(
|
|||||||
virtio_interrupt,
|
virtio_interrupt,
|
||||||
acked_features,
|
acked_features,
|
||||||
slave_req_handler,
|
slave_req_handler,
|
||||||
|
inflight,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user