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

Commit 347357a

Browse files
committed
Inflight I/O: Implement missing traits
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]>
1 parent 1a45bc2 commit 347357a

File tree

2 files changed

+54
-11
lines changed

2 files changed

+54
-11
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ virtio-bindings = "0.1.0"
1414
vm-memory = {version = ">=0.2.0", features = ["backend-mmap", "backend-atomic"]}
1515
virtio-queue = { git = "https://github.com/rust-vmm/vm-virtio" }
1616
vmm-sys-util = ">=0.3.1"
17+
nix = "0.21.0"

src/lib.rs

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,32 @@
77
#[macro_use]
88
extern crate log;
99

10-
use std::error;
1110
use std::fs::File;
1211
use std::io;
1312
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
1413
use std::os::unix::prelude::IntoRawFd;
1514
use std::result;
1615
use std::sync::{Arc, Mutex, RwLock};
1716
use std::thread;
17+
use std::{error, mem};
1818
use vhost::vhost_user::message::{
19-
VhostUserConfigFlags, VhostUserMemoryRegion, VhostUserProtocolFeatures,
19+
DescStatePacked, DescStateSplit, QueueRegionPacked, QueueRegionSplit, VhostUserConfigFlags,
20+
VhostUserInflight, VhostUserMemoryRegion, VhostUserProtocolFeatures,
2021
VhostUserSingleMemoryRegion, VhostUserVirtioFeatures, VhostUserVringAddrFlags,
2122
VhostUserVringState,
2223
};
2324
use vhost::vhost_user::{
2425
Error as VhostUserError, Listener, Result as VhostUserResult, SlaveFsCacheReq, SlaveListener,
2526
VhostUserSlaveReqHandlerMut,
2627
};
28+
use virtio_bindings::bindings::virtio_net::VIRTIO_F_RING_PACKED;
2729
use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
30+
use virtio_queue::Queue;
2831
use vm_memory::guest_memory::FileOffset;
2932
use vm_memory::{
3033
GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap, GuestRegionMmap,
3134
MmapRegion,
3235
};
33-
use virtio_queue::Queue;
3436
use vmm_sys_util::eventfd::EventFd;
3537

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

458461
impl<S: VhostUserBackend> VhostUserHandler<S> {
@@ -536,6 +539,7 @@ impl<S: VhostUserBackend> VhostUserHandler<S> {
536539
atomic_mem,
537540
vrings,
538541
worker_threads,
542+
inflight_file: None,
539543
})
540544
}
541545

@@ -948,16 +952,54 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
948952

949953
fn get_inflight_fd(
950954
&mut self,
951-
_inflight: &vhost::vhost_user::message::VhostUserInflight,
952-
) -> VhostUserResult<(vhost::vhost_user::message::VhostUserInflight, File)> {
953-
// Assume the backend hasn't negotiated the inflight feature; it
954-
// wouldn't be correct for the backend to do so, as we don't (yet)
955-
// provide a way for it to handle such requests.
956-
Err(VhostUserError::InvalidOperation)
955+
inflight: &VhostUserInflight,
956+
) -> VhostUserResult<(VhostUserInflight, File)> {
957+
let inflight_queue_region = nix::sys::memfd::memfd_create(
958+
&std::ffi::CString::new("inflight-region").unwrap(),
959+
nix::sys::memfd::MemFdCreateFlag::MFD_CLOEXEC,
960+
)
961+
.unwrap();
962+
963+
self.inflight_file = Some(unsafe { File::from_raw_fd(inflight_queue_region) });
964+
965+
let virtio_features = self.get_features().unwrap();
966+
let total_mmap_size;
967+
let queue_region_size;
968+
let descr_state_size;
969+
if virtio_features & (1 << VIRTIO_F_RING_PACKED) == 0 {
970+
// Use descriptor and queue states for split virtqueues
971+
queue_region_size = mem::size_of::<QueueRegionSplit>();
972+
descr_state_size = mem::size_of::<DescStateSplit>();
973+
} else {
974+
// Use descriptor and queue states for packed virtqueues
975+
queue_region_size = mem::size_of::<QueueRegionPacked>();
976+
descr_state_size = mem::size_of::<DescStatePacked>();
977+
}
978+
979+
total_mmap_size = (queue_region_size + descr_state_size * inflight.queue_size as usize)
980+
* inflight.num_queues as usize;
981+
982+
nix::unistd::ftruncate(inflight_queue_region, total_mmap_size as i64).unwrap();
983+
984+
Ok((
985+
VhostUserInflight {
986+
mmap_size: total_mmap_size as u64,
987+
mmap_offset: 0,
988+
num_queues: inflight.num_queues,
989+
queue_size: inflight.queue_size,
990+
},
991+
unsafe { File::from_raw_fd(inflight_queue_region) },
992+
))
957993
}
958994

959-
fn set_inflight_fd(&mut self, _inflight: &vhost::vhost_user::message::VhostUserInflight, _file: File) -> VhostUserResult<()> {
960-
Err(VhostUserError::InvalidOperation)
995+
fn set_inflight_fd(
996+
&mut self,
997+
_inflight: &VhostUserInflight,
998+
file: File,
999+
) -> VhostUserResult<()> {
1000+
self.inflight_file = Some(file);
1001+
1002+
Ok(())
9611003
}
9621004
}
9631005

0 commit comments

Comments
 (0)