1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io::BufRead;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::BufReader;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Cursor;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::fs::FileExt;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::AsRawFd;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
16*bb4ee6a4SAndroid Build Coastguard Worker
17*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
18*bb4ee6a4SAndroid Build Coastguard Worker
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::FileSystem;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::ZeroCopyReader;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::ZeroCopyWriter;
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::server::Mapper;
23*bb4ee6a4SAndroid Build Coastguard Worker use crate::server::Reader;
24*bb4ee6a4SAndroid Build Coastguard Worker use crate::server::Server;
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::server::Writer;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result;
29*bb4ee6a4SAndroid Build Coastguard Worker
30*bb4ee6a4SAndroid Build Coastguard Worker struct DevFuseReader {
31*bb4ee6a4SAndroid Build Coastguard Worker // File representing /dev/fuse for reading, with sufficient buffer to accommodate a FUSE read
32*bb4ee6a4SAndroid Build Coastguard Worker // transaction.
33*bb4ee6a4SAndroid Build Coastguard Worker reader: BufReader<File>,
34*bb4ee6a4SAndroid Build Coastguard Worker }
35*bb4ee6a4SAndroid Build Coastguard Worker
36*bb4ee6a4SAndroid Build Coastguard Worker impl DevFuseReader {
new(reader: BufReader<File>) -> Self37*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(reader: BufReader<File>) -> Self {
38*bb4ee6a4SAndroid Build Coastguard Worker DevFuseReader { reader }
39*bb4ee6a4SAndroid Build Coastguard Worker }
40*bb4ee6a4SAndroid Build Coastguard Worker
drain(&mut self)41*bb4ee6a4SAndroid Build Coastguard Worker fn drain(&mut self) {
42*bb4ee6a4SAndroid Build Coastguard Worker self.reader.consume(self.reader.buffer().len());
43*bb4ee6a4SAndroid Build Coastguard Worker }
44*bb4ee6a4SAndroid Build Coastguard Worker }
45*bb4ee6a4SAndroid Build Coastguard Worker
46*bb4ee6a4SAndroid Build Coastguard Worker impl Read for DevFuseReader {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>47*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
48*bb4ee6a4SAndroid Build Coastguard Worker self.reader.read(buf)
49*bb4ee6a4SAndroid Build Coastguard Worker }
50*bb4ee6a4SAndroid Build Coastguard Worker }
51*bb4ee6a4SAndroid Build Coastguard Worker
52*bb4ee6a4SAndroid Build Coastguard Worker impl Reader for DevFuseReader {}
53*bb4ee6a4SAndroid Build Coastguard Worker
54*bb4ee6a4SAndroid Build Coastguard Worker impl ZeroCopyReader for DevFuseReader {
read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>55*bb4ee6a4SAndroid Build Coastguard Worker fn read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize> {
56*bb4ee6a4SAndroid Build Coastguard Worker let buf = self.reader.fill_buf()?;
57*bb4ee6a4SAndroid Build Coastguard Worker let end = std::cmp::min(count, buf.len());
58*bb4ee6a4SAndroid Build Coastguard Worker let written = f.write_at(&buf[..end], off)?;
59*bb4ee6a4SAndroid Build Coastguard Worker self.reader.consume(written);
60*bb4ee6a4SAndroid Build Coastguard Worker Ok(written)
61*bb4ee6a4SAndroid Build Coastguard Worker }
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker
64*bb4ee6a4SAndroid Build Coastguard Worker struct DevFuseWriter {
65*bb4ee6a4SAndroid Build Coastguard Worker // File representing /dev/fuse for writing.
66*bb4ee6a4SAndroid Build Coastguard Worker dev_fuse: File,
67*bb4ee6a4SAndroid Build Coastguard Worker
68*bb4ee6a4SAndroid Build Coastguard Worker // An internal buffer to allow generating data and header out of order, such that they can be
69*bb4ee6a4SAndroid Build Coastguard Worker // flushed at once. This is wrapped by a cursor for tracking the current written position.
70*bb4ee6a4SAndroid Build Coastguard Worker write_buf: Cursor<Vec<u8>>,
71*bb4ee6a4SAndroid Build Coastguard Worker }
72*bb4ee6a4SAndroid Build Coastguard Worker
73*bb4ee6a4SAndroid Build Coastguard Worker impl DevFuseWriter {
new(dev_fuse: File, write_buf: Cursor<Vec<u8>>) -> Self74*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(dev_fuse: File, write_buf: Cursor<Vec<u8>>) -> Self {
75*bb4ee6a4SAndroid Build Coastguard Worker debug_assert_eq!(write_buf.position(), 0);
76*bb4ee6a4SAndroid Build Coastguard Worker
77*bb4ee6a4SAndroid Build Coastguard Worker DevFuseWriter {
78*bb4ee6a4SAndroid Build Coastguard Worker dev_fuse,
79*bb4ee6a4SAndroid Build Coastguard Worker write_buf,
80*bb4ee6a4SAndroid Build Coastguard Worker }
81*bb4ee6a4SAndroid Build Coastguard Worker }
82*bb4ee6a4SAndroid Build Coastguard Worker }
83*bb4ee6a4SAndroid Build Coastguard Worker
84*bb4ee6a4SAndroid Build Coastguard Worker impl Write for DevFuseWriter {
write(&mut self, buf: &[u8]) -> io::Result<usize>85*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
86*bb4ee6a4SAndroid Build Coastguard Worker self.write_buf.write(buf)
87*bb4ee6a4SAndroid Build Coastguard Worker }
88*bb4ee6a4SAndroid Build Coastguard Worker
flush(&mut self) -> io::Result<()>89*bb4ee6a4SAndroid Build Coastguard Worker fn flush(&mut self) -> io::Result<()> {
90*bb4ee6a4SAndroid Build Coastguard Worker self.dev_fuse.write_all(&self.write_buf.get_ref()[..])?;
91*bb4ee6a4SAndroid Build Coastguard Worker self.write_buf.set_position(0);
92*bb4ee6a4SAndroid Build Coastguard Worker self.write_buf.get_mut().clear();
93*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker }
96*bb4ee6a4SAndroid Build Coastguard Worker
97*bb4ee6a4SAndroid Build Coastguard Worker impl Writer for DevFuseWriter {
98*bb4ee6a4SAndroid Build Coastguard Worker type ClosureWriter = Self;
99*bb4ee6a4SAndroid Build Coastguard Worker
write_at<F>(&mut self, offset: usize, f: F) -> io::Result<usize> where F: Fn(&mut Self) -> io::Result<usize>,100*bb4ee6a4SAndroid Build Coastguard Worker fn write_at<F>(&mut self, offset: usize, f: F) -> io::Result<usize>
101*bb4ee6a4SAndroid Build Coastguard Worker where
102*bb4ee6a4SAndroid Build Coastguard Worker F: Fn(&mut Self) -> io::Result<usize>,
103*bb4ee6a4SAndroid Build Coastguard Worker {
104*bb4ee6a4SAndroid Build Coastguard Worker // Restore the cursor for idempotent.
105*bb4ee6a4SAndroid Build Coastguard Worker let original = self.write_buf.position();
106*bb4ee6a4SAndroid Build Coastguard Worker self.write_buf.set_position(offset as u64);
107*bb4ee6a4SAndroid Build Coastguard Worker let r = f(self);
108*bb4ee6a4SAndroid Build Coastguard Worker self.write_buf.set_position(original);
109*bb4ee6a4SAndroid Build Coastguard Worker r
110*bb4ee6a4SAndroid Build Coastguard Worker }
111*bb4ee6a4SAndroid Build Coastguard Worker
has_sufficient_buffer(&self, size: u32) -> bool112*bb4ee6a4SAndroid Build Coastguard Worker fn has_sufficient_buffer(&self, size: u32) -> bool {
113*bb4ee6a4SAndroid Build Coastguard Worker (self.write_buf.position() as usize + size as usize) < self.write_buf.get_ref().capacity()
114*bb4ee6a4SAndroid Build Coastguard Worker }
115*bb4ee6a4SAndroid Build Coastguard Worker }
116*bb4ee6a4SAndroid Build Coastguard Worker
117*bb4ee6a4SAndroid Build Coastguard Worker impl ZeroCopyWriter for DevFuseWriter {
write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>118*bb4ee6a4SAndroid Build Coastguard Worker fn write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize> {
119*bb4ee6a4SAndroid Build Coastguard Worker let pos = self.write_buf.position() as usize;
120*bb4ee6a4SAndroid Build Coastguard Worker let end = pos + count;
121*bb4ee6a4SAndroid Build Coastguard Worker let buf = self.write_buf.get_mut();
122*bb4ee6a4SAndroid Build Coastguard Worker
123*bb4ee6a4SAndroid Build Coastguard Worker let old_end = buf.len();
124*bb4ee6a4SAndroid Build Coastguard Worker buf.resize(end, 0);
125*bb4ee6a4SAndroid Build Coastguard Worker let read = f.read_at(&mut buf[pos..end], off)?;
126*bb4ee6a4SAndroid Build Coastguard Worker
127*bb4ee6a4SAndroid Build Coastguard Worker let new_end = pos + read;
128*bb4ee6a4SAndroid Build Coastguard Worker debug_assert!(new_end >= old_end);
129*bb4ee6a4SAndroid Build Coastguard Worker buf.truncate(new_end);
130*bb4ee6a4SAndroid Build Coastguard Worker self.write_buf.set_position(new_end as u64);
131*bb4ee6a4SAndroid Build Coastguard Worker Ok(read)
132*bb4ee6a4SAndroid Build Coastguard Worker }
133*bb4ee6a4SAndroid Build Coastguard Worker }
134*bb4ee6a4SAndroid Build Coastguard Worker
135*bb4ee6a4SAndroid Build Coastguard Worker struct DevFuseMapper;
136*bb4ee6a4SAndroid Build Coastguard Worker
137*bb4ee6a4SAndroid Build Coastguard Worker impl DevFuseMapper {
new() -> Self138*bb4ee6a4SAndroid Build Coastguard Worker fn new() -> Self {
139*bb4ee6a4SAndroid Build Coastguard Worker Self {}
140*bb4ee6a4SAndroid Build Coastguard Worker }
141*bb4ee6a4SAndroid Build Coastguard Worker }
142*bb4ee6a4SAndroid Build Coastguard Worker
143*bb4ee6a4SAndroid Build Coastguard Worker impl Mapper for DevFuseMapper {
map( &self, _mem_offset: u64, _size: usize, _fd: &dyn AsRawFd, _file_offset: u64, _prot: Protection, ) -> io::Result<()>144*bb4ee6a4SAndroid Build Coastguard Worker fn map(
145*bb4ee6a4SAndroid Build Coastguard Worker &self,
146*bb4ee6a4SAndroid Build Coastguard Worker _mem_offset: u64,
147*bb4ee6a4SAndroid Build Coastguard Worker _size: usize,
148*bb4ee6a4SAndroid Build Coastguard Worker _fd: &dyn AsRawFd,
149*bb4ee6a4SAndroid Build Coastguard Worker _file_offset: u64,
150*bb4ee6a4SAndroid Build Coastguard Worker _prot: Protection,
151*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<()> {
152*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker
unmap(&self, _offset: u64, _size: u64) -> io::Result<()>155*bb4ee6a4SAndroid Build Coastguard Worker fn unmap(&self, _offset: u64, _size: u64) -> io::Result<()> {
156*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::from_raw_os_error(libc::EOPNOTSUPP))
157*bb4ee6a4SAndroid Build Coastguard Worker }
158*bb4ee6a4SAndroid Build Coastguard Worker }
159*bb4ee6a4SAndroid Build Coastguard Worker
160*bb4ee6a4SAndroid Build Coastguard Worker /// Start the FUSE message handling loop. Returns when an error happens.
161*bb4ee6a4SAndroid Build Coastguard Worker ///
162*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
163*bb4ee6a4SAndroid Build Coastguard Worker ///
164*bb4ee6a4SAndroid Build Coastguard Worker /// * `dev_fuse` - A `File` object of /dev/fuse
165*bb4ee6a4SAndroid Build Coastguard Worker /// * `input_buffer_size` - Maximum bytes of the buffer when reads from /dev/fuse.
166*bb4ee6a4SAndroid Build Coastguard Worker /// * `output_buffer_size` - Maximum bytes of the buffer when writes to /dev/fuse. Must be large
167*bb4ee6a4SAndroid Build Coastguard Worker /// enough (usually equal) to `n` in `MountOption::MaxRead(n)`.
168*bb4ee6a4SAndroid Build Coastguard Worker ///
169*bb4ee6a4SAndroid Build Coastguard Worker /// [deprecated(note="Please migrate to the `FuseConfig` builder API"]
start_message_loop<F: FileSystem + Sync>( dev_fuse: File, input_buffer_size: u32, output_buffer_size: u32, fs: F, ) -> Result<()>170*bb4ee6a4SAndroid Build Coastguard Worker pub fn start_message_loop<F: FileSystem + Sync>(
171*bb4ee6a4SAndroid Build Coastguard Worker dev_fuse: File,
172*bb4ee6a4SAndroid Build Coastguard Worker input_buffer_size: u32,
173*bb4ee6a4SAndroid Build Coastguard Worker output_buffer_size: u32,
174*bb4ee6a4SAndroid Build Coastguard Worker fs: F,
175*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
176*bb4ee6a4SAndroid Build Coastguard Worker let server = Server::new(fs);
177*bb4ee6a4SAndroid Build Coastguard Worker do_start_message_loop(dev_fuse, input_buffer_size, output_buffer_size, &server)
178*bb4ee6a4SAndroid Build Coastguard Worker }
179*bb4ee6a4SAndroid Build Coastguard Worker
do_start_message_loop<F: FileSystem + Sync>( dev_fuse: File, input_buffer_size: u32, output_buffer_size: u32, server: &Server<F>, ) -> Result<()>180*bb4ee6a4SAndroid Build Coastguard Worker fn do_start_message_loop<F: FileSystem + Sync>(
181*bb4ee6a4SAndroid Build Coastguard Worker dev_fuse: File,
182*bb4ee6a4SAndroid Build Coastguard Worker input_buffer_size: u32,
183*bb4ee6a4SAndroid Build Coastguard Worker output_buffer_size: u32,
184*bb4ee6a4SAndroid Build Coastguard Worker server: &Server<F>,
185*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
186*bb4ee6a4SAndroid Build Coastguard Worker let mut dev_fuse_reader = {
187*bb4ee6a4SAndroid Build Coastguard Worker let rfile = dev_fuse.try_clone().map_err(Error::EndpointSetup)?;
188*bb4ee6a4SAndroid Build Coastguard Worker let buf_reader = BufReader::with_capacity(
189*bb4ee6a4SAndroid Build Coastguard Worker input_buffer_size as usize + size_of::<sys::InHeader>() + size_of::<sys::WriteIn>(),
190*bb4ee6a4SAndroid Build Coastguard Worker rfile,
191*bb4ee6a4SAndroid Build Coastguard Worker );
192*bb4ee6a4SAndroid Build Coastguard Worker DevFuseReader::new(buf_reader)
193*bb4ee6a4SAndroid Build Coastguard Worker };
194*bb4ee6a4SAndroid Build Coastguard Worker let mut dev_fuse_writer = {
195*bb4ee6a4SAndroid Build Coastguard Worker let wfile = dev_fuse;
196*bb4ee6a4SAndroid Build Coastguard Worker let write_buf = Cursor::new(Vec::with_capacity(output_buffer_size as usize));
197*bb4ee6a4SAndroid Build Coastguard Worker DevFuseWriter::new(wfile, write_buf)
198*bb4ee6a4SAndroid Build Coastguard Worker };
199*bb4ee6a4SAndroid Build Coastguard Worker let dev_fuse_mapper = DevFuseMapper::new();
200*bb4ee6a4SAndroid Build Coastguard Worker loop {
201*bb4ee6a4SAndroid Build Coastguard Worker server.handle_message(&mut dev_fuse_reader, &mut dev_fuse_writer, &dev_fuse_mapper)?;
202*bb4ee6a4SAndroid Build Coastguard Worker
203*bb4ee6a4SAndroid Build Coastguard Worker // Since we're reusing the buffer to avoid repeated allocation, drain the possible
204*bb4ee6a4SAndroid Build Coastguard Worker // residual from the buffer.
205*bb4ee6a4SAndroid Build Coastguard Worker dev_fuse_reader.drain();
206*bb4ee6a4SAndroid Build Coastguard Worker }
207*bb4ee6a4SAndroid Build Coastguard Worker }
208*bb4ee6a4SAndroid Build Coastguard Worker
209*bb4ee6a4SAndroid Build Coastguard Worker // TODO: Remove worker and this namespace from public
210*bb4ee6a4SAndroid Build Coastguard Worker pub mod internal {
211*bb4ee6a4SAndroid Build Coastguard Worker use crossbeam_utils::thread;
212*bb4ee6a4SAndroid Build Coastguard Worker
213*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
214*bb4ee6a4SAndroid Build Coastguard Worker
215*bb4ee6a4SAndroid Build Coastguard Worker /// Start the FUSE message handling loops in multiple threads. Returns when an error happens.
216*bb4ee6a4SAndroid Build Coastguard Worker ///
217*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
218*bb4ee6a4SAndroid Build Coastguard Worker ///
219*bb4ee6a4SAndroid Build Coastguard Worker /// * `dev_fuse` - A `File` object of /dev/fuse
220*bb4ee6a4SAndroid Build Coastguard Worker /// * `input_buffer_size` - Maximum bytes of the buffer when reads from /dev/fuse.
221*bb4ee6a4SAndroid Build Coastguard Worker /// * `output_buffer_size` - Maximum bytes of the buffer when writes to /dev/fuse.
222*bb4ee6a4SAndroid Build Coastguard Worker ///
223*bb4ee6a4SAndroid Build Coastguard Worker /// [deprecated(note="Please migrate to the `FuseConfig` builder API"]
start_message_loop_mt<F: FileSystem + Sync + Send>( dev_fuse: File, input_buffer_size: u32, output_buffer_size: u32, thread_numbers: usize, fs: F, ) -> Result<()>224*bb4ee6a4SAndroid Build Coastguard Worker pub fn start_message_loop_mt<F: FileSystem + Sync + Send>(
225*bb4ee6a4SAndroid Build Coastguard Worker dev_fuse: File,
226*bb4ee6a4SAndroid Build Coastguard Worker input_buffer_size: u32,
227*bb4ee6a4SAndroid Build Coastguard Worker output_buffer_size: u32,
228*bb4ee6a4SAndroid Build Coastguard Worker thread_numbers: usize,
229*bb4ee6a4SAndroid Build Coastguard Worker fs: F,
230*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
231*bb4ee6a4SAndroid Build Coastguard Worker let result = thread::scope(|s| {
232*bb4ee6a4SAndroid Build Coastguard Worker let server = Arc::new(Server::new(fs));
233*bb4ee6a4SAndroid Build Coastguard Worker for _ in 0..thread_numbers {
234*bb4ee6a4SAndroid Build Coastguard Worker let dev_fuse = dev_fuse
235*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
236*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::EndpointSetup)
237*bb4ee6a4SAndroid Build Coastguard Worker .expect("Failed to clone /dev/fuse FD");
238*bb4ee6a4SAndroid Build Coastguard Worker let server = server.clone();
239*bb4ee6a4SAndroid Build Coastguard Worker s.spawn(move |_| {
240*bb4ee6a4SAndroid Build Coastguard Worker do_start_message_loop(dev_fuse, input_buffer_size, output_buffer_size, &server)
241*bb4ee6a4SAndroid Build Coastguard Worker });
242*bb4ee6a4SAndroid Build Coastguard Worker }
243*bb4ee6a4SAndroid Build Coastguard Worker });
244*bb4ee6a4SAndroid Build Coastguard Worker
245*bb4ee6a4SAndroid Build Coastguard Worker unreachable!("Threads exited or crashed unexpectedly: {:?}", result);
246*bb4ee6a4SAndroid Build Coastguard Worker }
247*bb4ee6a4SAndroid Build Coastguard Worker }
248