Skip to content
This repository has been archived by the owner on Oct 24, 2022. It is now read-only.

Commit

Permalink
Inflight I/O: Implement missing traits
Browse files Browse the repository at this point in the history
This commit implements the get and set inflight fd members of the
VhostUserSlaveReqHandlerMut trait, which is used to pass inflight
I/O queue tracking regions as memfds.

Fixes #14.

Signed-off-by: Harshavardhan Unnibhavi <[email protected]>
  • Loading branch information
harshanavkis committed Jul 21, 2021
1 parent 1a45bc2 commit 9b9ee56
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ virtio-bindings = "0.1.0"
vm-memory = {version = ">=0.2.0", features = ["backend-mmap", "backend-atomic"]}
virtio-queue = { git = "https://github.com/rust-vmm/vm-virtio" }
vmm-sys-util = ">=0.3.1"
nix = "0.21.0"
70 changes: 59 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,32 @@
#[macro_use]
extern crate log;

use std::error;
use std::fs::File;
use std::io;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::prelude::IntoRawFd;
use std::result;
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::{error, mem};
use vhost::vhost_user::message::{
VhostUserConfigFlags, VhostUserMemoryRegion, VhostUserProtocolFeatures,
DescStatePacked, DescStateSplit, QueueRegionPacked, QueueRegionSplit, VhostUserConfigFlags,
VhostUserInflight, VhostUserMemoryRegion, VhostUserProtocolFeatures,
VhostUserSingleMemoryRegion, VhostUserVirtioFeatures, VhostUserVringAddrFlags,
VhostUserVringState,
};
use vhost::vhost_user::{
Error as VhostUserError, Listener, Result as VhostUserResult, SlaveFsCacheReq, SlaveListener,
VhostUserSlaveReqHandlerMut,
};
use virtio_bindings::bindings::virtio_net::VIRTIO_F_RING_PACKED;
use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
use virtio_queue::Queue;
use vm_memory::guest_memory::FileOffset;
use vm_memory::{
GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap, GuestRegionMmap,
MmapRegion,
};
use virtio_queue::Queue;
use vmm_sys_util::eventfd::EventFd;

const MAX_MEM_SLOTS: u64 = 32;
Expand Down Expand Up @@ -453,6 +455,7 @@ struct VhostUserHandler<S: VhostUserBackend> {
atomic_mem: GuestMemoryAtomic<GuestMemoryMmap>,
vrings: Vec<Arc<RwLock<Vring>>>,
worker_threads: Vec<thread::JoinHandle<VringWorkerResult<()>>>,
inflight_file: Option<File>,
}

impl<S: VhostUserBackend> VhostUserHandler<S> {
Expand Down Expand Up @@ -536,6 +539,7 @@ impl<S: VhostUserBackend> VhostUserHandler<S> {
atomic_mem,
vrings,
worker_threads,
inflight_file: None,
})
}

Expand Down Expand Up @@ -948,16 +952,60 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {

fn get_inflight_fd(
&mut self,
_inflight: &vhost::vhost_user::message::VhostUserInflight,
) -> VhostUserResult<(vhost::vhost_user::message::VhostUserInflight, File)> {
// Assume the backend hasn't negotiated the inflight feature; it
// wouldn't be correct for the backend to do so, as we don't (yet)
// provide a way for it to handle such requests.
Err(VhostUserError::InvalidOperation)
inflight: &VhostUserInflight,
) -> VhostUserResult<(VhostUserInflight, File)> {
let inflight_queue_region = nix::sys::memfd::memfd_create(
&std::ffi::CString::new("inflight-region").unwrap(),
nix::sys::memfd::MemFdCreateFlag::MFD_CLOEXEC,
)
.unwrap();

self.inflight_file = Some(unsafe { File::from_raw_fd(inflight_queue_region) });

let virtio_features = self.get_features().unwrap();
let total_mmap_size;
let queue_region_size;
let descr_state_size;
if virtio_features & (1 << VIRTIO_F_RING_PACKED) == 0 {
// Use descriptor and queue states for split virtqueues
// let single_queue_region = QueueRegionSplit::new(virtio_features, inflight.queue_size);
// let single_descriptor_state = DescStateSplit::new();

queue_region_size = mem::size_of::<QueueRegionSplit>();
descr_state_size = mem::size_of::<DescStateSplit>();
} else {
// Use descriptor and queue states for packed virtqueues
// let single_queue_region = QueueRegionPacked::new(virtio_features, inflight.queue_size);
// let single_descriptor_state = DescStatePacked::new();

queue_region_size = mem::size_of::<QueueRegionPacked>();
descr_state_size = mem::size_of::<DescStatePacked>();
}

total_mmap_size = (queue_region_size + descr_state_size * inflight.queue_size as usize)
* inflight.num_queues as usize;

nix::unistd::ftruncate(inflight_queue_region, total_mmap_size as i64).unwrap();

Ok((
VhostUserInflight {
mmap_size: total_mmap_size as u64,
mmap_offset: 0,
num_queues: inflight.num_queues,
queue_size: inflight.queue_size,
},
unsafe { File::from_raw_fd(inflight_queue_region) },
))
}

fn set_inflight_fd(&mut self, _inflight: &vhost::vhost_user::message::VhostUserInflight, _file: File) -> VhostUserResult<()> {
Err(VhostUserError::InvalidOperation)
fn set_inflight_fd(
&mut self,
_inflight: &VhostUserInflight,
file: File,
) -> VhostUserResult<()> {
self.inflight_file = Some(file);

Ok(())
}
}

Expand Down

0 comments on commit 9b9ee56

Please sign in to comment.