1 // Copyright 2022 The Chromium OS Authors. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 //! Windows specific code that keeps rest of the code in the crate platform independent. 5 6 use std::sync::Arc; 7 8 use base::AsRawDescriptor; 9 use base::CloseNotifier; 10 use base::ReadNotifier; 11 use tube_transporter::packed_tube; 12 13 use crate::master_req_handler::MasterReqHandler; 14 use crate::Result; 15 use crate::VhostUserMasterReqHandler; 16 17 impl<S: VhostUserMasterReqHandler> MasterReqHandler<S> { 18 /// Create a `MasterReqHandler` that uses a Tube internally. Must specify the backend process 19 /// which will receive the Tube. with_tube(backend: Arc<S>, backend_pid: u32) -> Result<Self>20 pub fn with_tube(backend: Arc<S>, backend_pid: u32) -> Result<Self> { 21 Self::new( 22 backend, 23 Box::new(move |tube| unsafe { 24 // Safe because we expect the tube to be unpacked in the other process. 25 packed_tube::pack(tube, backend_pid).expect("packed tube") 26 }), 27 ) 28 } 29 } 30 31 impl<S: VhostUserMasterReqHandler> ReadNotifier for MasterReqHandler<S> { 32 /// Used for polling. get_read_notifier(&self) -> &dyn AsRawDescriptor33 fn get_read_notifier(&self) -> &dyn AsRawDescriptor { 34 self.sub_sock.get_tube().get_read_notifier() 35 } 36 } 37 38 impl<S: VhostUserMasterReqHandler> CloseNotifier for MasterReqHandler<S> { 39 /// Used for closing. get_close_notifier(&self) -> &dyn AsRawDescriptor40 fn get_close_notifier(&self) -> &dyn AsRawDescriptor { 41 self.sub_sock.get_tube().get_close_notifier() 42 } 43 } 44 45 #[cfg(test)] 46 mod tests { 47 use std::sync::Mutex; 48 49 use base::AsRawDescriptor; 50 use base::Descriptor; 51 use base::INVALID_DESCRIPTOR; 52 53 use super::*; 54 use crate::message::VhostUserFSSlaveMsg; 55 use crate::HandlerResult; 56 #[cfg(feature = "device")] 57 use crate::Slave; 58 use crate::VhostUserMasterReqHandlerMut; 59 60 struct MockMasterReqHandler {} 61 62 impl VhostUserMasterReqHandlerMut for MockMasterReqHandler { 63 /// Handle virtio-fs map file requests from the slave. fs_slave_map( &mut self, _fs: &VhostUserFSSlaveMsg, _fd: &dyn AsRawDescriptor, ) -> HandlerResult<u64>64 fn fs_slave_map( 65 &mut self, 66 _fs: &VhostUserFSSlaveMsg, 67 _fd: &dyn AsRawDescriptor, 68 ) -> HandlerResult<u64> { 69 Ok(0) 70 } 71 72 /// Handle virtio-fs unmap file requests from the slave. fs_slave_unmap(&mut self, _fs: &VhostUserFSSlaveMsg) -> HandlerResult<u64>73 fn fs_slave_unmap(&mut self, _fs: &VhostUserFSSlaveMsg) -> HandlerResult<u64> { 74 Err(std::io::Error::from_raw_os_error(libc::ENOSYS)) 75 } 76 } 77 78 #[test] test_new_master_req_handler()79 fn test_new_master_req_handler() { 80 let backend = Arc::new(Mutex::new(MockMasterReqHandler {})); 81 let handler = MasterReqHandler::with_tube(backend, std::process::id()).unwrap(); 82 83 assert!(handler.get_read_notifier().as_raw_descriptor() != INVALID_DESCRIPTOR); 84 assert!(handler.get_close_notifier().as_raw_descriptor() != INVALID_DESCRIPTOR); 85 } 86 87 #[cfg(feature = "device")] 88 #[test] test_master_slave_req_handler()89 fn test_master_slave_req_handler() { 90 let backend = Arc::new(Mutex::new(MockMasterReqHandler {})); 91 let mut handler = MasterReqHandler::with_tube(backend, std::process::id()).unwrap(); 92 93 let event = base::Event::new().unwrap(); 94 let tx_descriptor = handler.take_tx_descriptor(); 95 // Safe because we only do it once. 96 let stream = unsafe { packed_tube::unpack(tx_descriptor).unwrap() }; 97 let fs_cache = Slave::from_stream(stream); 98 99 std::thread::spawn(move || { 100 let res = handler.handle_request().unwrap(); 101 assert_eq!(res, 0); 102 handler.handle_request().unwrap_err(); 103 }); 104 105 fs_cache 106 .fs_slave_map( 107 &VhostUserFSSlaveMsg::default(), 108 &Descriptor(event.as_raw_descriptor()), 109 ) 110 .unwrap(); 111 // When REPLY_ACK has not been negotiated, the master has no way to detect failure from 112 // slave side. 113 fs_cache 114 .fs_slave_unmap(&VhostUserFSSlaveMsg::default()) 115 .unwrap(); 116 } 117 118 #[cfg(feature = "device")] 119 #[test] test_master_slave_req_handler_with_ack()120 fn test_master_slave_req_handler_with_ack() { 121 let backend = Arc::new(Mutex::new(MockMasterReqHandler {})); 122 let mut handler = MasterReqHandler::with_tube(backend, std::process::id()).unwrap(); 123 handler.set_reply_ack_flag(true); 124 125 let event = base::Event::new().unwrap(); 126 let tx_descriptor = handler.take_tx_descriptor(); 127 // Safe because we only do it once. 128 let stream = unsafe { packed_tube::unpack(tx_descriptor).unwrap() }; 129 let fs_cache = Slave::from_stream(stream); 130 131 std::thread::spawn(move || { 132 let res = handler.handle_request().unwrap(); 133 assert_eq!(res, 0); 134 handler.handle_request().unwrap_err(); 135 }); 136 137 fs_cache.set_reply_ack_flag(true); 138 fs_cache 139 .fs_slave_map( 140 &VhostUserFSSlaveMsg::default(), 141 &Descriptor(event.as_raw_descriptor()), 142 ) 143 .unwrap(); 144 fs_cache 145 .fs_slave_unmap(&VhostUserFSSlaveMsg::default()) 146 .unwrap_err(); 147 } 148 } 149