Introduce VhostBackendMut trait
Originally the VhostBackend trait is designed to take a mutable self, which causes a common usage pattern Arc<RwLock<T: VhostBackend>>. This pattern may enforce serialization among multiple threads. So rename the original VhostBackend as VhostBackendMut, and introduce a new VhostBackend trait with interior mutability to improve performance by removing the serialization. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
This commit is contained in:
parent
8c6919bf60
commit
d748d5bdcf
4 changed files with 354 additions and 36 deletions
328
src/backend.rs
328
src/backend.rs
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved.
|
||||
// Copyright (C) 2019-2021 Alibaba Cloud. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
//
|
||||
// Portions Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
|
|
@ -9,14 +9,18 @@
|
|||
|
||||
//! Common traits and structs for vhost-kern and vhost-user backend drivers.
|
||||
|
||||
use super::Result;
|
||||
use std::cell::RefCell;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use super::Result;
|
||||
|
||||
/// Maximum number of memory regions supported.
|
||||
pub const VHOST_MAX_MEMORY_REGIONS: usize = 255;
|
||||
|
||||
/// Vring/virtque configuration data.
|
||||
/// Vring configuration data.
|
||||
pub struct VringConfigData {
|
||||
/// Maximum queue size supported by the driver.
|
||||
pub queue_max_size: u16,
|
||||
|
|
@ -65,21 +69,108 @@ pub struct VhostUserMemoryRegionInfo {
|
|||
pub userspace_addr: u64,
|
||||
/// Optional offset where region starts in the mapped memory.
|
||||
pub mmap_offset: u64,
|
||||
/// Optional file diescriptor for mmap
|
||||
/// Optional file descriptor for mmap.
|
||||
pub mmap_handle: RawFd,
|
||||
}
|
||||
|
||||
/// An interface for setting up vhost-based backend drivers with interior mutability.
|
||||
///
|
||||
/// Vhost devices are subset of virtio devices, which improve virtio device's performance by
|
||||
/// delegating data plane operations to dedicated IO service processes. Vhost devices use the
|
||||
/// same virtqueue layout as virtio devices to allow vhost devices to be mapped directly to
|
||||
/// virtio devices.
|
||||
///
|
||||
/// The purpose of vhost is to implement a subset of a virtio device's functionality outside the
|
||||
/// VMM process. Typically fast paths for IO operations are delegated to the dedicated IO service
|
||||
/// processes, and slow path for device configuration are still handled by the VMM process. It may
|
||||
/// also be used to control access permissions of virtio backend devices.
|
||||
pub trait VhostBackend: std::marker::Sized {
|
||||
/// Get a bitmask of supported virtio/vhost features.
|
||||
fn get_features(&self) -> Result<u64>;
|
||||
|
||||
/// Inform the vhost subsystem which features to enable.
|
||||
/// This should be a subset of supported features from get_features().
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `features` - Bitmask of features to set.
|
||||
fn set_features(&self, features: u64) -> Result<()>;
|
||||
|
||||
/// Set the current process as the owner of the vhost backend.
|
||||
/// This must be run before any other vhost commands.
|
||||
fn set_owner(&self) -> Result<()>;
|
||||
|
||||
/// Used to be sent to request disabling all rings
|
||||
/// This is no longer used.
|
||||
fn reset_owner(&self) -> Result<()>;
|
||||
|
||||
/// Set the guest memory mappings for vhost to use.
|
||||
fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()>;
|
||||
|
||||
/// Set base address for page modification logging.
|
||||
fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()>;
|
||||
|
||||
/// Specify an eventfd file descriptor to signal on log write.
|
||||
fn set_log_fd(&self, fd: RawFd) -> Result<()>;
|
||||
|
||||
/// Set the number of descriptors in the vring.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to set descriptor count for.
|
||||
/// * `num` - Number of descriptors in the queue.
|
||||
fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()>;
|
||||
|
||||
/// Set the addresses for a given vring.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to set addresses for.
|
||||
/// * `config_data` - Configuration data for a vring.
|
||||
fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()>;
|
||||
|
||||
/// Set the first index to look for available descriptors.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `num` - Index where available descriptors start.
|
||||
fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()>;
|
||||
|
||||
/// Get the available vring base offset.
|
||||
fn get_vring_base(&self, queue_index: usize) -> Result<u32>;
|
||||
|
||||
/// Set the eventfd to trigger when buffers have been used by the host.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd to trigger.
|
||||
fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()>;
|
||||
|
||||
/// Set the eventfd that will be signaled by the guest when buffers are
|
||||
/// available for the host to process.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd that will be signaled from guest.
|
||||
fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()>;
|
||||
|
||||
/// Set the eventfd that will be signaled by the guest when error happens.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd that will be signaled from guest.
|
||||
fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()>;
|
||||
}
|
||||
|
||||
/// An interface for setting up vhost-based backend drivers.
|
||||
///
|
||||
/// Vhost devices are subset of virtio devices, which improve virtio device's performance by
|
||||
/// delegating data plane operations to dedicated IO service processes. Vhost devices use the
|
||||
/// same virtqueue layout as virtio devices to allow vhost devices to be mapped directly to
|
||||
/// virtio devices.
|
||||
///
|
||||
/// The purpose of vhost is to implement a subset of a virtio device's functionality outside the
|
||||
/// VMM process. Typically fast paths for IO operations are delegated to the dedicated IO service
|
||||
/// processes, and slow path for device configuration are still handled by the VMM process. It may
|
||||
/// also be used to control access permissions of virtio backend devices.
|
||||
pub trait VhostBackend: std::marker::Sized {
|
||||
pub trait VhostBackendMut: std::marker::Sized {
|
||||
/// Get a bitmask of supported virtio/vhost features.
|
||||
fn get_features(&mut self) -> Result<u64>;
|
||||
|
||||
|
|
@ -154,10 +245,237 @@ pub trait VhostBackend: std::marker::Sized {
|
|||
fn set_vring_err(&mut self, queue_index: usize, fd: &EventFd) -> Result<()>;
|
||||
}
|
||||
|
||||
impl<T: VhostBackendMut> VhostBackend for RwLock<T> {
|
||||
fn get_features(&self) -> Result<u64> {
|
||||
self.write().unwrap().get_features()
|
||||
}
|
||||
|
||||
fn set_features(&self, features: u64) -> Result<()> {
|
||||
self.write().unwrap().set_features(features)
|
||||
}
|
||||
|
||||
fn set_owner(&self) -> Result<()> {
|
||||
self.write().unwrap().set_owner()
|
||||
}
|
||||
|
||||
fn reset_owner(&self) -> Result<()> {
|
||||
self.write().unwrap().reset_owner()
|
||||
}
|
||||
|
||||
fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
|
||||
self.write().unwrap().set_mem_table(regions)
|
||||
}
|
||||
|
||||
fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
|
||||
self.write().unwrap().set_log_base(base, fd)
|
||||
}
|
||||
|
||||
fn set_log_fd(&self, fd: RawFd) -> Result<()> {
|
||||
self.write().unwrap().set_log_fd(fd)
|
||||
}
|
||||
|
||||
fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()> {
|
||||
self.write().unwrap().set_vring_num(queue_index, num)
|
||||
}
|
||||
|
||||
fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
|
||||
self.write()
|
||||
.unwrap()
|
||||
.set_vring_addr(queue_index, config_data)
|
||||
}
|
||||
|
||||
fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()> {
|
||||
self.write().unwrap().set_vring_base(queue_index, base)
|
||||
}
|
||||
|
||||
fn get_vring_base(&self, queue_index: usize) -> Result<u32> {
|
||||
self.write().unwrap().get_vring_base(queue_index)
|
||||
}
|
||||
|
||||
fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
self.write().unwrap().set_vring_call(queue_index, fd)
|
||||
}
|
||||
|
||||
fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
self.write().unwrap().set_vring_kick(queue_index, fd)
|
||||
}
|
||||
|
||||
fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
self.write().unwrap().set_vring_err(queue_index, fd)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: VhostBackendMut> VhostBackend for RefCell<T> {
|
||||
fn get_features(&self) -> Result<u64> {
|
||||
self.borrow_mut().get_features()
|
||||
}
|
||||
|
||||
fn set_features(&self, features: u64) -> Result<()> {
|
||||
self.borrow_mut().set_features(features)
|
||||
}
|
||||
|
||||
fn set_owner(&self) -> Result<()> {
|
||||
self.borrow_mut().set_owner()
|
||||
}
|
||||
|
||||
fn reset_owner(&self) -> Result<()> {
|
||||
self.borrow_mut().reset_owner()
|
||||
}
|
||||
|
||||
fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
|
||||
self.borrow_mut().set_mem_table(regions)
|
||||
}
|
||||
|
||||
fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
|
||||
self.borrow_mut().set_log_base(base, fd)
|
||||
}
|
||||
|
||||
fn set_log_fd(&self, fd: RawFd) -> Result<()> {
|
||||
self.borrow_mut().set_log_fd(fd)
|
||||
}
|
||||
|
||||
fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()> {
|
||||
self.borrow_mut().set_vring_num(queue_index, num)
|
||||
}
|
||||
|
||||
fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
|
||||
self.borrow_mut().set_vring_addr(queue_index, config_data)
|
||||
}
|
||||
|
||||
fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()> {
|
||||
self.borrow_mut().set_vring_base(queue_index, base)
|
||||
}
|
||||
|
||||
fn get_vring_base(&self, queue_index: usize) -> Result<u32> {
|
||||
self.borrow_mut().get_vring_base(queue_index)
|
||||
}
|
||||
|
||||
fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
self.borrow_mut().set_vring_call(queue_index, fd)
|
||||
}
|
||||
|
||||
fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
self.borrow_mut().set_vring_kick(queue_index, fd)
|
||||
}
|
||||
|
||||
fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
self.borrow_mut().set_vring_err(queue_index, fd)
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use VringConfigData;
|
||||
|
||||
struct MockBackend {}
|
||||
|
||||
impl VhostBackendMut for MockBackend {
|
||||
fn get_features(&mut self) -> Result<u64> {
|
||||
Ok(0x1)
|
||||
}
|
||||
|
||||
fn set_features(&mut self, features: u64) -> Result<()> {
|
||||
assert_eq!(features, 0x1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_owner(&mut self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_owner(&mut self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_mem_table(&mut self, _regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_log_base(&mut self, base: u64, fd: Option<RawFd>) -> Result<()> {
|
||||
assert_eq!(base, 0x100);
|
||||
assert_eq!(fd, Some(100));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_log_fd(&mut self, fd: RawFd) -> Result<()> {
|
||||
assert_eq!(fd, 100);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_vring_num(&mut self, queue_index: usize, num: u16) -> Result<()> {
|
||||
assert_eq!(queue_index, 1);
|
||||
assert_eq!(num, 256);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_vring_addr(
|
||||
&mut self,
|
||||
queue_index: usize,
|
||||
_config_data: &VringConfigData,
|
||||
) -> Result<()> {
|
||||
assert_eq!(queue_index, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_vring_base(&mut self, queue_index: usize, base: u16) -> Result<()> {
|
||||
assert_eq!(queue_index, 1);
|
||||
assert_eq!(base, 2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_vring_base(&mut self, queue_index: usize) -> Result<u32> {
|
||||
assert_eq!(queue_index, 1);
|
||||
Ok(2)
|
||||
}
|
||||
|
||||
fn set_vring_call(&mut self, queue_index: usize, _fd: &EventFd) -> Result<()> {
|
||||
assert_eq!(queue_index, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_vring_kick(&mut self, queue_index: usize, _fd: &EventFd) -> Result<()> {
|
||||
assert_eq!(queue_index, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_vring_err(&mut self, queue_index: usize, _fd: &EventFd) -> Result<()> {
|
||||
assert_eq!(queue_index, 1);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vring_backend_mut() {
|
||||
let b = RwLock::new(MockBackend {});
|
||||
|
||||
assert_eq!(b.get_features().unwrap(), 0x1);
|
||||
b.set_features(0x1).unwrap();
|
||||
b.set_owner().unwrap();
|
||||
b.reset_owner().unwrap();
|
||||
b.set_mem_table(&[]).unwrap();
|
||||
b.set_log_base(0x100, Some(100)).unwrap();
|
||||
b.set_log_fd(100).unwrap();
|
||||
b.set_vring_num(1, 256).unwrap();
|
||||
|
||||
let config = VringConfigData {
|
||||
queue_max_size: 0x1000,
|
||||
queue_size: 0x2000,
|
||||
flags: 0x0,
|
||||
desc_table_addr: 0x4000,
|
||||
used_ring_addr: 0x5000,
|
||||
avail_ring_addr: 0x6000,
|
||||
log_addr: None,
|
||||
};
|
||||
b.set_vring_addr(1, &config).unwrap();
|
||||
|
||||
b.set_vring_base(1, 2).unwrap();
|
||||
assert_eq!(b.get_vring_base(1).unwrap(), 2);
|
||||
|
||||
let eventfd = EventFd::new(0).unwrap();
|
||||
b.set_vring_call(1, &eventfd).unwrap();
|
||||
b.set_vring_kick(1, &eventfd).unwrap();
|
||||
b.set_vring_err(1, &eventfd).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vring_config_data() {
|
||||
let mut config = VringConfigData {
|
||||
|
|
|
|||
|
|
@ -87,20 +87,20 @@ pub trait VhostKernBackend: AsRawFd {
|
|||
impl<T: VhostKernBackend> VhostBackend for T {
|
||||
/// Set the current process as the owner of this file descriptor.
|
||||
/// This must be run before any other vhost ioctls.
|
||||
fn set_owner(&mut self) -> Result<()> {
|
||||
fn set_owner(&self) -> Result<()> {
|
||||
// This ioctl is called on a valid vhost fd and has its return value checked.
|
||||
let ret = unsafe { ioctl(self, VHOST_SET_OWNER()) };
|
||||
ioctl_result(ret, ())
|
||||
}
|
||||
|
||||
fn reset_owner(&mut self) -> Result<()> {
|
||||
fn reset_owner(&self) -> Result<()> {
|
||||
// This ioctl is called on a valid vhost fd and has its return value checked.
|
||||
let ret = unsafe { ioctl(self, VHOST_RESET_OWNER()) };
|
||||
ioctl_result(ret, ())
|
||||
}
|
||||
|
||||
/// Get a bitmask of supported virtio/vhost features.
|
||||
fn get_features(&mut self) -> Result<u64> {
|
||||
fn get_features(&self) -> Result<u64> {
|
||||
let mut avail_features: u64 = 0;
|
||||
// This ioctl is called on a valid vhost fd and has its return value checked.
|
||||
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_GET_FEATURES(), &mut avail_features) };
|
||||
|
|
@ -112,14 +112,14 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
///
|
||||
/// # Arguments
|
||||
/// * `features` - Bitmask of features to set.
|
||||
fn set_features(&mut self, features: u64) -> Result<()> {
|
||||
fn set_features(&self, features: u64) -> Result<()> {
|
||||
// This ioctl is called on a valid vhost fd and has its return value checked.
|
||||
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_FEATURES(), &features) };
|
||||
ioctl_result(ret, ())
|
||||
}
|
||||
|
||||
/// Set the guest memory mappings for vhost to use.
|
||||
fn set_mem_table(&mut self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
|
||||
fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
|
||||
if regions.is_empty() || regions.len() > VHOST_MAX_MEMORY_REGIONS {
|
||||
return Err(Error::InvalidGuestMemory);
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
///
|
||||
/// # Arguments
|
||||
/// * `base` - Base address for page modification logging.
|
||||
fn set_log_base(&mut self, base: u64, fd: Option<RawFd>) -> Result<()> {
|
||||
fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
|
||||
if fd.is_some() {
|
||||
return Err(Error::LogAddress);
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
}
|
||||
|
||||
/// Specify an eventfd file descriptor to signal on log write.
|
||||
fn set_log_fd(&mut self, fd: RawFd) -> Result<()> {
|
||||
fn set_log_fd(&self, fd: RawFd) -> Result<()> {
|
||||
// This ioctl is called on a valid vhost fd and has its return value checked.
|
||||
let val: i32 = fd;
|
||||
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_LOG_FD(), &val) };
|
||||
|
|
@ -171,7 +171,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to set descriptor count for.
|
||||
/// * `num` - Number of descriptors in the queue.
|
||||
fn set_vring_num(&mut self, queue_index: usize, num: u16) -> Result<()> {
|
||||
fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()> {
|
||||
let vring_state = vhost_vring_state {
|
||||
index: queue_index as u32,
|
||||
num: u32::from(num),
|
||||
|
|
@ -187,7 +187,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to set addresses for.
|
||||
/// * `config_data` - Vring config data.
|
||||
fn set_vring_addr(&mut self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
|
||||
fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
|
||||
if !self.is_valid(config_data) {
|
||||
return Err(Error::InvalidQueue);
|
||||
}
|
||||
|
|
@ -212,7 +212,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `num` - Index where available descriptors start.
|
||||
fn set_vring_base(&mut self, queue_index: usize, base: u16) -> Result<()> {
|
||||
fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()> {
|
||||
let vring_state = vhost_vring_state {
|
||||
index: queue_index as u32,
|
||||
num: u32::from(base),
|
||||
|
|
@ -224,7 +224,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
}
|
||||
|
||||
/// Get a bitmask of supported virtio/vhost features.
|
||||
fn get_vring_base(&mut self, queue_index: usize) -> Result<u32> {
|
||||
fn get_vring_base(&self, queue_index: usize) -> Result<u32> {
|
||||
let vring_state = vhost_vring_state {
|
||||
index: queue_index as u32,
|
||||
num: 0,
|
||||
|
|
@ -239,7 +239,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd to trigger.
|
||||
fn set_vring_call(&mut self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
let vring_file = vhost_vring_file {
|
||||
index: queue_index as u32,
|
||||
fd: fd.as_raw_fd(),
|
||||
|
|
@ -256,7 +256,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd that will be signaled from guest.
|
||||
fn set_vring_kick(&mut self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
let vring_file = vhost_vring_file {
|
||||
index: queue_index as u32,
|
||||
fd: fd.as_raw_fd(),
|
||||
|
|
@ -272,7 +272,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
|
|||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd that will be signaled from the backend.
|
||||
fn set_vring_err(&mut self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
let vring_file = vhost_vring_file {
|
||||
index: queue_index as u32,
|
||||
fd: fd.as_raw_fd(),
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ impl Master {
|
|||
|
||||
impl VhostBackend for Master {
|
||||
/// Get from the underlying vhost implementation the feature bitmask.
|
||||
fn get_features(&mut self) -> Result<u64> {
|
||||
fn get_features(&self) -> Result<u64> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
let hdr = node.send_request_header(MasterReq::GET_FEATURES, None)?;
|
||||
let val = node.recv_reply::<VhostUserU64>(&hdr)?;
|
||||
|
|
@ -124,7 +124,7 @@ impl VhostBackend for Master {
|
|||
}
|
||||
|
||||
/// Enable features in the underlying vhost implementation using a bitmask.
|
||||
fn set_features(&mut self, features: u64) -> Result<()> {
|
||||
fn set_features(&self, features: u64) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
let val = VhostUserU64::new(features);
|
||||
let _ = node.send_request_with_body(MasterReq::SET_FEATURES, &val, None)?;
|
||||
|
|
@ -135,7 +135,7 @@ impl VhostBackend for Master {
|
|||
}
|
||||
|
||||
/// Set the current Master as an owner of the session.
|
||||
fn set_owner(&mut self) -> Result<()> {
|
||||
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();
|
||||
|
|
@ -145,7 +145,7 @@ impl VhostBackend for Master {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_owner(&mut self) -> Result<()> {
|
||||
fn reset_owner(&self) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
let _ = node.send_request_header(MasterReq::RESET_OWNER, None)?;
|
||||
// Don't wait for ACK here because the protocol feature negotiation process hasn't been
|
||||
|
|
@ -155,7 +155,7 @@ impl VhostBackend for Master {
|
|||
|
||||
/// Set the memory map regions on the slave so it can translate the vring
|
||||
/// addresses. In the ancillary data there is an array of file descriptors
|
||||
fn set_mem_table(&mut self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
|
||||
fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
|
||||
if regions.is_empty() || regions.len() > MAX_ATTACHED_FD_ENTRIES {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
}
|
||||
|
|
@ -187,7 +187,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(&mut self, base: u64, fd: Option<RawFd>) -> Result<()> {
|
||||
fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
let val = VhostUserU64::new(base);
|
||||
|
||||
|
|
@ -202,7 +202,7 @@ impl VhostBackend for Master {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn set_log_fd(&mut self, fd: RawFd) -> Result<()> {
|
||||
fn set_log_fd(&self, fd: RawFd) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
let fds = [fd];
|
||||
node.send_request_header(MasterReq::SET_LOG_FD, Some(&fds))?;
|
||||
|
|
@ -210,7 +210,7 @@ impl VhostBackend for Master {
|
|||
}
|
||||
|
||||
/// Set the size of the queue.
|
||||
fn set_vring_num(&mut self, queue_index: usize, num: u16) -> Result<()> {
|
||||
fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
if queue_index as u64 >= node.max_queue_num {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
|
|
@ -222,7 +222,7 @@ impl VhostBackend for Master {
|
|||
}
|
||||
|
||||
/// Sets the addresses of the different aspects of the vring.
|
||||
fn set_vring_addr(&mut self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
|
||||
fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
if queue_index as u64 >= node.max_queue_num
|
||||
|| config_data.flags & !(VhostUserVringAddrFlags::all().bits()) != 0
|
||||
|
|
@ -236,7 +236,7 @@ impl VhostBackend for Master {
|
|||
}
|
||||
|
||||
/// Sets the base offset in the available vring.
|
||||
fn set_vring_base(&mut self, queue_index: usize, base: u16) -> Result<()> {
|
||||
fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
if queue_index as u64 >= node.max_queue_num {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
|
|
@ -247,7 +247,7 @@ impl VhostBackend for Master {
|
|||
node.wait_for_ack(&hdr).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn get_vring_base(&mut self, queue_index: usize) -> Result<u32> {
|
||||
fn get_vring_base(&self, queue_index: usize) -> Result<u32> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
if queue_index as u64 >= node.max_queue_num {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
|
|
@ -263,7 +263,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. This signals that polling
|
||||
/// will be used instead of waiting for the call.
|
||||
fn set_vring_call(&mut self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
if queue_index as u64 >= node.max_queue_num {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
|
|
@ -276,7 +276,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. This signals that polling
|
||||
/// should be used instead of waiting for a kick.
|
||||
fn set_vring_kick(&mut self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
if queue_index as u64 >= node.max_queue_num {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
|
|
@ -288,7 +288,7 @@ impl VhostBackend for Master {
|
|||
/// Set the event file descriptor to signal when error occurs.
|
||||
/// 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(&mut self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
|
||||
let mut node = self.node.lock().unwrap();
|
||||
if queue_index as u64 >= node.max_queue_num {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
|
|
@ -654,7 +654,7 @@ mod tests {
|
|||
let listener = Listener::new(UNIX_SOCKET_MASTER, true).unwrap();
|
||||
listener.set_nonblocking(true).unwrap();
|
||||
|
||||
let mut master = Master::connect(UNIX_SOCKET_MASTER, 1).unwrap();
|
||||
let master = Master::connect(UNIX_SOCKET_MASTER, 1).unwrap();
|
||||
let mut slave = Endpoint::<MasterReq>::from_stream(listener.accept().unwrap().unwrap());
|
||||
|
||||
// Send two messages continuously
|
||||
|
|
@ -692,7 +692,7 @@ mod tests {
|
|||
#[test]
|
||||
#[ignore]
|
||||
fn test_features() {
|
||||
let (mut master, mut peer) = create_pair(UNIX_SOCKET_MASTER3);
|
||||
let (master, mut peer) = create_pair(UNIX_SOCKET_MASTER3);
|
||||
|
||||
master.set_owner().unwrap();
|
||||
let (hdr, rfds) = peer.recv_header().unwrap();
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_set_owner() {
|
||||
let slave_be = Arc::new(Mutex::new(DummySlaveReqHandler::new()));
|
||||
let (mut master, mut slave) =
|
||||
let (master, mut slave) =
|
||||
create_slave("/tmp/vhost_user_lib_unit_test_owner", slave_be.clone());
|
||||
|
||||
assert_eq!(slave_be.lock().unwrap().owned, false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue