fuse_backend_rs/api/server/
mod.rs1use std::ffi::CStr;
20use std::io::{self, Read};
21use std::marker::PhantomData;
22use std::mem::size_of;
23use std::sync::Arc;
24
25use arc_swap::ArcSwap;
26
27use crate::abi::fuse_abi::*;
28use crate::api::filesystem::{Context, FileSystem, ZeroCopyReader, ZeroCopyWriter};
29use crate::file_traits::FileReadWriteVolatile;
30use crate::transport::{Reader, Writer};
31use crate::{bytes_to_cstr, BitmapSlice, Error, Result};
32
33#[cfg(feature = "async-io")]
34mod async_io;
35mod sync_io;
36
37#[cfg(target_os = "linux")]
39pub const MAX_BUFFER_SIZE: u32 = 1 << 20;
40#[cfg(target_os = "macos")]
42pub const MAX_BUFFER_SIZE: u32 = 1 << 25;
43const MIN_READ_BUFFER: u32 = 8192;
44const BUFFER_HEADER_SIZE: u32 = 0x1000;
45const DIRENT_PADDING: [u8; 8] = [0; 8];
46
47pub const MAX_REQ_PAGES: u16 = 256; pub struct Server<F: FileSystem + Sync> {
52 fs: F,
53 vers: ArcSwap<ServerVersion>,
54}
55
56impl<F: FileSystem + Sync> Server<F> {
57 pub fn new(fs: F) -> Server<F> {
59 Server {
60 fs,
61 vers: ArcSwap::new(Arc::new(ServerVersion {
62 major: KERNEL_VERSION,
63 minor: KERNEL_MINOR_VERSION,
64 })),
65 }
66 }
67}
68
69struct ZcReader<'a, S: BitmapSlice = ()>(Reader<'a, S>);
70
71impl<'a, S: BitmapSlice> ZeroCopyReader for ZcReader<'a, S> {
72 fn read_to(
73 &mut self,
74 f: &mut dyn FileReadWriteVolatile,
75 count: usize,
76 off: u64,
77 ) -> io::Result<usize> {
78 self.0.read_to_at(f, count, off)
79 }
80}
81
82impl<'a, S: BitmapSlice> io::Read for ZcReader<'a, S> {
83 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
84 self.0.read(buf)
85 }
86}
87
88struct ZcWriter<'a, S: BitmapSlice = ()>(Writer<'a, S>);
89
90impl<'a, S: BitmapSlice> ZeroCopyWriter for ZcWriter<'a, S> {
91 fn write_from(
92 &mut self,
93 f: &mut dyn FileReadWriteVolatile,
94 count: usize,
95 off: u64,
96 ) -> io::Result<usize> {
97 self.0.write_from_at(f, count, off)
98 }
99
100 fn available_bytes(&self) -> usize {
101 self.0.available_bytes()
102 }
103}
104
105impl<'a, S: BitmapSlice> io::Write for ZcWriter<'a, S> {
106 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
107 self.0.write(buf)
108 }
109
110 fn flush(&mut self) -> io::Result<()> {
111 self.0.flush()
112 }
113}
114
115#[allow(dead_code)]
116struct ServerVersion {
117 major: u32,
118 minor: u32,
119}
120
121struct ServerUtil();
122
123impl ServerUtil {
124 fn get_message_body<S: BitmapSlice>(
125 r: &mut Reader<'_, S>,
126 in_header: &InHeader,
127 sub_hdr_sz: usize,
128 ) -> Result<Vec<u8>> {
129 let len = (in_header.len as usize)
130 .checked_sub(size_of::<InHeader>())
131 .and_then(|l| l.checked_sub(sub_hdr_sz))
132 .ok_or(Error::InvalidHeaderLength)?;
133
134 let mut buf = Vec::<u8>::with_capacity(len);
136 #[allow(clippy::uninit_vec)]
138 unsafe {
139 buf.set_len(len)
140 };
141 r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
142
143 Ok(buf)
144 }
145
146 fn extract_two_cstrs(buf: &[u8]) -> Result<(&CStr, &CStr)> {
147 if let Some(mut pos) = buf.iter().position(|x| *x == 0) {
148 let first = CStr::from_bytes_with_nul(&buf[0..=pos]).map_err(Error::InvalidCString)?;
149 pos += 1;
150 if pos < buf.len() {
151 return Ok((first, bytes_to_cstr(&buf[pos..])?));
152 }
153 }
154
155 Err(Error::DecodeMessage(std::io::Error::from_raw_os_error(
156 libc::EINVAL,
157 )))
158 }
159}
160
161pub trait MetricsHook {
163 fn collect(&self, ih: &InHeader);
165 fn release(&self, oh: Option<&OutHeader>);
167}
168
169struct SrvContext<'a, F, S: BitmapSlice = ()> {
170 in_header: InHeader,
171 context: Context,
172 r: Reader<'a, S>,
173 w: Writer<'a, S>,
174 phantom: PhantomData<F>,
175 phantom2: PhantomData<S>,
176}
177
178impl<'a, F: FileSystem, S: BitmapSlice> SrvContext<'a, F, S> {
179 fn new(in_header: InHeader, r: Reader<'a, S>, w: Writer<'a, S>) -> Self {
180 let context = Context::from(&in_header);
181
182 SrvContext {
183 in_header,
184 context,
185 r,
186 w,
187 phantom: PhantomData,
188 phantom2: PhantomData,
189 }
190 }
191
192 fn context(&self) -> &Context {
193 &self.context
194 }
195
196 fn unique(&self) -> u64 {
197 self.in_header.unique
198 }
199
200 fn nodeid(&self) -> F::Inode {
201 self.in_header.nodeid.into()
202 }
203
204 fn take_reader(&mut self) -> Reader<'a, S> {
205 let mut reader = Reader::default();
206
207 std::mem::swap(&mut self.r, &mut reader);
208
209 reader
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn test_extract_cstrs() {
219 assert_eq!(
220 ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8, 0x0, 0x3, 0x0]).unwrap(),
221 (
222 CStr::from_bytes_with_nul(&[0x1u8, 0x2u8, 0x0]).unwrap(),
223 CStr::from_bytes_with_nul(&[0x3u8, 0x0]).unwrap(),
224 )
225 );
226 assert_eq!(
227 ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8, 0x0, 0x3, 0x0, 0x0]).unwrap(),
228 (
229 CStr::from_bytes_with_nul(&[0x1u8, 0x2u8, 0x0]).unwrap(),
230 CStr::from_bytes_with_nul(&[0x3u8, 0x0]).unwrap(),
231 )
232 );
233 assert_eq!(
234 ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8, 0x0, 0x3, 0x0, 0x4]).unwrap(),
235 (
236 CStr::from_bytes_with_nul(&[0x1u8, 0x2u8, 0x0]).unwrap(),
237 CStr::from_bytes_with_nul(&[0x3u8, 0x0]).unwrap(),
238 )
239 );
240 assert_eq!(
241 ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8, 0x0, 0x0, 0x4]).unwrap(),
242 (
243 CStr::from_bytes_with_nul(&[0x1u8, 0x2u8, 0x0]).unwrap(),
244 CStr::from_bytes_with_nul(&[0x0]).unwrap(),
245 )
246 );
247
248 ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8, 0x0, 0x3]).unwrap_err();
249 ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8, 0x0]).unwrap_err();
250 ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8]).unwrap_err();
251 }
252}