• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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