|
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,56 @@ 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 = 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 | + )) |
957 | 995 | } |
958 | 996 |
|
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(()) |
961 | 1005 | } |
962 | 1006 | } |
963 | 1007 |
|
|
0 commit comments