blown_fuse/ops/
global.rs

1use super::traits::ReplyOk;
2use crate::{io::FsInfo, proto, sealed::Sealed, util::page_size, Done, Operation, Reply};
3
4pub enum Init {}
5pub enum Statfs {}
6
7pub struct InitState {
8    pub(crate) kernel_flags: proto::InitFlags,
9    pub(crate) buffer_pages: usize,
10}
11
12pub trait ReplyFsInfo<'o>: Operation<'o> {
13    fn info(reply: Reply<'o, Self>, info: &FsInfo) -> Done<'o>;
14}
15
16impl Sealed for Init {}
17impl Sealed for Statfs {}
18
19impl<'o> Operation<'o> for Init {
20    type RequestBody = &'o proto::InitIn;
21    type ReplyState = InitState;
22}
23
24impl<'o> Operation<'o> for Statfs {
25    type RequestBody = ();
26    type ReplyState = ();
27}
28
29impl<'o> ReplyOk<'o> for Init {
30    fn ok(reply: Reply<'o, Self>) -> Done<'o> {
31        let InitState {
32            kernel_flags,
33            buffer_pages,
34        } = reply.state;
35
36        let flags = {
37            use proto::InitFlags;
38
39            //TODO: Conditions for these feature flags
40            // - Locks
41            // - ASYNC_DIO
42            // - WRITEBACK_CACHE
43            // - NO_OPEN_SUPPORT
44            // - HANDLE_KILLPRIV
45            // - POSIX_ACL
46            // - NO_OPENDIR_SUPPORT
47            // - EXPLICIT_INVAL_DATA
48
49            let supported = InitFlags::ASYNC_READ
50                | InitFlags::FILE_OPS
51                | InitFlags::ATOMIC_O_TRUNC
52                | InitFlags::EXPORT_SUPPORT
53                | InitFlags::BIG_WRITES
54                | InitFlags::HAS_IOCTL_DIR
55                | InitFlags::AUTO_INVAL_DATA
56                | InitFlags::DO_READDIRPLUS
57                | InitFlags::READDIRPLUS_AUTO
58                | InitFlags::PARALLEL_DIROPS
59                | InitFlags::ABORT_ERROR
60                | InitFlags::MAX_PAGES
61                | InitFlags::CACHE_SYMLINKS;
62
63            kernel_flags & supported
64        };
65
66        let buffer_size = page_size() * buffer_pages;
67
68        // See fs/fuse/dev.c in the kernel source tree for details about max_write
69        let max_write = buffer_size - std::mem::size_of::<(proto::InHeader, proto::WriteIn)>();
70
71        reply.single(&proto::InitOut {
72            major: proto::MAJOR_VERSION,
73            minor: proto::TARGET_MINOR_VERSION,
74            max_readahead: 0, //TODO
75            flags: flags.bits(),
76            max_background: 0,       //TODO
77            congestion_threshold: 0, //TODO
78            max_write: max_write.try_into().unwrap(),
79            time_gran: 1, //TODO
80            max_pages: buffer_pages.try_into().unwrap(),
81            padding: Default::default(),
82            unused: Default::default(),
83        })
84    }
85}
86
87impl<'o> ReplyFsInfo<'o> for Statfs {
88    fn info(reply: Reply<'o, Self>, fs_info: &FsInfo) -> Done<'o> {
89        reply.single(&proto::StatfsOut::from(*fs_info))
90    }
91}