Prepare vmm_vhost to be milti-platform 1/2
The patch prepares backend.rs and connection.rs to be platform
independent by
- depending on base instead on sys_util
- using base::Event over sys_util::EventFd
- replacing RawFd usage with RawDescriptor and derivatives
To keep the noise low, the patch
- aliases structs/traits (Event as EventFd)
- does not rename variables (say from fd to rd).
Note: With this patch the crate/files are not completely platform
independent.
Test: Built, clippy and fmt
Bug: b:213151429
Change-Id: Id93d4a70db627578e6577017f8ca4d69f892d69a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3460427
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Vikram Auradkar <auradkar@google.com>
diff --git a/common/sys_util/src/descriptor.rs b/common/sys_util/src/descriptor.rs
index b83bfd4..fe81431 100644
--- a/common/sys_util/src/descriptor.rs
+++ b/common/sys_util/src/descriptor.rs
@@ -18,6 +18,8 @@
pub type RawDescriptor = RawFd;
+pub const INVALID_DESCRIPTOR: RawDescriptor = -1;
+
/// Trait for forfeiting ownership of the current raw descriptor, and returning the raw descriptor
pub trait IntoRawDescriptor {
fn into_raw_descriptor(self) -> RawDescriptor;
diff --git a/devices/src/virtio/vhost/user/vmm/handler.rs b/devices/src/virtio/vhost/user/vmm/handler.rs
index 15fcf05..4021868 100644
--- a/devices/src/virtio/vhost/user/vmm/handler.rs
+++ b/devices/src/virtio/vhost/user/vmm/handler.rs
@@ -170,7 +170,7 @@
/// Sets the channel for device-specific messages.
pub fn set_device_request_channel(&mut self, channel: Tube) -> Result<()> {
self.vu
- .set_slave_request_fd(&channel.as_raw_descriptor())
+ .set_slave_request_fd(&channel)
.map_err(Error::SetDeviceRequestChannel)
}
@@ -236,10 +236,10 @@
.map_err(Error::SetVringBase)?;
self.vu
- .set_vring_call(queue_index, &irqfd.0)
+ .set_vring_call(queue_index, irqfd)
.map_err(Error::SetVringCall)?;
self.vu
- .set_vring_kick(queue_index, &queue_evt.0)
+ .set_vring_kick(queue_index, queue_evt)
.map_err(Error::SetVringKick)?;
self.vu
.set_vring_enable(queue_index, true)
diff --git a/third_party/vmm_vhost/Cargo.toml b/third_party/vmm_vhost/Cargo.toml
index f90e542..f5c10e2 100644
--- a/third_party/vmm_vhost/Cargo.toml
+++ b/third_party/vmm_vhost/Cargo.toml
@@ -18,6 +18,7 @@
[dependencies]
anyhow = "*"
+base = { path = "../../common/base" }
bitflags = ">=1.0.1"
data_model= "*"
libc = ">=0.2.39"
diff --git a/third_party/vmm_vhost/src/backend.rs b/third_party/vmm_vhost/src/backend.rs
index a799563..548434a 100644
--- a/third_party/vmm_vhost/src/backend.rs
+++ b/third_party/vmm_vhost/src/backend.rs
@@ -9,11 +9,12 @@
//! Common traits and structs for vhost-user backend drivers.
+use base::RawDescriptor;
use std::cell::RefCell;
-use std::os::unix::io::RawFd;
use std::sync::RwLock;
-use sys_util::EventFd;
+// TODO(b/219522861): Remove this alias and use Event in the code.
+use base::Event as EventFd;
use super::Result;
@@ -70,7 +71,7 @@
/// Optional offset where region starts in the mapped memory.
pub mmap_offset: u64,
/// Optional file descriptor for mmap.
- pub mmap_handle: RawFd,
+ pub mmap_handle: RawDescriptor,
}
/// An interface for setting up vhost-based backend drivers with interior mutability.
@@ -107,10 +108,10 @@
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<()>;
+ fn set_log_base(&self, base: u64, fd: Option<RawDescriptor>) -> Result<()>;
/// Specify an eventfd file descriptor to signal on log write.
- fn set_log_fd(&self, fd: RawFd) -> Result<()>;
+ fn set_log_fd(&self, fd: RawDescriptor) -> Result<()>;
/// Set the number of descriptors in the vring.
///
@@ -193,10 +194,10 @@
fn set_mem_table(&mut self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()>;
/// Set base address for page modification logging.
- fn set_log_base(&mut self, base: u64, fd: Option<RawFd>) -> Result<()>;
+ fn set_log_base(&mut self, base: u64, fd: Option<RawDescriptor>) -> Result<()>;
/// Specify an eventfd file descriptor to signal on log write.
- fn set_log_fd(&mut self, fd: RawFd) -> Result<()>;
+ fn set_log_fd(&mut self, fd: RawDescriptor) -> Result<()>;
/// Set the number of descriptors in the vring.
///
@@ -266,11 +267,11 @@
self.write().unwrap().set_mem_table(regions)
}
- fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
+ fn set_log_base(&self, base: u64, fd: Option<RawDescriptor>) -> Result<()> {
self.write().unwrap().set_log_base(base, fd)
}
- fn set_log_fd(&self, fd: RawFd) -> Result<()> {
+ fn set_log_fd(&self, fd: RawDescriptor) -> Result<()> {
self.write().unwrap().set_log_fd(fd)
}
@@ -326,11 +327,11 @@
self.borrow_mut().set_mem_table(regions)
}
- fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
+ fn set_log_base(&self, base: u64, fd: Option<RawDescriptor>) -> Result<()> {
self.borrow_mut().set_log_base(base, fd)
}
- fn set_log_fd(&self, fd: RawFd) -> Result<()> {
+ fn set_log_fd(&self, fd: RawDescriptor) -> Result<()> {
self.borrow_mut().set_log_fd(fd)
}
@@ -390,13 +391,13 @@
Ok(())
}
- fn set_log_base(&mut self, base: u64, fd: Option<RawFd>) -> Result<()> {
+ fn set_log_base(&mut self, base: u64, fd: Option<RawDescriptor>) -> Result<()> {
assert_eq!(base, 0x100);
assert_eq!(fd, Some(100));
Ok(())
}
- fn set_log_fd(&mut self, fd: RawFd) -> Result<()> {
+ fn set_log_fd(&mut self, fd: RawDescriptor) -> Result<()> {
assert_eq!(fd, 100);
Ok(())
}
diff --git a/third_party/vmm_vhost/src/connection.rs b/third_party/vmm_vhost/src/connection.rs
index 60f10b3..6dc4469 100644
--- a/third_party/vmm_vhost/src/connection.rs
+++ b/third_party/vmm_vhost/src/connection.rs
@@ -8,10 +8,10 @@
#[cfg(feature = "vfio-device")]
pub mod vfio;
+use base::RawDescriptor;
use std::fs::File;
use std::io::{IoSlice, IoSliceMut};
use std::mem;
-use std::os::unix::io::RawFd;
use std::path::Path;
use data_model::DataInit;
@@ -47,7 +47,7 @@
///
/// # Return:
/// * - number of bytes sent on success
- fn send_iovec(&mut self, iovs: &[IoSlice], fds: Option<&[RawFd]>) -> Result<usize>;
+ fn send_iovec(&mut self, iovs: &[IoSlice], fds: Option<&[RawDescriptor]>) -> Result<usize>;
/// Reads bytes into the given scatter/gather vectors with optional attached file.
///
@@ -120,7 +120,7 @@
fn send_iovec_all(
&mut self,
mut iovs: &mut [&[u8]],
- mut fds: Option<&[RawFd]>,
+ mut fds: Option<&[RawDescriptor]>,
) -> Result<usize> {
// Guarantee that `iovs` becomes empty if it doesn't contain any data.
advance_slices(&mut iovs, 0);
@@ -151,7 +151,7 @@
/// # Return:
/// * - number of bytes sent on success
#[cfg(test)]
- fn send_slice(&mut self, data: IoSlice, fds: Option<&[RawFd]>) -> Result<usize> {
+ fn send_slice(&mut self, data: IoSlice, fds: Option<&[RawDescriptor]>) -> Result<usize> {
self.send_iovec(&[data], fds)
}
@@ -161,7 +161,11 @@
/// * - number of bytes sent on success
/// * - PartialMessage: received a partial message.
/// * - backend specific errors
- fn send_header(&mut self, hdr: &VhostUserMsgHeader<R>, fds: Option<&[RawFd]>) -> Result<()> {
+ fn send_header(
+ &mut self,
+ hdr: &VhostUserMsgHeader<R>,
+ fds: Option<&[RawDescriptor]>,
+ ) -> Result<()> {
let mut iovs = [hdr.as_slice()];
let bytes = self.send_iovec_all(&mut iovs[..], fds)?;
if bytes != mem::size_of::<VhostUserMsgHeader<R>>() {
@@ -182,7 +186,7 @@
&mut self,
hdr: &VhostUserMsgHeader<R>,
body: &T,
- fds: Option<&[RawFd]>,
+ fds: Option<&[RawDescriptor]>,
) -> Result<()> {
if mem::size_of::<T>() > MAX_MSG_SIZE {
return Err(Error::OversizedMsg);
@@ -209,7 +213,7 @@
hdr: &VhostUserMsgHeader<R>,
body: &T,
payload: &[u8],
- fds: Option<&[RawFd]>,
+ fds: Option<&[RawDescriptor]>,
) -> Result<()> {
let len = payload.len();
if mem::size_of::<T>() > MAX_MSG_SIZE {
diff --git a/third_party/vmm_vhost/src/lib.rs b/third_party/vmm_vhost/src/lib.rs
index 14281f2..919a317 100644
--- a/third_party/vmm_vhost/src/lib.rs
+++ b/third_party/vmm_vhost/src/lib.rs
@@ -220,6 +220,7 @@
use super::*;
use crate::backend::VhostBackend;
use crate::{VhostUserMemoryRegionInfo, VringConfigData};
+ use base::AsRawDescriptor;
use tempfile::{tempfile, Builder, TempDir};
fn temp_dir() -> TempDir {
@@ -417,13 +418,13 @@
let num = master.get_queue_num().unwrap();
assert_eq!(num, 2);
- let eventfd = sys_util::EventFd::new().unwrap();
+ let eventfd = base::Event::new().unwrap();
let mem = [VhostUserMemoryRegionInfo {
guest_phys_addr: 0,
memory_size: 0x10_0000,
userspace_addr: 0,
mmap_offset: 0,
- mmap_handle: eventfd.as_raw_fd(),
+ mmap_handle: eventfd.as_raw_descriptor(),
}];
master.set_mem_table(&mem).unwrap();
@@ -442,8 +443,10 @@
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_log_base(0, Some(eventfd.as_raw_descriptor()))
+ .unwrap();
+ master.set_log_fd(eventfd.as_raw_descriptor()).unwrap();
master.set_vring_num(0, 256).unwrap();
master.set_vring_base(0, 0).unwrap();
diff --git a/third_party/vmm_vhost/src/master.rs b/third_party/vmm_vhost/src/master.rs
index 1afa670..0b82916 100644
--- a/third_party/vmm_vhost/src/master.rs
+++ b/third_party/vmm_vhost/src/master.rs
@@ -3,15 +3,16 @@
//! Traits and Struct for vhost-user master.
+use base::{AsRawDescriptor, RawDescriptor};
use std::fs::File;
use std::mem;
-use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::net::UnixStream;
use std::path::Path;
use std::sync::{Arc, Mutex, MutexGuard};
+// TODO(b/219522861): Remove this alias and use Event in the code.
+use base::Event as EventFd;
use data_model::DataInit;
-use sys_util::EventFd;
use super::connection::{Endpoint, EndpointExt};
use super::message::*;
@@ -51,7 +52,7 @@
fn set_config(&mut self, offset: u32, flags: VhostUserConfigFlags, buf: &[u8]) -> Result<()>;
/// Setup slave communication channel.
- fn set_slave_request_fd(&mut self, fd: &dyn AsRawFd) -> Result<()>;
+ fn set_slave_request_fd(&mut self, fd: &dyn AsRawDescriptor) -> Result<()>;
/// Retrieve shared buffer for inflight I/O tracking.
fn get_inflight_fd(
@@ -60,7 +61,7 @@
) -> Result<(VhostUserInflight, File)>;
/// Set shared buffer for inflight I/O tracking.
- fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, fd: RawFd) -> Result<()>;
+ fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, fd: RawDescriptor) -> Result<()>;
/// Query the maximum amount of memory slots supported by the backend.
fn get_max_mem_slots(&mut self) -> Result<u64>;
@@ -212,7 +213,7 @@
// 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<()> {
+ fn set_log_base(&self, base: u64, fd: Option<RawDescriptor>) -> Result<()> {
let mut node = self.node();
let val = VhostUserU64::new(base);
@@ -227,7 +228,7 @@
Ok(())
}
- fn set_log_fd(&self, fd: RawFd) -> Result<()> {
+ fn set_log_fd(&self, fd: RawDescriptor) -> Result<()> {
let mut node = self.node();
let fds = [fd];
let hdr = node.send_request_header(MasterReq::SET_LOG_FD, Some(&fds))?;
@@ -293,7 +294,11 @@
if queue_index as u64 >= node.max_queue_num {
return Err(VhostUserError::InvalidParam);
}
- let hdr = node.send_fd_for_vring(MasterReq::SET_VRING_CALL, queue_index, fd.as_raw_fd())?;
+ let hdr = node.send_fd_for_vring(
+ MasterReq::SET_VRING_CALL,
+ queue_index,
+ fd.as_raw_descriptor(),
+ )?;
node.wait_for_ack(&hdr)
}
@@ -306,7 +311,11 @@
if queue_index as u64 >= node.max_queue_num {
return Err(VhostUserError::InvalidParam);
}
- let hdr = node.send_fd_for_vring(MasterReq::SET_VRING_KICK, queue_index, fd.as_raw_fd())?;
+ let hdr = node.send_fd_for_vring(
+ MasterReq::SET_VRING_KICK,
+ queue_index,
+ fd.as_raw_descriptor(),
+ )?;
node.wait_for_ack(&hdr)
}
@@ -318,7 +327,11 @@
if queue_index as u64 >= node.max_queue_num {
return Err(VhostUserError::InvalidParam);
}
- let hdr = node.send_fd_for_vring(MasterReq::SET_VRING_ERR, queue_index, fd.as_raw_fd())?;
+ let hdr = node.send_fd_for_vring(
+ MasterReq::SET_VRING_ERR,
+ queue_index,
+ fd.as_raw_descriptor(),
+ )?;
node.wait_for_ack(&hdr)
}
}
@@ -443,12 +456,12 @@
node.wait_for_ack(&hdr)
}
- fn set_slave_request_fd(&mut self, fd: &dyn AsRawFd) -> Result<()> {
+ fn set_slave_request_fd(&mut self, fd: &dyn AsRawDescriptor) -> Result<()> {
let mut node = self.node();
if node.acked_protocol_features & VhostUserProtocolFeatures::SLAVE_REQ.bits() == 0 {
return Err(VhostUserError::InvalidOperation);
}
- let fds = [fd.as_raw_fd()];
+ let fds = [fd.as_raw_descriptor()];
let hdr = node.send_request_header(MasterReq::SET_SLAVE_REQ_FD, Some(&fds))?;
node.wait_for_ack(&hdr)
}
@@ -471,7 +484,7 @@
}
}
- fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, fd: RawFd) -> Result<()> {
+ fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, fd: RawDescriptor) -> Result<()> {
let mut node = self.node();
if node.acked_protocol_features & VhostUserProtocolFeatures::INFLIGHT_SHMFD.bits() == 0 {
return Err(VhostUserError::InvalidOperation);
@@ -541,17 +554,17 @@
}
}
-impl<E: Endpoint<MasterReq> + AsRawFd> AsRawFd for Master<E> {
- fn as_raw_fd(&self) -> RawFd {
+impl<E: Endpoint<MasterReq> + AsRawDescriptor> AsRawDescriptor for Master<E> {
+ fn as_raw_descriptor(&self) -> RawDescriptor {
let node = self.node();
- node.main_sock.as_raw_fd()
+ node.main_sock.as_raw_descriptor()
}
}
/// Context object to pass guest memory configuration to VhostUserMaster::set_mem_table().
struct VhostUserMemoryContext {
regions: VhostUserMemoryPayload,
- fds: Vec<RawFd>,
+ fds: Vec<RawDescriptor>,
}
impl VhostUserMemoryContext {
@@ -563,8 +576,8 @@
}
}
- /// Append a user memory region and corresponding RawFd into the context object.
- pub fn append(&mut self, region: &VhostUserMemoryRegion, fd: RawFd) {
+ /// Append a user memory region and corresponding RawDescriptor into the context object.
+ pub fn append(&mut self, region: &VhostUserMemoryRegion, fd: RawDescriptor) {
self.regions.push(*region);
self.fds.push(fd);
}
@@ -595,7 +608,7 @@
fn send_request_header(
&mut self,
code: MasterReq,
- fds: Option<&[RawFd]>,
+ fds: Option<&[RawDescriptor]>,
) -> VhostUserResult<VhostUserMsgHeader<MasterReq>> {
self.check_state()?;
let hdr = self.new_request_header(code, 0);
@@ -607,7 +620,7 @@
&mut self,
code: MasterReq,
msg: &T,
- fds: Option<&[RawFd]>,
+ fds: Option<&[RawDescriptor]>,
) -> VhostUserResult<VhostUserMsgHeader<MasterReq>> {
if mem::size_of::<T>() > MAX_MSG_SIZE {
return Err(VhostUserError::InvalidParam);
@@ -624,7 +637,7 @@
code: MasterReq,
msg: &T,
payload: &[u8],
- fds: Option<&[RawFd]>,
+ fds: Option<&[RawDescriptor]>,
) -> VhostUserResult<VhostUserMsgHeader<MasterReq>> {
let len = mem::size_of::<T>() + payload.len();
if len > MAX_MSG_SIZE {
@@ -647,7 +660,7 @@
&mut self,
code: MasterReq,
queue_index: usize,
- fd: RawFd,
+ fd: RawDescriptor,
) -> VhostUserResult<VhostUserMsgHeader<MasterReq>> {
if queue_index as u64 >= self.max_queue_num {
return Err(VhostUserError::InvalidParam);
@@ -793,7 +806,7 @@
let master = Master::<SocketEndpoint<_>>::connect(&path, 1).unwrap();
let mut slave = SocketEndpoint::<MasterReq>::from(listener.accept().unwrap().unwrap());
- assert!(master.as_raw_fd() > 0);
+ assert!(master.as_raw_descriptor() > 0);
// Send two messages continuously
master.set_owner().unwrap();
master.reset_owner().unwrap();