summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-03-08 22:41:30 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 09:36:14 +0000
commit2507cc57bc0145eb57305e60f6a7c21f3b4c9192 (patch)
treea6b700b920b6b2733ae8049302c613d3eb93a330
parent3d1bc2e0bb5bae7f32a9fa18b5348295facd5ab6 (diff)
downloadcrosvm-2507cc57bc0145eb57305e60f6a7c21f3b4c9192.tar
crosvm-2507cc57bc0145eb57305e60f6a7c21f3b4c9192.tar.gz
crosvm-2507cc57bc0145eb57305e60f6a7c21f3b4c9192.tar.bz2
crosvm-2507cc57bc0145eb57305e60f6a7c21f3b4c9192.tar.lz
crosvm-2507cc57bc0145eb57305e60f6a7c21f3b4c9192.tar.xz
crosvm-2507cc57bc0145eb57305e60f6a7c21f3b4c9192.tar.zst
crosvm-2507cc57bc0145eb57305e60f6a7c21f3b4c9192.zip
vm_control: make MaybeOwnedFd generic
This will allow more easily sending types other than File over
sockets, (e.g., UnixSeqpacket).
-rw-r--r--devices/src/usb/host_backend/host_backend_device_provider.rs7
-rw-r--r--devices/src/virtio/wl.rs30
-rw-r--r--msg_socket/src/msg_on_socket.rs4
-rw-r--r--src/wl.rs53
-rw-r--r--sys_util/src/net.rs1
-rw-r--r--sys_util/src/shm.rs1
-rw-r--r--vm_control/src/lib.rs37
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<MaybeOwnedFd>) -> UsbControlResult {
+    fn handle_attach_device(&self, fd: Option<MaybeOwnedFd<File>>) -> 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::<File>::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::<File>::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<SharedMemory>,
+    pub interrupt: MaybeOwnedFd<UnixSeqpacket>,
+    pub interrupt_resample_evt: MaybeOwnedFd<EventFd>,
     pub in_queue: Queue,
     pub out_queue: Queue,
-    pub vm_socket: MaybeOwnedFd,
+    pub vm_socket: MaybeOwnedFd<UnixSeqpacket>,
     pub use_transition_flags: bool,
-    pub in_queue_evt: MaybeOwnedFd,
-    pub out_queue_evt: MaybeOwnedFd,
-    pub kill_evt: MaybeOwnedFd,
+    pub in_queue_evt: MaybeOwnedFd<EventFd>,
+    pub out_queue_evt: MaybeOwnedFd<EventFd>,
+    pub kill_evt: MaybeOwnedFd<EventFd>,
 }
 
 type Socket = MsgSocket<SingleFd, ()>;
@@ -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(&regions, shm).expect("GuestMemory::with_memfd failed");
 
-                let interrupt: MsgSocket<InterruptProxyEvent, ()> = 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<InterruptProxyEvent, ()> =
+                    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<P: AsRef<Path>>(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> {
     /// 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<Owned> MaybeOwnedFd<Owned> {
+    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<Owned: AsRawFd> AsRawFd for MaybeOwnedFd<Owned> {
     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<Owned: AsRawFd + FromRawFd + MsgOnSocket> MsgOnSocket for MaybeOwnedFd<Owned> {
     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<usize> {
@@ -202,7 +215,7 @@ pub enum UsbControlCommand {
         addr: u8,
         vid: u16,
         pid: u16,
-        fd: Option<MaybeOwnedFd>,
+        fd: Option<MaybeOwnedFd<File>>,
     },
     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<File>, 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<File>, 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<File>,
         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<File>,
         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<File> },
     /// 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<File>,
         pfn: u64,
         slot: u32,
         desc: GpuMemoryDesc,