1#![allow(unused_variables, unused_mut, clippy::too_many_arguments)]
5
6use std::ffi::OsStr;
7use std::path::Path;
8use std::time::SystemTime;
9
10use log::{debug, warn};
11use tokio::io;
12
13use crate::{
14 AccessFlags, BsdFileFlags, Config, CopyFileRangeFlags, Errno, FileHandle, INodeNo,
15 KernelConfig, LockOwner, OpenFlags, RenameFlags, Request, TimeOrNow, WriteFlags,
16 reply_async::{
17 AttrResponse, CreateResponse, DataResponse, DirectoryResponse, EntryResponse,
18 GetAttrResponse, LookupResponse, OpenResponse, ReadResponse, StatfsResponse, WriteResponse,
19 XattrResponse,
20 },
21 session_async::AsyncSessionBuilder,
22};
23
24#[async_trait::async_trait]
42pub trait AsyncFilesystem: Send + Sync + 'static {
43 async fn init(&mut self, _req: &Request, _config: &mut KernelConfig) -> io::Result<()> {
46 Ok(())
47 }
48
49 fn destroy(&mut self) {}
52
53 async fn lookup(
56 &self,
57 context: &Request,
58 parent: INodeNo,
59 name: &OsStr,
60 ) -> Result<LookupResponse, Errno> {
61 warn!(
62 "lookup not implemented for parent inode {}, name {:?}",
63 parent, name
64 );
65 Err(Errno::ENOTSUP)
66 }
67
68 async fn getattr(
71 &self,
72 context: &Request,
73 ino: INodeNo,
74 file_handle: Option<FileHandle>,
75 ) -> Result<GetAttrResponse, Errno> {
76 warn!("getattr not implemented for inode {}", ino);
77 Err(Errno::ENOTSUP)
78 }
79
80 async fn forget(&self, req: &Request, ino: INodeNo, nlookup: u64) {
83 debug!("forget not implemented for inode {}", ino);
84 }
85
86 async fn setattr(
88 &self,
89 req: &Request,
90 ino: INodeNo,
91 mode: Option<u32>,
92 uid: Option<u32>,
93 gid: Option<u32>,
94 size: Option<u64>,
95 atime: Option<TimeOrNow>,
96 mtime: Option<TimeOrNow>,
97 ctime: Option<SystemTime>,
98 fh: Option<FileHandle>,
99 crtime: Option<SystemTime>,
100 chgtime: Option<SystemTime>,
101 bkuptime: Option<SystemTime>,
102 flags: Option<BsdFileFlags>,
103 ) -> Result<AttrResponse, Errno> {
104 warn!(
105 "setattr not implemented for inode {}, mode {:?}, uid {:?}, gid {:?}, size {:?}, fh {:?}, flags {:?}",
106 ino, mode, uid, gid, size, fh, flags
107 );
108 Err(Errno::ENOTSUP)
109 }
110
111 async fn readlink(&self, req: &Request, ino: INodeNo) -> Result<DataResponse, Errno> {
113 warn!("readlink not implemented for inode {}", ino);
114 Err(Errno::ENOTSUP)
115 }
116
117 async fn mknod(
119 &self,
120 req: &Request,
121 parent: INodeNo,
122 name: &OsStr,
123 mode: u32,
124 umask: u32,
125 rdev: u32,
126 ) -> Result<EntryResponse, Errno> {
127 warn!(
128 "mknod not implemented for parent inode {}, name {:?}, mode {}, umask {}, rdev {}",
129 parent, name, mode, umask, rdev
130 );
131 Err(Errno::ENOTSUP)
132 }
133
134 async fn mkdir(
136 &self,
137 req: &Request,
138 parent: INodeNo,
139 name: &OsStr,
140 mode: u32,
141 umask: u32,
142 ) -> Result<EntryResponse, Errno> {
143 warn!(
144 "mkdir not implemented for parent inode {}, name {:?}, mode {}, umask {}",
145 parent, name, mode, umask
146 );
147 Err(Errno::ENOTSUP)
148 }
149
150 async fn unlink(&self, req: &Request, parent: INodeNo, name: &OsStr) -> Result<(), Errno> {
152 warn!(
153 "unlink not implemented for parent inode {}, name {:?}",
154 parent, name
155 );
156 Err(Errno::ENOTSUP)
157 }
158
159 async fn rmdir(&self, req: &Request, parent: INodeNo, name: &OsStr) -> Result<(), Errno> {
161 warn!(
162 "rmdir not implemented for parent inode {}, name {:?}",
163 parent, name
164 );
165 Err(Errno::ENOTSUP)
166 }
167
168 async fn symlink(
170 &self,
171 req: &Request,
172 parent: INodeNo,
173 link_name: &OsStr,
174 target: &Path,
175 ) -> Result<EntryResponse, Errno> {
176 warn!(
177 "symlink not implemented for parent inode {}, link_name {:?}, target {:?}",
178 parent, link_name, target
179 );
180 Err(Errno::ENOTSUP)
181 }
182
183 async fn rename(
185 &self,
186 req: &Request,
187 parent: INodeNo,
188 name: &OsStr,
189 newparent: INodeNo,
190 newname: &OsStr,
191 flags: RenameFlags,
192 ) -> Result<(), Errno> {
193 warn!(
194 "rename not implemented for parent inode {}, name {:?}, newparent {}, newname {:?}, flags {:?}",
195 parent, name, newparent, newname, flags
196 );
197 Err(Errno::ENOTSUP)
198 }
199
200 async fn link(
202 &self,
203 req: &Request,
204 ino: INodeNo,
205 newparent: INodeNo,
206 newname: &OsStr,
207 ) -> Result<EntryResponse, Errno> {
208 warn!(
209 "link not implemented for inode {}, newparent {}, newname {:?}",
210 ino, newparent, newname
211 );
212 Err(Errno::ENOTSUP)
213 }
214
215 async fn open(
217 &self,
218 req: &Request,
219 ino: INodeNo,
220 flags: OpenFlags,
221 ) -> Result<OpenResponse, Errno> {
222 warn!("open not implemented for inode {}, flags {:?}", ino, flags);
223 Err(Errno::ENOTSUP)
224 }
225
226 async fn read(
229 &self,
230 req: &Request,
231 ino: INodeNo,
232 file_handle: FileHandle,
233 offset: u64,
234 size: u32,
235 flags: OpenFlags,
236 lock: Option<LockOwner>,
237 ) -> Result<ReadResponse, Errno> {
238 warn!(
239 "read not implemented for inode {}, offset {}, size {}",
240 ino, offset, size
241 );
242 Err(Errno::ENOTSUP)
243 }
244
245 async fn write(
259 &self,
260 req: &Request,
261 ino: INodeNo,
262 fh: FileHandle,
263 offset: u64,
264 data: &[u8],
265 write_flags: WriteFlags,
266 flags: OpenFlags,
267 lock_owner: Option<LockOwner>,
268 ) -> Result<WriteResponse, Errno> {
269 warn!(
270 "write not implemented for inode {}, offset {}, size {}",
271 ino,
272 offset,
273 data.len()
274 );
275 Err(Errno::ENOTSUP)
276 }
277
278 async fn release(
280 &self,
281 req: &Request,
282 ino: INodeNo,
283 fh: FileHandle,
284 flags: OpenFlags,
285 lock_owner: Option<LockOwner>,
286 flush: bool,
287 ) -> Result<(), Errno> {
288 warn!("release not implemented for inode {}, fh {:?}", ino, fh);
289 Err(Errno::ENOTSUP)
290 }
291
292 async fn opendir(
294 &self,
295 req: &Request,
296 ino: INodeNo,
297 flags: OpenFlags,
298 ) -> Result<OpenResponse, Errno> {
299 warn!(
300 "opendir not implemented for inode {}, flags {:?}",
301 ino, flags
302 );
303 Err(Errno::ENOTSUP)
304 }
305
306 async fn readdir(
309 &self,
310 req: &Request,
311 ino: INodeNo,
312 file_handle: FileHandle,
313 size: u32,
314 offset: u64,
315 ) -> Result<DirectoryResponse, Errno> {
316 warn!(
317 "readdir not implemented for inode {}, offset {}, size {}",
318 ino, offset, size
319 );
320 Err(Errno::ENOTSUP)
321 }
322
323 async fn releasedir(
325 &self,
326 req: &Request,
327 ino: INodeNo,
328 fh: FileHandle,
329 flags: OpenFlags,
330 ) -> Result<(), Errno> {
331 warn!("releasedir not implemented for inode {}, fh {:?}", ino, fh);
332 Err(Errno::ENOTSUP)
333 }
334
335 async fn statfs(&self, req: &Request, ino: INodeNo) -> Result<StatfsResponse, Errno> {
337 warn!("statfs not implemented for inode {}", ino);
338 Err(Errno::ENOTSUP)
339 }
340
341 async fn setxattr(
343 &self,
344 req: &Request,
345 ino: INodeNo,
346 name: &OsStr,
347 value: &[u8],
348 flags: i32,
349 position: u32,
350 ) -> Result<(), Errno> {
351 warn!(
352 "setxattr not implemented for inode {}, name {:?}, flags {}, position {}",
353 ino, name, flags, position
354 );
355 Err(Errno::ENOTSUP)
356 }
357
358 async fn getxattr(
360 &self,
361 req: &Request,
362 ino: INodeNo,
363 name: &OsStr,
364 size: u32,
365 ) -> Result<XattrResponse, Errno> {
366 warn!(
367 "getxattr not implemented for inode {}, name {:?}, size {}",
368 ino, name, size
369 );
370 Err(Errno::ENOTSUP)
371 }
372
373 async fn listxattr(
375 &self,
376 req: &Request,
377 ino: INodeNo,
378 size: u32,
379 ) -> Result<XattrResponse, Errno> {
380 warn!("listxattr not implemented for inode {}, size {}", ino, size);
381 Err(Errno::ENOTSUP)
382 }
383
384 async fn removexattr(&self, req: &Request, ino: INodeNo, name: &OsStr) -> Result<(), Errno> {
386 warn!(
387 "removexattr not implemented for inode {}, name {:?}",
388 ino, name
389 );
390 Err(Errno::ENOTSUP)
391 }
392
393 async fn access(&self, req: &Request, ino: INodeNo, mask: AccessFlags) -> Result<(), Errno> {
395 warn!("access not implemented for inode {}, mask {:?}", ino, mask);
396 Err(Errno::ENOTSUP)
397 }
398
399 async fn create(
401 &self,
402 req: &Request,
403 parent: INodeNo,
404 name: &OsStr,
405 mode: u32,
406 umask: u32,
407 flags: i32,
408 ) -> Result<CreateResponse, Errno> {
409 warn!(
410 "create not implemented for parent inode {}, name {:?}, mode {}, umask {}, flags {}",
411 parent, name, mode, umask, flags
412 );
413 Err(Errno::ENOTSUP)
414 }
415
416 async fn fallocate(
418 &self,
419 req: &Request,
420 ino: INodeNo,
421 fh: FileHandle,
422 offset: u64,
423 length: u64,
424 mode: i32,
425 ) -> Result<(), Errno> {
426 warn!(
427 "fallocate not implemented for inode {}, offset {}, length {}, mode {}",
428 ino, offset, length, mode
429 );
430 Err(Errno::ENOTSUP)
431 }
432
433 async fn copy_file_range(
435 &self,
436 req: &Request,
437 ino_in: INodeNo,
438 fh_in: FileHandle,
439 offset_in: u64,
440 ino_out: INodeNo,
441 fh_out: FileHandle,
442 offset_out: u64,
443 len: u64,
444 flags: CopyFileRangeFlags,
445 ) -> Result<WriteResponse, Errno> {
446 warn!(
447 "copy_file_range not implemented for src ({}, {}, {}), dest ({}, {}, {}), len {}, flags {:?}",
448 ino_in, fh_in, offset_in, ino_out, fh_out, offset_out, len, flags
449 );
450 Err(Errno::ENOTSUP)
451 }
452}
453
454pub async fn mount_async<FS: AsyncFilesystem, P: AsRef<Path>>(
461 filesystem: FS,
462 mountpoint: P,
463 options: &Config,
464) -> io::Result<()> {
465 let session = AsyncSessionBuilder::new()
466 .filesystem(filesystem)
467 .mountpoint(mountpoint)
468 .options(options.clone())?
469 .build()
470 .await?;
471 session.run().await
472}