From 2507cc57bc0145eb57305e60f6a7c21f3b4c9192 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Sun, 8 Mar 2020 22:41:30 +0000 Subject: vm_control: make MaybeOwnedFd generic This will allow more easily sending types other than File over sockets, (e.g., UnixSeqpacket). --- .../host_backend/host_backend_device_provider.rs | 7 +-- devices/src/virtio/wl.rs | 30 ++++++------ msg_socket/src/msg_on_socket.rs | 4 ++ src/wl.rs | 53 +++++----------------- sys_util/src/net.rs | 1 + sys_util/src/shm.rs | 1 + vm_control/src/lib.rs | 37 ++++++++++----- 7 files changed, 61 insertions(+), 72 deletions(-) diff --git a/devices/src/usb/host_backend/host_backend_device_provider.rs b/devices/src/usb/host_backend/host_backend_device_provider.rs index f60983f..c5debf1 100644 --- a/devices/src/usb/host_backend/host_backend_device_provider.rs +++ b/devices/src/usb/host_backend/host_backend_device_provider.rs @@ -12,6 +12,7 @@ use crate::utils::AsyncJobQueue; use crate::utils::{EventHandler, EventLoop, FailHandle}; use msg_socket::{MsgReceiver, MsgSender, MsgSocket}; use std::collections::HashMap; +use std::fs::File; use std::mem; use std::os::unix::io::{AsRawFd, RawFd}; use std::time::Duration; @@ -160,7 +161,7 @@ impl ProviderInner { /// Open a usbdevfs file to create a host USB device object. /// `fd` should be an open file descriptor for a file in `/dev/bus/usb`. - fn handle_attach_device(&self, fd: Option) -> UsbControlResult { + fn handle_attach_device(&self, fd: Option>) -> UsbControlResult { let usb_file = match fd { Some(MaybeOwnedFd::Owned(file)) => file, _ => { @@ -185,7 +186,7 @@ impl ProviderInner { }); if let Err(e) = self.event_loop.add_event( - &MaybeOwnedFd::Borrowed(raw_fd), + &MaybeOwnedFd::::Borrowed(raw_fd), WatchingEvents::empty().set_read().set_write(), Arc::downgrade(&event_handler), ) { @@ -232,7 +233,7 @@ impl ProviderInner { if let Err(e) = self .event_loop - .remove_event_for_fd(&MaybeOwnedFd::Borrowed(fd.as_raw_fd())) + .remove_event_for_fd(&MaybeOwnedFd::::Borrowed(fd.as_raw_fd())) { error!( "failed to remove poll change handler from event loop: {}", diff --git a/devices/src/virtio/wl.rs b/devices/src/virtio/wl.rs index a685e51..a38d0fe 100644 --- a/devices/src/virtio/wl.rs +++ b/devices/src/virtio/wl.rs @@ -77,16 +77,16 @@ use sys_util::net::UnixSeqpacket; #[derive(Debug, MsgOnSocket)] pub struct SingleFd { - pub memfd: MaybeOwnedFd, - pub interrupt: MaybeOwnedFd, - pub interrupt_resample_evt: MaybeOwnedFd, + pub shm: MaybeOwnedFd, + pub interrupt: MaybeOwnedFd, + pub interrupt_resample_evt: MaybeOwnedFd, pub in_queue: Queue, pub out_queue: Queue, - pub vm_socket: MaybeOwnedFd, + pub vm_socket: MaybeOwnedFd, pub use_transition_flags: bool, - pub in_queue_evt: MaybeOwnedFd, - pub out_queue_evt: MaybeOwnedFd, - pub kill_evt: MaybeOwnedFd, + pub in_queue_evt: MaybeOwnedFd, + pub out_queue_evt: MaybeOwnedFd, + pub kill_evt: MaybeOwnedFd, } type Socket = MsgSocket; @@ -1691,18 +1691,16 @@ impl VirtioDevice for Wl { let (ours, theirs) = UnixSeqpacket::pair().expect("pair failed"); if let Err(e) = SOCKET.send(&SingleFd { - memfd: MaybeOwnedFd::Borrowed(mem.as_raw_fd()), - interrupt: MaybeOwnedFd::Borrowed(theirs.as_raw_fd()), - interrupt_resample_evt: MaybeOwnedFd::Borrowed( - interrupt.get_resample_evt().as_raw_fd(), - ), + shm: MaybeOwnedFd::new_borrowed(&mem), + interrupt: MaybeOwnedFd::new_borrowed(&theirs), + interrupt_resample_evt: MaybeOwnedFd::new_borrowed(interrupt.get_resample_evt()), in_queue: queues.remove(0), out_queue: queues.remove(0), - vm_socket: MaybeOwnedFd::Borrowed(vm_socket.as_raw_fd()), + vm_socket: MaybeOwnedFd::new_borrowed(&vm_socket), use_transition_flags, - in_queue_evt: MaybeOwnedFd::Borrowed(queue_evts[0].as_raw_fd()), - out_queue_evt: MaybeOwnedFd::Borrowed(queue_evts[1].as_raw_fd()), - kill_evt: MaybeOwnedFd::Borrowed(kill_evt.as_raw_fd()), + in_queue_evt: MaybeOwnedFd::new_borrowed(&queue_evts[0]), + out_queue_evt: MaybeOwnedFd::new_borrowed(&queue_evts[1]), + kill_evt: MaybeOwnedFd::new_borrowed(&kill_evt), }) { error!("failed to send SingleFd: {}", e); return; diff --git a/msg_socket/src/msg_on_socket.rs b/msg_socket/src/msg_on_socket.rs index 731276a..4149098 100644 --- a/msg_socket/src/msg_on_socket.rs +++ b/msg_socket/src/msg_on_socket.rs @@ -18,6 +18,8 @@ use std::sync::Arc; use data_model::*; use slice::{slice_read_helper, slice_write_helper}; use sync::Mutex; +use sys_util::net::UnixSeqpacket; +use sys_util::SharedMemory; use sys_util::{Error as SysError, EventFd, GuestAddress}; #[derive(Debug, PartialEq)] @@ -289,6 +291,8 @@ rawfd_impl!(TcpListener); rawfd_impl!(UdpSocket); rawfd_impl!(UnixListener); rawfd_impl!(UnixDatagram); +rawfd_impl!(UnixSeqpacket); +rawfd_impl!(SharedMemory); // usize could be different sizes on different targets. We always use u64. impl MsgOnSocket for usize { diff --git a/src/wl.rs b/src/wl.rs index 419fb67..b35af8b 100644 --- a/src/wl.rs +++ b/src/wl.rs @@ -1,15 +1,10 @@ // SPDX-License-Identifier: BSD-3-Clause -use std::os::unix::prelude::*; - use devices::virtio::{InterruptProxy, InterruptProxyEvent, SingleFd, Worker}; use msg_socket::{MsgReceiver, MsgSocket}; use std::collections::BTreeMap; use std::fs::remove_file; -use sys_util::{ - net::{UnixSeqpacket, UnixSeqpacketListener}, - EventFd, GuestMemory, SharedMemory, -}; +use sys_util::{net::UnixSeqpacketListener, GuestMemory}; use vm_control::VmMemoryControlRequestSocket; #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] @@ -36,7 +31,7 @@ fn main() { loop { match msg_socket.recv() { Ok(SingleFd { - memfd, + shm, interrupt, interrupt_resample_evt, in_queue, @@ -47,8 +42,7 @@ fn main() { out_queue_evt, kill_evt, }) => { - let shm = unsafe { SharedMemory::from_raw_fd(memfd.as_raw_fd()) }; - std::mem::forget(memfd); + let shm = shm.owned(); let regions = arch_memory_regions(MemoryParams { size: shm.size(), @@ -57,27 +51,19 @@ fn main() { let mem = GuestMemory::with_memfd(®ions, shm).expect("GuestMemory::with_memfd failed"); - let interrupt: MsgSocket = MsgSocket::new(unsafe { - let sock = UnixSeqpacket::from_raw_fd(interrupt.as_raw_fd()); - std::mem::forget(interrupt); - sock - }); - let vm_socket: VmMemoryControlRequestSocket = MsgSocket::new(unsafe { - let sock = UnixSeqpacket::from_raw_fd(vm_socket.as_raw_fd()); - std::mem::forget(vm_socket); - sock - }); + let interrupt: MsgSocket = + MsgSocket::new(interrupt.owned()); + let vm_socket: VmMemoryControlRequestSocket = MsgSocket::new(vm_socket.owned()); let mut wayland_paths = BTreeMap::new(); wayland_paths.insert("".into(), "/run/user/1000/wayland-0".into()); let mut worker = Worker::new( mem, - Box::new(InterruptProxy::new(interrupt, unsafe { - let evt = EventFd::from_raw_fd(interrupt_resample_evt.as_raw_fd()); - std::mem::forget(interrupt_resample_evt); - evt - })), + Box::new(InterruptProxy::new( + interrupt, + interrupt_resample_evt.owned(), + )), in_queue, out_queue, wayland_paths, @@ -87,23 +73,8 @@ fn main() { ); worker.run( - vec![ - unsafe { - let evt = EventFd::from_raw_fd(in_queue_evt.as_raw_fd()); - std::mem::forget(in_queue_evt); - evt - }, - unsafe { - let evt = EventFd::from_raw_fd(out_queue_evt.as_raw_fd()); - std::mem::forget(out_queue_evt); - evt - }, - ], - unsafe { - let evt = EventFd::from_raw_fd(kill_evt.as_raw_fd()); - std::mem::forget(kill_evt); - evt - }, + vec![in_queue_evt.owned(), out_queue_evt.owned()], + kill_evt.owned(), ); } diff --git a/sys_util/src/net.rs b/sys_util/src/net.rs index 71ab3ee..a2de0c4 100644 --- a/sys_util/src/net.rs +++ b/sys_util/src/net.rs @@ -71,6 +71,7 @@ fn sockaddr_un>(path: P) -> io::Result<(libc::sockaddr_un, libc:: } /// A Unix `SOCK_SEQPACKET` socket point to given `path` +#[derive(Debug)] pub struct UnixSeqpacket { fd: RawFd, } diff --git a/sys_util/src/shm.rs b/sys_util/src/shm.rs index 04eca3e..5a7dee9 100644 --- a/sys_util/src/shm.rs +++ b/sys_util/src/shm.rs @@ -17,6 +17,7 @@ use syscall_defines::linux::LinuxSyscall::SYS_memfd_create; use crate::{errno, errno_result, Result}; /// A shared memory file descriptor and its size. +#[derive(Debug)] pub struct SharedMemory { fd: File, size: u64, diff --git a/vm_control/src/lib.rs b/vm_control/src/lib.rs index d4922ab..3d92c8b 100644 --- a/vm_control/src/lib.rs +++ b/vm_control/src/lib.rs @@ -26,14 +26,27 @@ use sys_util::{error, Error as SysError, EventFd, GuestAddress, MemoryMapping, M /// A data structure that either owns or borrows a file descriptor. #[derive(Debug)] -pub enum MaybeOwnedFd { +pub enum MaybeOwnedFd { /// Owned by this enum variant, and will be destructed automatically if not moved out. - Owned(File), + Owned(Owned), /// A file descriptor borrwed by this enum. Borrowed(RawFd), } -impl AsRawFd for MaybeOwnedFd { +impl MaybeOwnedFd { + pub fn new_borrowed(fd: &dyn AsRawFd) -> Self { + Self::Borrowed(fd.as_raw_fd()) + } + + pub fn owned(self) -> Owned { + match self { + Self::Owned(owned) => owned, + Self::Borrowed(_) => panic!("owned() called on a borrowed MaybeOwnedFd"), + } + } +} + +impl AsRawFd for MaybeOwnedFd { fn as_raw_fd(&self) -> RawFd { match self { MaybeOwnedFd::Owned(f) => f.as_raw_fd(), @@ -43,7 +56,7 @@ impl AsRawFd for MaybeOwnedFd { } // When sent, it could be owned or borrowed. On the receiver end, it always owned. -impl MsgOnSocket for MaybeOwnedFd { +impl MsgOnSocket for MaybeOwnedFd { fn uses_fd() -> bool { true } @@ -54,7 +67,7 @@ impl MsgOnSocket for MaybeOwnedFd { 1usize } unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> { - let (file, size) = File::read_from_buffer(buffer, fds)?; + let (file, size) = Owned::read_from_buffer(buffer, fds)?; Ok((MaybeOwnedFd::Owned(file), size)) } fn write_to_buffer(&self, _buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult { @@ -202,7 +215,7 @@ pub enum UsbControlCommand { addr: u8, vid: u16, pid: u16, - fd: Option, + fd: Option>, }, DetachDevice { port: u8, @@ -260,10 +273,10 @@ impl Display for UsbControlResult { pub enum VmMemoryRequest { /// Register shared memory represented by the given fd into guest address space. The response /// variant is `VmResponse::RegisterMemory`. - RegisterMemory(MaybeOwnedFd, usize), + RegisterMemory(MaybeOwnedFd, usize), /// Similiar to `VmMemoryRequest::RegisterMemory`, but doesn't allocate new address space. /// Useful for cases where the address space is already allocated (PCI regions). - RegisterFdAtPciBarOffset(Alloc, MaybeOwnedFd, usize, u64), + RegisterFdAtPciBarOffset(Alloc, MaybeOwnedFd, usize, u64), /// Unregister the given memory slot that was previously registereed with `RegisterMemory`. UnregisterMemory(u32), /// Allocate GPU buffer of a given size/format and register the memory into guest address space. @@ -275,7 +288,7 @@ pub enum VmMemoryRequest { }, /// Register mmaped memory into kvm's EPT. RegisterMmapMemory { - fd: MaybeOwnedFd, + fd: MaybeOwnedFd, size: usize, offset: u64, gpa: u64, @@ -369,7 +382,7 @@ pub enum VmMemoryResponse { /// The request to allocate and register GPU memory into guest address space was successfully /// done at page frame number `pfn` and memory slot number `slot` for buffer with `desc`. AllocateAndRegisterGpuMemory { - fd: MaybeOwnedFd, + fd: MaybeOwnedFd, pfn: u64, slot: u32, desc: GpuMemoryDesc, @@ -381,7 +394,7 @@ pub enum VmMemoryResponse { #[derive(MsgOnSocket, Debug)] pub enum VmIrqRequest { /// Allocate one gsi, and associate gsi to irqfd with register_irqfd() - AllocateOneMsi { irqfd: MaybeOwnedFd }, + AllocateOneMsi { irqfd: MaybeOwnedFd }, /// Add one msi route entry into kvm AddMsiRoute { gsi: u32, @@ -693,7 +706,7 @@ pub enum VmResponse { /// The request to allocate and register GPU memory into guest address space was successfully /// done at page frame number `pfn` and memory slot number `slot` for buffer with `desc`. AllocateAndRegisterGpuMemory { - fd: MaybeOwnedFd, + fd: MaybeOwnedFd, pfn: u64, slot: u32, desc: GpuMemoryDesc, -- cgit 1.4.1