|
7 | 7 | #[macro_use]
|
8 | 8 | extern crate log;
|
9 | 9 |
|
10 |
| -use std::error; |
11 | 10 | use std::fs::File;
|
12 | 11 | use std::io;
|
13 | 12 | use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
14 | 13 | use std::os::unix::prelude::IntoRawFd;
|
15 | 14 | use std::result;
|
16 | 15 | use std::sync::{Arc, Mutex, RwLock};
|
17 | 16 | use std::thread;
|
| 17 | +use std::{error, mem}; |
18 | 18 | use vhost::vhost_user::message::{
|
19 |
| - VhostUserConfigFlags, VhostUserMemoryRegion, VhostUserProtocolFeatures, |
| 19 | + DescStatePacked, DescStateSplit, QueueRegionPacked, QueueRegionSplit, VhostUserConfigFlags, |
| 20 | + VhostUserInflight, VhostUserMemoryRegion, VhostUserProtocolFeatures, |
20 | 21 | VhostUserSingleMemoryRegion, VhostUserVirtioFeatures, VhostUserVringAddrFlags,
|
21 | 22 | VhostUserVringState,
|
22 | 23 | };
|
23 | 24 | use vhost::vhost_user::{
|
24 | 25 | Error as VhostUserError, Listener, Result as VhostUserResult, SlaveFsCacheReq, SlaveListener,
|
25 | 26 | VhostUserSlaveReqHandlerMut,
|
26 | 27 | };
|
| 28 | +use virtio_bindings::bindings::virtio_net::VIRTIO_F_RING_PACKED; |
27 | 29 | use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
|
| 30 | +use virtio_queue::Queue; |
28 | 31 | use vm_memory::guest_memory::FileOffset;
|
29 | 32 | use vm_memory::{
|
30 | 33 | GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap, GuestRegionMmap,
|
31 | 34 | MmapRegion,
|
32 | 35 | };
|
33 |
| -use virtio_queue::Queue; |
34 | 36 | use vmm_sys_util::eventfd::EventFd;
|
35 | 37 |
|
36 | 38 | const MAX_MEM_SLOTS: u64 = 32;
|
@@ -453,6 +455,7 @@ struct VhostUserHandler<S: VhostUserBackend> {
|
453 | 455 | atomic_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
454 | 456 | vrings: Vec<Arc<RwLock<Vring>>>,
|
455 | 457 | worker_threads: Vec<thread::JoinHandle<VringWorkerResult<()>>>,
|
| 458 | + inflight_file: Option<File>, |
456 | 459 | }
|
457 | 460 |
|
458 | 461 | impl<S: VhostUserBackend> VhostUserHandler<S> {
|
@@ -536,6 +539,7 @@ impl<S: VhostUserBackend> VhostUserHandler<S> {
|
536 | 539 | atomic_mem,
|
537 | 540 | vrings,
|
538 | 541 | worker_threads,
|
| 542 | + inflight_file: None, |
539 | 543 | })
|
540 | 544 | }
|
541 | 545 |
|
@@ -948,16 +952,54 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandlerMut for VhostUserHandler<S> {
|
948 | 952 |
|
949 | 953 | fn get_inflight_fd(
|
950 | 954 | &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 | + )) |
957 | 993 | }
|
958 | 994 |
|
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(()) |
961 | 1003 | }
|
962 | 1004 | }
|
963 | 1005 |
|
|
0 commit comments