blown_fuse/ops/
inode.rs

1use super::traits::{ReplyOk, RequestHandle};
2use crate::{
3    io::{Ino, Stat},
4    proto,
5    sealed::Sealed,
6    Done, Operation, Reply, Request,
7};
8
9pub enum Forget {}
10pub enum Getattr {}
11pub enum Bmap {}
12
13pub trait RequestForget<'o>: Operation<'o> {
14    fn forget_list<'a>(request: &'a Request<'o, Self>) -> ForgetList<'a>;
15}
16
17pub trait RequestBlock<'o>: Operation<'o> {
18    fn block(request: &Request<'o, Self>) -> u64;
19    fn block_size(request: &Request<'o, Self>) -> u32;
20}
21
22pub trait ReplyStat<'o>: Operation<'o> {
23    fn stat(reply: Reply<'o, Self>, inode: &impl Stat) -> Done<'o>;
24}
25
26pub trait ReplyBlock<'o>: Operation<'o> {
27    fn block(reply: Reply<'o, Self>, block: u64) -> Done<'o>;
28}
29
30pub enum ForgetList<'a> {
31    Single(Option<(Ino, u64)>),
32    Batch(std::slice::Iter<'a, proto::ForgetOne>),
33}
34
35impl Sealed for Forget {}
36impl Sealed for Getattr {}
37impl Sealed for Bmap {}
38
39impl<'o> Operation<'o> for Forget {
40    type RequestBody = proto::OpcodeSelect<
41        (&'o proto::BatchForgetIn, &'o [proto::ForgetOne]),
42        &'o proto::ForgetIn,
43        { proto::Opcode::BatchForget as u32 },
44    >;
45
46    type ReplyState = ();
47}
48
49impl<'o> Operation<'o> for Getattr {
50    type RequestBody = &'o proto::GetattrIn;
51    type ReplyState = ();
52}
53
54impl<'o> Operation<'o> for Bmap {
55    type RequestBody = &'o proto::BmapIn;
56    type ReplyState = ();
57}
58
59impl<'o> RequestForget<'o> for Forget {
60    fn forget_list<'a>(request: &'a Request<'o, Self>) -> ForgetList<'a> {
61        use {proto::OpcodeSelect::*, ForgetList::*};
62
63        impl Iterator for ForgetList<'_> {
64            type Item = (Ino, u64);
65
66            fn next(&mut self) -> Option<Self::Item> {
67                match self {
68                    Single(single) => single.take(),
69                    Batch(batch) => {
70                        let forget = batch.next()?;
71                        Some((Ino(forget.ino), forget.nlookup))
72                    }
73                }
74            }
75        }
76
77        match request.body {
78            Match((_, slice)) => Batch(slice.iter()),
79            Alt(single) => Single(Some((request.ino(), single.nlookup))),
80        }
81    }
82}
83
84impl<'o> ReplyOk<'o> for Forget {
85    fn ok(_reply: Reply<'o, Self>) -> Done<'o> {
86        // No reply for forget requests
87        Done::new()
88    }
89}
90
91impl<'o> RequestHandle<'o> for Getattr {
92    fn handle(request: &Request<'o, Self>) -> u64 {
93        request.body.fh
94    }
95}
96
97impl<'o> ReplyStat<'o> for Getattr {
98    fn stat(reply: Reply<'o, Self>, inode: &impl Stat) -> Done<'o> {
99        let (attrs, ttl) = inode.attrs();
100        let attrs = attrs.finish(inode);
101
102        reply.single(&proto::AttrOut {
103            attr_valid: ttl.seconds(),
104            attr_valid_nsec: ttl.nanoseconds(),
105            dummy: Default::default(),
106            attr: attrs,
107        })
108    }
109}
110
111impl<'o> RequestBlock<'o> for Bmap {
112    fn block(request: &Request<'o, Self>) -> u64 {
113        request.body.block
114    }
115
116    fn block_size(request: &Request<'o, Self>) -> u32 {
117        request.body.block_size
118    }
119}
120
121impl<'o> ReplyBlock<'o> for Bmap {
122    fn block(reply: Reply<'o, Self>, block: u64) -> Done<'o> {
123        reply.single(&proto::BmapOut { block })
124    }
125}