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

Commit ee492da

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 ee492da

File tree

1 file changed

+55
-11
lines changed

1 file changed

+55
-11
lines changed

src/lib.rs

Lines changed: 55 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,56 @@ 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 = unsafe {
958+
libc::syscall(
959+
libc::SYS_memfd_create,
960+
&std::ffi::CString::new("inflight-region").unwrap(),
961+
libc::MFD_CLOEXEC,
962+
)
963+
};
964+
965+
self.inflight_file = Some(unsafe { File::from_raw_fd(inflight_queue_region as RawFd) });
966+
967+
let virtio_features = self.get_features().unwrap();
968+
let total_mmap_size;
969+
let queue_region_size;
970+
let descr_state_size;
971+
if virtio_features & (1 << VIRTIO_F_RING_PACKED) == 0 {
972+
// Use descriptor and queue states for split virtqueues
973+
queue_region_size = mem::size_of::<QueueRegionSplit>();
974+
descr_state_size = mem::size_of::<DescStateSplit>();
975+
} else {
976+
// Use descriptor and queue states for packed virtqueues
977+
queue_region_size = mem::size_of::<QueueRegionPacked>();
978+
descr_state_size = mem::size_of::<DescStatePacked>();
979+
}
980+
981+
total_mmap_size = (queue_region_size + descr_state_size * inflight.queue_size as usize)
982+
* inflight.num_queues as usize;
983+
984+
unsafe { libc::ftruncate(inflight_queue_region as i32, total_mmap_size as i64) };
985+
986+
Ok((
987+
VhostUserInflight {
988+
mmap_size: total_mmap_size as u64,
989+
mmap_offset: 0,
990+
num_queues: inflight.num_queues,
991+
queue_size: inflight.queue_size,
992+
},
993+
unsafe { File::from_raw_fd(inflight_queue_region as RawFd) },
994+
))
957995
}
958996

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

0 commit comments

Comments
 (0)