From 392b73cdbc3c862cf4ffaa0cace19d22077c5648 Mon Sep 17 00:00:00 2001 From: Keiichi Watanabe Date: Wed, 22 Jan 2020 19:35:02 +0900 Subject: devices: virtio: Add a function to get a FD via resource_bridge Add a function to get a resource FD via resource_bridge by extracting code from the wayland device implementation. This function will be used by virtio-video devices. BUG=b:147465619 TEST=Run ARCVM and check that a window is displayed Change-Id: I7b064c9a04bd082e30dd488d0b14731228e6047d Signed-off-by: Keiichi Watanabe Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2014520 Tested-by: kokoro Reviewed-by: Chirantan Ekbote --- devices/src/virtio/resource_bridge.rs | 50 ++++++++++++++++++++++++++++++++--- devices/src/virtio/wl.rs | 20 +++++--------- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/devices/src/virtio/resource_bridge.rs b/devices/src/virtio/resource_bridge.rs index d3a3375..aaf776c 100644 --- a/devices/src/virtio/resource_bridge.rs +++ b/devices/src/virtio/resource_bridge.rs @@ -5,11 +5,11 @@ //! This module defines the protocol between `virtio-wayland` and `virtio-gpu` for sharing resources //! that are backed by file descriptors. +use std::fmt; use std::fs::File; -use std::io::Result; use msg_on_socket_derive::MsgOnSocket; -use msg_socket::MsgSocket; +use msg_socket::{MsgError, MsgReceiver, MsgSender, MsgSocket}; #[derive(MsgOnSocket)] pub enum ResourceRequest { @@ -25,6 +25,50 @@ pub enum ResourceResponse { pub type ResourceRequestSocket = MsgSocket; pub type ResourceResponseSocket = MsgSocket; -pub fn pair() -> Result<(ResourceRequestSocket, ResourceResponseSocket)> { +pub fn pair() -> std::io::Result<(ResourceRequestSocket, ResourceResponseSocket)> { msg_socket::pair() } + +#[derive(Debug)] +pub enum ResourceBridgeError { + InvalidResource(u32), + SendFailure(u32, MsgError), + RecieveFailure(u32, MsgError), +} + +impl fmt::Display for ResourceBridgeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ResourceBridgeError::InvalidResource(id) => { + write!(f, "attempt to send non-existent gpu resource for id {}", id) + } + ResourceBridgeError::SendFailure(id, e) => write!( + f, + "failed to send a resource bridge request for id {}: {}", + id, e + ), + ResourceBridgeError::RecieveFailure(id, e) => write!( + f, + "error receiving resource bridge response for id {}: {}", + id, e + ), + } + } +} + +impl std::error::Error for ResourceBridgeError {} + +pub fn get_resource_fd( + sock: &ResourceRequestSocket, + id: u32, +) -> std::result::Result { + if let Err(e) = sock.send(&ResourceRequest::GetResource { id }) { + return Err(ResourceBridgeError::SendFailure(id, e)); + } + + match sock.recv() { + Ok(ResourceResponse::Resource(bridged_file)) => Ok(bridged_file), + Ok(ResourceResponse::Invalid) => Err(ResourceBridgeError::InvalidResource(id)), + Err(e) => Err(ResourceBridgeError::RecieveFailure(id, e)), + } +} diff --git a/devices/src/virtio/wl.rs b/devices/src/virtio/wl.rs index 5bbd914..5ace29c 100644 --- a/devices/src/virtio/wl.rs +++ b/devices/src/virtio/wl.rs @@ -1092,26 +1092,18 @@ impl WlState { }, #[cfg(feature = "gpu")] VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU if self.resource_bridge.is_some() => { - if let Err(e) = self - .resource_bridge - .as_ref() - .unwrap() - .send(&ResourceRequest::GetResource { id }) - { - error!("error sending resource bridge request: {}", e); - return Ok(WlResp::InvalidId); - } - match self.resource_bridge.as_ref().unwrap().recv() { - Ok(ResourceResponse::Resource(bridged_file)) => { + let sock = self.resource_bridge.as_ref().unwrap(); + match get_resource_fd(sock, id) { + Ok(bridged_file) => { *fd = bridged_file.as_raw_fd(); bridged_files.push(bridged_file); } - Ok(ResourceResponse::Invalid) => { - warn!("attempt to send non-existant gpu resource {}", id); + Err(ResourceBridgeError::InvalidResource(id)) => { + warn!("attempt to send non-existent gpu resource {}", id); return Ok(WlResp::InvalidId); } Err(e) => { - error!("error receiving resource bridge response: {}", e); + error!("{}", e); // If there was an error with the resource bridge, it can no longer be // trusted to continue to function. self.resource_bridge = None; -- cgit 1.4.1