Skip to main content

starnix_modules_fuse/
lib.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#![recursion_limit = "512"]
6
7use fuchsia_rcu::RcuReadScope;
8use linux_uapi::FUSE_DEV_IOC_PASSTHROUGH_OPEN_V2;
9use starnix_core::mm::memory::MemoryObject;
10use starnix_core::mm::{MemoryAccessorExt, PAGE_SIZE, ProtectionFlags};
11use starnix_core::mutable_state::Guard;
12use starnix_core::security;
13use starnix_core::task::waiter::WaiterOptions;
14use starnix_core::task::{CurrentTask, EventHandler, Kernel, WaitCanceler, WaitQueue, Waiter};
15use starnix_core::vfs::buffers::{
16    Buffer, InputBuffer, InputBufferExt as _, OutputBuffer, OutputBufferCallback,
17};
18use starnix_core::vfs::pseudo::dynamic_file::{DynamicFile, DynamicFileBuf, DynamicFileSource};
19use starnix_core::vfs::pseudo::simple_directory::SimpleDirectory;
20use starnix_core::vfs::pseudo::simple_file::SimpleFileNode;
21use starnix_core::vfs::pseudo::vec_directory::{VecDirectory, VecDirectoryEntry};
22use starnix_core::vfs::{
23    AppendLockWriteGuard, CacheMode, CheckAccessReason, DirEntry, DirEntryOps, DirectoryEntryType,
24    DirentSink, FallocMode, FdNumber, FileObject, FileObjectState, FileOps, FileSystem,
25    FileSystemHandle, FileSystemOps, FileSystemOptions, FsLockDepType, FsNode, FsNodeFlags,
26    FsNodeHandle, FsNodeInfo, FsNodeOps, FsStr, FsString, NamespaceNode,
27    PeekBufferSegmentsCallback, RenameContext, SeekTarget, StatxFlags, SymlinkTarget, ValueOrSize,
28    WeakFileHandle, XattrOp, default_eof_offset, default_fcntl, default_seek,
29    fileops_impl_nonseekable, fileops_impl_noop_sync, fs_args, fs_node_impl_dir_readonly,
30};
31use starnix_lifecycle::AtomicCounter;
32use starnix_logging::{log_error, log_trace, log_warn, track_stub};
33use starnix_sync::{
34    AtomicMonotonicInstant, DynamicLockDepRwLock, FuseConnectionStateLock, FuseConnectionsLock,
35    FuseNodeStateLock, LockDepGuard, LockDepMutex, LockDepReadGuard, LockDepWriteGuard,
36};
37use starnix_syscalls::{SyscallArg, SyscallResult};
38use starnix_types::time::{NANOS_PER_SECOND, duration_from_timespec, time_from_timespec};
39use starnix_types::vfs::default_statfs;
40use starnix_uapi::auth::FsCred;
41use starnix_uapi::device_id::DeviceId;
42use starnix_uapi::errors::{EINTR, EINVAL, ENOENT, ENOSYS, Errno};
43use starnix_uapi::file_mode::{Access, FileMode};
44use starnix_uapi::math::round_up_to_increment;
45use starnix_uapi::open_flags::OpenFlags;
46use starnix_uapi::vfs::FdEvents;
47use starnix_uapi::{
48    FUSE_SUPER_MAGIC, errno, errno_from_code, error, ino_t, mode, off_t, statfs, uapi,
49};
50use std::collections::hash_map::Entry;
51use std::collections::{HashMap, VecDeque};
52
53const FUSE_DEFAULT_MAX_PAGES: u16 = 32;
54
55static FUSE_DEFAULT_MAX_WRITE: std::sync::LazyLock<u32> =
56    std::sync::LazyLock::new(|| (FUSE_DEFAULT_MAX_PAGES as u32) * (*PAGE_SIZE as u32));
57use std::ops::{Deref, DerefMut};
58use std::sync::atomic::{AtomicBool, Ordering};
59use std::sync::{Arc, Weak};
60use syncio::zxio_node_attr_has_t;
61use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
62
63const FUSE_ROOT_ID_U64: u64 = uapi::FUSE_ROOT_ID as u64;
64const CONFIGURATION_AVAILABLE_EVENT: u64 = u64::MAX;
65
66uapi::check_arch_independent_layout! {
67    fuse_access_in {}
68    fuse_attr {}
69    fuse_attr_out {}
70    fuse_create_in {}
71    fuse_dirent {}
72    fuse_entry_out {}
73    fuse_flush_in {}
74    fuse_forget_in {}
75    fuse_getxattr_in {}
76    fuse_getxattr_out {}
77    fuse_in_header {}
78    fuse_init_in {}
79    fuse_init_out {}
80    fuse_interrupt_in {}
81    fuse_link_in {}
82    fuse_lseek_in {}
83    fuse_lseek_out {}
84    fuse_mkdir_in {}
85    fuse_mknod_in {}
86    fuse_opcode {}
87    fuse_open_in {}
88    fuse_open_out {}
89    fuse_out_header {}
90    fuse_poll_in {}
91    fuse_poll_out {}
92    fuse_read_in {}
93    fuse_release_in {}
94    fuse_rename2_in {}
95    fuse_setattr_in {}
96    fuse_setxattr_in {}
97    fuse_statfs_out {}
98    fuse_write_in {}
99    fuse_write_out {}
100}
101
102#[derive(Debug)]
103struct DevFuse {
104    connection: Arc<FuseConnection>,
105}
106
107pub fn open_fuse_device(
108    current_task: &CurrentTask,
109    _id: DeviceId,
110    _node: &NamespaceNode,
111    _flags: OpenFlags,
112) -> Result<Box<dyn FileOps>, Errno> {
113    let connection = fuse_connections(current_task.kernel()).new_connection(current_task);
114    Ok(Box::new(DevFuse { connection }))
115}
116
117fn attr_valid_to_duration(
118    attr_valid: u64,
119    attr_valid_nsec: u32,
120) -> Result<zx::MonotonicDuration, Errno> {
121    duration_from_timespec(uapi::timespec {
122        tv_sec: i64::try_from(attr_valid).unwrap_or(i64::MAX),
123        tv_nsec: attr_valid_nsec.into(),
124    })
125}
126
127impl FileOps for DevFuse {
128    fileops_impl_nonseekable!();
129    fileops_impl_noop_sync!();
130
131    fn close(self: Box<Self>, _file: &FileObjectState, _current_task: &CurrentTask) {
132        self.connection.lock().disconnect();
133    }
134
135    fn read(
136        &self,
137        file: &FileObject,
138        current_task: &CurrentTask,
139        offset: usize,
140        data: &mut dyn OutputBuffer,
141    ) -> Result<usize, Errno> {
142        debug_assert!(offset == 0);
143        file.blocking_op(current_task, FdEvents::POLLIN, None, || self.connection.lock().read(data))
144    }
145
146    fn write(
147        &self,
148        _file: &FileObject,
149        _current_task: &CurrentTask,
150        offset: usize,
151        data: &mut dyn InputBuffer,
152    ) -> Result<usize, Errno> {
153        debug_assert!(offset == 0);
154        self.connection.lock().write(data)
155    }
156
157    fn wait_async(
158        &self,
159        _file: &FileObject,
160        _current_task: &CurrentTask,
161        waiter: &Waiter,
162        events: FdEvents,
163        handler: EventHandler,
164    ) -> Option<WaitCanceler> {
165        self.connection.lock().wait_async(waiter, events, handler)
166    }
167
168    fn query_events(
169        &self,
170        _file: &FileObject,
171        _current_task: &CurrentTask,
172    ) -> Result<FdEvents, Errno> {
173        Ok(self.connection.lock().query_events())
174    }
175
176    fn ioctl(
177        &self,
178        _file: &FileObject,
179        current_task: &CurrentTask,
180        request: u32,
181        arg: SyscallArg,
182    ) -> Result<SyscallResult, Errno> {
183        match request {
184            FUSE_DEV_IOC_PASSTHROUGH_OPEN_V2 => {
185                let fd = current_task.read_object::<FdNumber>(arg.into())?;
186                let fd = current_task.files().get(fd)?;
187                let id = {
188                    let mut connection = self.connection.lock();
189                    let (mut id, _) = connection.last_passthrough_id.overflowing_add(1);
190                    let mut entry = connection.registered_passthrough.entry(id);
191                    while id == 0 || matches!(entry, Entry::Occupied(_)) {
192                        let (new_id, _) = id.overflowing_add(1);
193                        id = new_id;
194                        entry = connection.registered_passthrough.entry(id);
195                    }
196                    entry.or_insert_with(|| Arc::downgrade(&fd));
197                    connection.last_passthrough_id = id;
198                    id
199                };
200                Ok(id.into())
201            }
202            _ => error!(ENOTTY),
203        }
204    }
205}
206
207pub fn new_fuse_fs(
208    current_task: &CurrentTask,
209    options: FileSystemOptions,
210) -> Result<FileSystemHandle, Errno> {
211    let fd = fs_args::parse::<FdNumber>(
212        options.params.get(b"fd").ok_or_else(|| errno!(EINVAL))?.as_ref(),
213    )?;
214    let default_permissions = options.params.get(b"default_permissions").is_some().into();
215    let connection = current_task
216        .files()
217        .get(fd)?
218        .downcast_file::<DevFuse>()
219        .ok_or_else(|| errno!(EINVAL))?
220        .connection
221        .clone();
222
223    let fs = FileSystem::new(
224        current_task.kernel(),
225        CacheMode::Cached(current_task.kernel().fs_cache_config()),
226        FuseFs { connection: connection.clone(), default_permissions },
227        options,
228    )?;
229    let fuse_node = FuseNode::new(connection.clone(), FUSE_ROOT_ID_U64, 0);
230    fuse_node.state.lock().nlookup += 1;
231
232    fs.create_root(FUSE_ROOT_ID_U64, fuse_node);
233
234    {
235        let mut state = connection.lock();
236        state.connect();
237        state.execute_operation(
238            current_task,
239            FuseNode::from_node(&fs.root().node),
240            FuseOperation::Init { fs: Arc::downgrade(&fs) },
241        )?;
242    }
243    Ok(fs)
244}
245
246fn fuse_connections(kernel: &Kernel) -> Arc<FuseConnections> {
247    kernel.expando.get::<FuseConnections>()
248}
249
250pub fn new_fusectl_fs(
251    current_task: &CurrentTask,
252    options: FileSystemOptions,
253) -> Result<FileSystemHandle, Errno> {
254    let fs = FileSystem::new(current_task.kernel(), CacheMode::Uncached, FuseCtlFs, options)?;
255
256    let root_ino = fs.allocate_ino();
257    fs.create_root_with_info(
258        root_ino,
259        FuseCtlConnectionsDirectory {},
260        FsNodeInfo::new(mode!(IFDIR, 0o755), FsCred::root()),
261    );
262
263    Ok(fs)
264}
265
266#[derive(Debug)]
267struct FuseFs {
268    connection: Arc<FuseConnection>,
269    default_permissions: AtomicBool,
270}
271
272impl FuseFs {
273    /// Downcasts this `fs` to a [`FuseFs`].
274    ///
275    /// # Panics
276    ///
277    /// Panics if the `fs` is not a `FuseFs`.
278    fn from_fs(fs: &FileSystem) -> &FuseFs {
279        fs.downcast_ops::<FuseFs>().expect("FUSE should only handle `FuseFs`s")
280    }
281}
282
283impl FileSystemOps for FuseFs {
284    fn fs_lockdep_type(&self) -> FsLockDepType {
285        FsLockDepType::Fuse
286    }
287
288    fn rename(
289        &self,
290        _fs: &FileSystem,
291        current_task: &CurrentTask,
292        context: &mut RenameContext<'_>,
293        old_name: &FsStr,
294        new_name: &FsStr,
295    ) -> Result<(), Errno> {
296        let old_parent = &context.old_parent().node;
297        let new_parent = &context.new_parent().node;
298        self.connection.lock().execute_operation(
299            current_task,
300            FuseNode::from_node(&old_parent),
301            FuseOperation::Rename {
302                old_name: old_name.to_owned(),
303                new_dir: new_parent.node_key(),
304                new_name: new_name.to_owned(),
305            },
306        )?;
307        Ok(())
308    }
309
310    fn uses_external_node_ids(&self) -> bool {
311        true
312    }
313
314    fn statfs(&self, fs: &FileSystem, current_task: &CurrentTask) -> Result<statfs, Errno> {
315        let node = FuseNode::from_node(&fs.root().node);
316        let response =
317            self.connection.lock().execute_operation(current_task, &node, FuseOperation::Statfs)?;
318        let FuseResponse::Statfs(statfs_out) = response else {
319            return error!(EINVAL);
320        };
321        Ok(statfs {
322            f_type: FUSE_SUPER_MAGIC as i64,
323            f_blocks: statfs_out.st.blocks.try_into().map_err(|_| errno!(EINVAL))?,
324            f_bfree: statfs_out.st.bfree.try_into().map_err(|_| errno!(EINVAL))?,
325            f_bavail: statfs_out.st.bavail.try_into().map_err(|_| errno!(EINVAL))?,
326            f_files: statfs_out.st.files.try_into().map_err(|_| errno!(EINVAL))?,
327            f_ffree: statfs_out.st.ffree.try_into().map_err(|_| errno!(EINVAL))?,
328            f_bsize: statfs_out.st.bsize.try_into().map_err(|_| errno!(EINVAL))?,
329            f_namelen: statfs_out.st.namelen.try_into().map_err(|_| errno!(EINVAL))?,
330            f_frsize: statfs_out.st.frsize.try_into().map_err(|_| errno!(EINVAL))?,
331            ..statfs::default()
332        })
333    }
334    fn name(&self) -> &'static FsStr {
335        "fuse".into()
336    }
337    fn unmount(&self) {
338        self.connection.lock().disconnect();
339    }
340}
341
342#[derive(Debug, Default)]
343struct FuseConnections {
344    connections: LockDepMutex<Vec<Weak<FuseConnection>>, FuseConnectionsLock>,
345    next_identifier: AtomicCounter<u64>,
346}
347
348impl FuseConnections {
349    fn new_connection(&self, current_task: &CurrentTask) -> Arc<FuseConnection> {
350        let connection = Arc::new(FuseConnection {
351            id: self.next_identifier.next(),
352            creds: current_task.current_fscred(),
353            state: Default::default(),
354        });
355        self.connections.lock().push(Arc::downgrade(&connection));
356        connection
357    }
358
359    fn for_each<F>(&self, mut f: F)
360    where
361        F: FnMut(Arc<FuseConnection>),
362    {
363        self.connections.lock().retain(|connection| {
364            if let Some(connection) = connection.upgrade() {
365                f(connection);
366                true
367            } else {
368                false
369            }
370        });
371    }
372}
373
374struct FuseCtlFs;
375
376impl FileSystemOps for FuseCtlFs {
377    fn rename(
378        &self,
379        _fs: &FileSystem,
380        _current_task: &CurrentTask,
381        _context: &mut RenameContext<'_>,
382        _old_name: &FsStr,
383        _new_name: &FsStr,
384    ) -> Result<(), Errno> {
385        error!(ENOTSUP)
386    }
387
388    fn statfs(&self, _fs: &FileSystem, _current_task: &CurrentTask) -> Result<statfs, Errno> {
389        // Magic number has been extracted from the stat utility.
390        const FUSE_CTL_MAGIC: u32 = 0x65735543;
391        Ok(default_statfs(FUSE_CTL_MAGIC))
392    }
393
394    fn name(&self) -> &'static FsStr {
395        "fusectl".into()
396    }
397}
398
399#[derive(Debug)]
400struct FuseCtlConnectionsDirectory;
401
402impl FsNodeOps for FuseCtlConnectionsDirectory {
403    fs_node_impl_dir_readonly!();
404
405    fn create_file_ops(
406        &self,
407        _node: &FsNode,
408        current_task: &CurrentTask,
409        _flags: OpenFlags,
410    ) -> Result<Box<dyn FileOps>, Errno> {
411        let connnections = fuse_connections(current_task.kernel());
412        let mut entries = vec![];
413        connnections.for_each(|connection| {
414            entries.push(VecDirectoryEntry {
415                entry_type: DirectoryEntryType::DIR,
416                name: connection.id.to_string().into(),
417                inode: None,
418            });
419        });
420        Ok(VecDirectory::new_file(entries))
421    }
422
423    fn lookup(
424        &self,
425        entry: &DirEntry,
426        current_task: &CurrentTask,
427        name: &FsStr,
428    ) -> Result<FsNodeHandle, Errno> {
429        let name = std::str::from_utf8(name).map_err(|_| errno!(ENOENT))?;
430        let id = name.parse::<u64>().map_err(|_| errno!(ENOENT))?;
431        let connnections = fuse_connections(current_task.kernel());
432        let mut connection = None;
433        connnections.for_each(|c| {
434            if c.id == id {
435                connection = Some(c);
436            }
437        });
438        let Some(connection) = connection else {
439            return error!(ENOENT);
440        };
441        let fs = entry.node.fs();
442        let dir = SimpleDirectory::new();
443        dir.edit(&fs, |dir| {
444            dir.node(
445                "abort".into(),
446                fs.create_node_and_allocate_node_id(
447                    AbortFile::new_node(connection.clone()),
448                    FsNodeInfo::new(mode!(IFREG, 0o200), connection.creds),
449                ),
450            );
451            dir.node(
452                "waiting".into(),
453                fs.create_node_and_allocate_node_id(
454                    WaitingFile::new_node(connection.clone()),
455                    FsNodeInfo::new(mode!(IFREG, 0o400), connection.creds),
456                ),
457            );
458        });
459
460        let info = FsNodeInfo::new(mode!(IFDIR, 0o500), connection.creds);
461        Ok(fs.create_node_and_allocate_node_id(dir, info))
462    }
463}
464
465#[derive(Debug)]
466struct AbortFile {
467    connection: Arc<FuseConnection>,
468}
469
470impl AbortFile {
471    fn new_node(connection: Arc<FuseConnection>) -> impl FsNodeOps {
472        SimpleFileNode::new(move |_| Ok(Self { connection: connection.clone() }))
473    }
474}
475
476impl FileOps for AbortFile {
477    fileops_impl_nonseekable!();
478    fileops_impl_noop_sync!();
479
480    fn read(
481        &self,
482        _file: &FileObject,
483        _current_task: &CurrentTask,
484        _offset: usize,
485        _data: &mut dyn OutputBuffer,
486    ) -> Result<usize, Errno> {
487        Ok(0)
488    }
489
490    fn write(
491        &self,
492        _file: &FileObject,
493        _current_task: &CurrentTask,
494        _offset: usize,
495        data: &mut dyn InputBuffer,
496    ) -> Result<usize, Errno> {
497        let drained = data.drain();
498        if drained > 0 {
499            self.connection.lock().disconnect();
500        }
501        Ok(drained)
502    }
503}
504
505#[derive(Clone, Debug)]
506struct WaitingFile {
507    connection: Arc<FuseConnection>,
508}
509
510impl WaitingFile {
511    fn new_node(connection: Arc<FuseConnection>) -> impl FsNodeOps {
512        DynamicFile::new_node(Self { connection })
513    }
514}
515
516impl DynamicFileSource for WaitingFile {
517    fn generate(
518        &self,
519        _current_task: &CurrentTask,
520        sink: &mut DynamicFileBuf,
521    ) -> Result<(), Errno> {
522        let value = {
523            let state = self.connection.state.lock();
524            state.operations.len() + state.message_queue.len()
525        };
526        let value = format!("{value}\n");
527        sink.write(value.as_bytes());
528        Ok(())
529    }
530}
531
532#[derive(Debug, Default)]
533struct FuseNodeMutableState {
534    nlookup: u64,
535
536    /// Validity deadline from the most recent entry reply (e.g. to `FUSE_LOOKUP`) that returned
537    /// this node, for the `DirEntry` created for that reply.
538    ///
539    /// Taken by `create_dir_entry_ops` so that the new `DirEntry` is not revalidated before the
540    /// deadline, like Linux does with `fuse_change_entry_timeout()`.
541    entry_valid_until: Option<zx::MonotonicInstant>,
542}
543
544#[derive(Debug)]
545struct FuseNode {
546    connection: Arc<FuseConnection>,
547
548    /// A unique identifier for this node.
549    ///
550    /// This value might not be the same as the inode number ([`FsNodeInfo::ino`]).
551    ///
552    /// See <https://libfuse.github.io/doxygen/structfuse__operations.html#ac39a0b7125a0e5001eb5ff42e05faa5d>
553    /// for more information.
554    nodeid: u64,
555
556    generation: u64,
557    attributes_valid_until: AtomicMonotonicInstant,
558    state: LockDepMutex<FuseNodeMutableState, FuseNodeStateLock>,
559}
560
561impl FuseNode {
562    fn new(connection: Arc<FuseConnection>, nodeid: u64, generation: u64) -> Self {
563        Self {
564            connection,
565            nodeid,
566            generation,
567            attributes_valid_until: zx::MonotonicInstant::INFINITE_PAST.into(),
568            state: Default::default(),
569        }
570    }
571
572    /// Downcasts this `node` to a [`FuseNode`].
573    ///
574    /// # Panics
575    ///
576    /// Panics if the `node` is not a `FuseNode`.
577    fn from_node(node: &FsNode) -> &FuseNode {
578        node.downcast_ops::<FuseNode>().expect("FUSE should only handle `FuseNode`s")
579    }
580
581    fn default_check_access_with_valid_node_attributes(
582        &self,
583        node: &FsNode,
584        current_task: &CurrentTask,
585        permission_flags: security::PermissionFlags,
586        reason: CheckAccessReason,
587        info: &DynamicLockDepRwLock<FsNodeInfo>,
588        audit_context: security::Auditable<'_>,
589    ) -> Result<(), Errno> {
590        let info = self.refresh_expired_node_attributes(current_task, info)?;
591        node.default_check_access_impl(current_task, permission_flags, reason, info, audit_context)
592    }
593
594    fn refresh_expired_node_attributes<'a>(
595        &self,
596        current_task: &CurrentTask,
597        info: &'a DynamicLockDepRwLock<FsNodeInfo>,
598    ) -> Result<LockDepReadGuard<'a, FsNodeInfo>, Errno> {
599        // Relaxed because the attributes valid until atomic is not used to synchronize
600        // anything. Its final access is protected by the info lock anyways.
601        const VALID_UNTIL_LOAD_ORDERING: Ordering = Ordering::Relaxed;
602
603        let now = zx::MonotonicInstant::get();
604        if self.attributes_valid_until.load(VALID_UNTIL_LOAD_ORDERING) >= now {
605            let info = info.read();
606
607            // Check the valid_until again after taking the info lock to make sure
608            // that the attributes are still valid. We do this because after we
609            // checked the first time and now, the node's attributes could have been
610            // invalidated or expired.
611            //
612            // But why not only check if the attributes are valid after taking the
613            // lock? Because when we will impact FUSE implementations that don't
614            // support caching, or caching with small valid durations, by always
615            // taking a read lock which we then drop to acquire a write lock. We
616            // slightly pessimize the "happy" path with an extra atomic load so
617            // that we don't overly pessimize the uncached/"slower" path.
618            if self.attributes_valid_until.load(VALID_UNTIL_LOAD_ORDERING) >= now {
619                return Ok(info);
620            }
621        }
622
623        // Force a refresh of our cached attributes.
624        self.fetch_and_refresh_info_impl(current_task, info)
625    }
626
627    fn fetch_and_refresh_info_impl<'a>(
628        &self,
629        current_task: &CurrentTask,
630        info: &'a DynamicLockDepRwLock<FsNodeInfo>,
631    ) -> Result<LockDepReadGuard<'a, FsNodeInfo>, Errno> {
632        let response =
633            self.connection.lock().execute_operation(current_task, self, FuseOperation::GetAttr)?;
634        let uapi::fuse_attr_out { attr_valid, attr_valid_nsec, attr, .. } =
635            if let FuseResponse::Attr(attr) = response {
636                attr
637            } else {
638                return error!(EINVAL);
639            };
640        let mut info = info.write();
641        FuseNode::update_node_info_from_attr(
642            &mut info,
643            attr,
644            attr_valid_to_duration(attr_valid, attr_valid_nsec)?,
645            &self.attributes_valid_until,
646        )?;
647        Ok(LockDepWriteGuard::downgrade(info))
648    }
649
650    fn invalidate_attributes(&self) {
651        self.attributes_valid_until.store(zx::MonotonicInstant::INFINITE_PAST, Ordering::Relaxed);
652    }
653
654    fn update_node_info_from_attr(
655        info: &mut FsNodeInfo,
656        attributes: uapi::fuse_attr,
657        attr_valid_duration: zx::MonotonicDuration,
658        node_attributes_valid_until: &AtomicMonotonicInstant,
659    ) -> Result<(), Errno> {
660        info.mode = FileMode::from_bits(attributes.mode);
661        info.size = attributes.size.try_into().map_err(|_| errno!(EINVAL))?;
662        info.blocks = attributes.blocks.try_into().map_err(|_| errno!(EINVAL))?;
663        info.blksize = attributes.blksize.try_into().map_err(|_| errno!(EINVAL))?;
664        info.uid = attributes.uid;
665        info.gid = attributes.gid;
666        info.link_count = attributes.nlink.try_into().map_err(|_| errno!(EINVAL))?;
667        info.time_status_change = time_from_timespec(uapi::timespec {
668            tv_sec: attributes.ctime as i64,
669            tv_nsec: attributes.ctimensec as i64,
670        })?;
671        info.time_access = time_from_timespec(uapi::timespec {
672            tv_sec: attributes.atime as i64,
673            tv_nsec: attributes.atimensec as i64,
674        })?;
675        info.time_modify = time_from_timespec(uapi::timespec {
676            tv_sec: attributes.mtime as i64,
677            tv_nsec: attributes.mtimensec as i64,
678        })?;
679        info.rdev = DeviceId::from_bits(attributes.rdev as u64);
680
681        node_attributes_valid_until
682            .store(zx::MonotonicInstant::after(attr_valid_duration), Ordering::Relaxed);
683        Ok(())
684    }
685
686    /// Build a FsNodeHandle from a FuseResponse that is expected to be a FuseResponse::Entry.
687    fn fs_node_from_entry(
688        &self,
689        node: &FsNode,
690        name: &FsStr,
691        entry: &uapi::fuse_entry_out,
692    ) -> Result<FsNodeHandle, Errno> {
693        if entry.nodeid == 0 {
694            return error!(ENOENT);
695        }
696        let attr_valid_duration = attr_valid_to_duration(entry.attr_valid, entry.attr_valid_nsec)?;
697        let entry_valid_until = zx::MonotonicInstant::after(attr_valid_to_duration(
698            entry.entry_valid,
699            entry.entry_valid_nsec,
700        )?);
701        let mut created = false;
702        let node = node.fs().get_and_validate_or_create_node(
703            entry.nodeid,
704            |node| {
705                let fuse_node = FuseNode::from_node(&node);
706                fuse_node.generation == entry.generation
707            },
708            || {
709                created = true;
710                let fuse_node =
711                    FuseNode::new(self.connection.clone(), entry.nodeid, entry.generation);
712                let mut info = FsNodeInfo::default();
713                FuseNode::update_node_info_from_attr(
714                    &mut info,
715                    entry.attr,
716                    attr_valid_duration,
717                    &fuse_node.attributes_valid_until,
718                )?;
719                Ok(FsNode::new_uncached(
720                    entry.attr.ino,
721                    fuse_node,
722                    &node.fs(),
723                    info,
724                    FsNodeFlags::empty(),
725                ))
726            },
727        )?;
728        // . and .. do not get their lookup count increased, nor a `DirEntry` of their own.
729        if !DirEntry::is_reserved_name(name) {
730            let fuse_node = FuseNode::from_node(&node);
731            {
732                let mut state = fuse_node.state.lock();
733                state.nlookup += 1;
734                state.entry_valid_until = Some(entry_valid_until);
735            }
736            if !created {
737                node.update_info(|info| {
738                    FuseNode::update_node_info_from_attr(
739                        info,
740                        entry.attr,
741                        attr_valid_duration,
742                        &fuse_node.attributes_valid_until,
743                    )
744                })?;
745            }
746        }
747        Ok(node)
748    }
749}
750
751struct FuseFileObject {
752    connection: Arc<FuseConnection>,
753    /// An optional file handle to redirect all read/write to.
754    passthrough_file: WeakFileHandle,
755    /// The response to the open calls from the userspace process.
756    open_out: uapi::fuse_open_out,
757}
758
759impl FuseFileObject {
760    /// Returns the `FuseNode` associated with the opened file.
761    fn get_fuse_node(file: &FileObject) -> &FuseNode {
762        FuseNode::from_node(file.node())
763    }
764}
765
766impl FileOps for FuseFileObject {
767    fn close(self: Box<Self>, file: &FileObjectState, current_task: &CurrentTask) {
768        let node = FuseNode::from_node(file.node());
769        let is_dir = file.node().is_dir();
770        {
771            let mut connection = self.connection.lock();
772            if let Err(e) = connection.execute_operation(
773                current_task,
774                node,
775                if is_dir {
776                    FuseOperation::ReleaseDir(self.open_out)
777                } else {
778                    FuseOperation::Release(self.open_out)
779                },
780            ) {
781                if e.code != ENOSYS {
782                    log_error!("Error when releasing fh: {e:?}");
783                }
784            }
785            connection.clear_released_passthrough_fds();
786        }
787    }
788
789    fn flush(&self, file: &FileObject, current_task: &CurrentTask) {
790        let node = Self::get_fuse_node(file);
791        if let Err(e) = self.connection.lock().execute_operation(
792            current_task,
793            node,
794            FuseOperation::Flush(self.open_out),
795        ) {
796            log_error!("Error when flushing fh: {e:?}");
797        }
798    }
799
800    fn is_seekable(&self) -> bool {
801        true
802    }
803
804    fn read(
805        &self,
806        file: &FileObject,
807        current_task: &CurrentTask,
808        mut offset: usize,
809        data: &mut dyn OutputBuffer,
810    ) -> Result<usize, Errno> {
811        if file.node().info().mode.is_dir() {
812            return error!(EISDIR);
813        }
814        if let Some(file_object) = self.passthrough_file.upgrade() {
815            return file_object.ops().read(&file_object, current_task, offset, data);
816        }
817
818        // EOF bounds capping to prevent reading past file limits.
819        let file_size = file.node().fetch_and_refresh_info(current_task)?.size;
820        if offset >= file_size {
821            return Ok(0);
822        }
823        let mut target_size = std::cmp::min(data.available(), file_size - offset);
824        if target_size == 0 {
825            return Ok(0);
826        }
827
828        let max_transfer = self.connection.max_read_size();
829        let node = Self::get_fuse_node(file);
830        let mut total_read = 0;
831
832        while target_size > 0 {
833            let chunk_size = std::cmp::min(target_size, max_transfer);
834            let response = self.connection.lock().execute_operation(
835                current_task,
836                node,
837                FuseOperation::Read(uapi::fuse_read_in {
838                    fh: self.open_out.fh,
839                    offset: offset.try_into().map_err(|_| errno!(EINVAL))?,
840                    size: chunk_size.try_into().map_err(|_| errno!(EINVAL))?,
841                    read_flags: 0,
842                    lock_owner: 0,
843                    flags: 0,
844                    padding: 0,
845                }),
846            );
847
848            let response = match response {
849                Ok(r) => r,
850                Err(e) => {
851                    if total_read > 0 {
852                        return Ok(total_read);
853                    } else {
854                        return Err(e);
855                    }
856                }
857            };
858
859            let FuseResponse::Read(read_out) = response else {
860                if total_read > 0 {
861                    return Ok(total_read);
862                } else {
863                    return error!(EINVAL);
864                }
865            };
866            let read_out_len = read_out.len();
867            if read_out_len == 0 {
868                return Ok(total_read); // EOF from daemon
869            }
870            let to_write = std::cmp::min(read_out_len, chunk_size);
871            let write_len = match data.write(&read_out[..to_write]) {
872                Ok(len) => len,
873                Err(e) => {
874                    if total_read > 0 {
875                        return Ok(total_read);
876                    } else {
877                        return Err(e);
878                    }
879                }
880            };
881            offset += write_len;
882            total_read += write_len;
883            target_size = target_size.saturating_sub(write_len);
884            if write_len < to_write {
885                // The guest buffer is full or we hit a memory fault.
886                return Ok(total_read);
887            }
888            if read_out_len < chunk_size {
889                // Short read from daemon indicates EOF or no more data available.
890                return Ok(total_read);
891            }
892        }
893        Ok(total_read)
894    }
895
896    fn write(
897        &self,
898        file: &FileObject,
899        current_task: &CurrentTask,
900        mut offset: usize,
901        data: &mut dyn InputBuffer,
902    ) -> Result<usize, Errno> {
903        if file.node().info().mode.is_dir() {
904            return error!(EISDIR);
905        }
906        let node = Self::get_fuse_node(file);
907        if let Some(file_object) = self.passthrough_file.upgrade() {
908            let written = file_object.ops().write(&file_object, current_task, offset, data)?;
909            if written > 0 {
910                node.invalidate_attributes();
911            }
912            return Ok(written);
913        }
914
915        let max_transfer = self.connection.max_write_size();
916        let mut total_written = 0;
917
918        while data.available() > 0 {
919            let chunk_size = std::cmp::min(data.available(), max_transfer);
920            let mut chunk = Vec::with_capacity(chunk_size);
921            let bytes_peeked = data.peek(chunk.spare_capacity_mut())?;
922            if bytes_peeked == 0 {
923                break;
924            }
925            // SAFETY: `data.peek` guarantees that it has initialized `bytes_peeked` bytes in the
926            // buffer. `bytes_peeked` is `<= chunk_size` (which is the capacity of the vector).
927            unsafe {
928                chunk.set_len(bytes_peeked);
929            }
930
931            let response = self.connection.lock().execute_operation(
932                current_task,
933                node,
934                FuseOperation::Write {
935                    write_in: uapi::fuse_write_in {
936                        fh: self.open_out.fh,
937                        offset: offset.try_into().map_err(|_| errno!(EINVAL))?,
938                        size: bytes_peeked.try_into().map_err(|_| errno!(EINVAL))?,
939                        write_flags: 0,
940                        lock_owner: 0,
941                        flags: 0,
942                        padding: 0,
943                    },
944                    content: chunk,
945                },
946            );
947
948            let response = match response {
949                Ok(r) => r,
950                Err(e) => {
951                    if total_written > 0 {
952                        break;
953                    } else {
954                        return Err(e);
955                    }
956                }
957            };
958
959            let FuseResponse::Write(write_out) = response else {
960                if total_written > 0 {
961                    break;
962                } else {
963                    return error!(EINVAL);
964                }
965            };
966
967            let written = std::cmp::min(write_out.size as usize, bytes_peeked);
968            offset += written;
969            total_written += written;
970            data.advance(written)?;
971            if written < bytes_peeked {
972                break; // Short write from daemon
973            }
974        }
975        if total_written > 0 {
976            node.invalidate_attributes();
977        }
978        Ok(total_written)
979    }
980
981    fn seek(
982        &self,
983        file: &FileObject,
984        current_task: &CurrentTask,
985        current_offset: off_t,
986        target: SeekTarget,
987    ) -> Result<off_t, Errno> {
988        // Only delegate SEEK_DATA and SEEK_HOLE to the userspace process.
989        if matches!(target, SeekTarget::Data(_) | SeekTarget::Hole(_)) {
990            let node = Self::get_fuse_node(file);
991            let response = self.connection.lock().execute_operation(
992                current_task,
993                node,
994                FuseOperation::Seek(uapi::fuse_lseek_in {
995                    fh: self.open_out.fh,
996                    offset: target.offset().try_into().map_err(|_| errno!(EINVAL))?,
997                    whence: target.whence(),
998                    padding: 0,
999                }),
1000            );
1001            match response {
1002                Ok(response) => {
1003                    let FuseResponse::Seek(seek_out) = response else {
1004                        return error!(EINVAL);
1005                    };
1006                    return seek_out.offset.try_into().map_err(|_| errno!(EINVAL));
1007                }
1008                // If errno is ENOSYS, the userspace process doesn't support the seek operation and
1009                // the default seek must be used.
1010                Err(errno) if errno == ENOSYS => {}
1011                Err(errno) => return Err(errno),
1012            };
1013        }
1014
1015        default_seek(current_offset, target, || default_eof_offset(file, current_task))
1016    }
1017
1018    fn sync(&self, file: &FileObject, current_task: &CurrentTask) -> Result<(), Errno> {
1019        if let Some(file_object) = self.passthrough_file.upgrade() {
1020            return file_object.ops().sync(&file_object, current_task);
1021        }
1022        let node = Self::get_fuse_node(file);
1023        let is_dir = file.node().info().mode.is_dir();
1024        let _response = self.connection.lock().execute_operation(
1025            current_task,
1026            node,
1027            FuseOperation::Fsync { fh: self.open_out.fh, is_dir, datasync: false },
1028        )?;
1029        Ok(())
1030    }
1031
1032    fn data_sync(&self, file: &FileObject, current_task: &CurrentTask) -> Result<(), Errno> {
1033        if let Some(file_object) = self.passthrough_file.upgrade() {
1034            return file_object.ops().data_sync(&file_object, current_task);
1035        }
1036        let node = Self::get_fuse_node(file);
1037        let is_dir = file.node().info().mode.is_dir();
1038        let _response = self.connection.lock().execute_operation(
1039            current_task,
1040            node,
1041            FuseOperation::Fsync { fh: self.open_out.fh, is_dir, datasync: true },
1042        )?;
1043        Ok(())
1044    }
1045
1046    fn get_memory(
1047        &self,
1048        _file: &FileObject,
1049        current_task: &CurrentTask,
1050        length: Option<usize>,
1051        prot: ProtectionFlags,
1052    ) -> Result<Arc<MemoryObject>, Errno> {
1053        if let Some(file_object) = self.passthrough_file.upgrade() {
1054            return file_object.ops().get_memory(&file_object, current_task, length, prot);
1055        }
1056        error!(ENODEV)
1057    }
1058
1059    fn wait_async(
1060        &self,
1061        _file: &FileObject,
1062        _current_task: &CurrentTask,
1063        _waiter: &Waiter,
1064        _events: FdEvents,
1065        _handler: EventHandler,
1066    ) -> Option<WaitCanceler> {
1067        None
1068    }
1069
1070    fn query_events(
1071        &self,
1072        file: &FileObject,
1073        current_task: &CurrentTask,
1074    ) -> Result<FdEvents, Errno> {
1075        let node = Self::get_fuse_node(file);
1076        let response = self.connection.lock().execute_operation(
1077            current_task,
1078            node,
1079            FuseOperation::Poll(uapi::fuse_poll_in {
1080                fh: self.open_out.fh,
1081                kh: 0,
1082                flags: 0,
1083                events: FdEvents::all().bits(),
1084            }),
1085        )?;
1086        let FuseResponse::Poll(poll_out) = response else {
1087            return error!(EINVAL);
1088        };
1089        FdEvents::from_bits(poll_out.revents).ok_or_else(|| errno!(EINVAL))
1090    }
1091
1092    fn readdir(
1093        &self,
1094        file: &FileObject,
1095        current_task: &CurrentTask,
1096        sink: &mut dyn DirentSink,
1097    ) -> Result<(), Errno> {
1098        let mut state = self.connection.lock();
1099        let configuration = state.get_configuration(current_task)?;
1100        let use_readdirplus = {
1101            if configuration.flags.contains(FuseInitFlags::DO_READDIRPLUS) {
1102                if configuration.flags.contains(FuseInitFlags::READDIRPLUS_AUTO) {
1103                    sink.offset() == 0
1104                } else {
1105                    true
1106                }
1107            } else {
1108                false
1109            }
1110        };
1111        // Request a number of bytes related to the user capacity. If none is given, default to a
1112        // single page of data.
1113        let user_capacity = if let Some(base_user_capacity) = sink.user_capacity() {
1114            if use_readdirplus {
1115                // Add some amount of capacity for the entries.
1116                base_user_capacity * 3 / 2
1117            } else {
1118                base_user_capacity
1119            }
1120        } else {
1121            *PAGE_SIZE as usize
1122        };
1123        let node = Self::get_fuse_node(file);
1124        let response = state.execute_operation(
1125            current_task,
1126            node,
1127            FuseOperation::Readdir {
1128                read_in: uapi::fuse_read_in {
1129                    fh: self.open_out.fh,
1130                    offset: sink.offset().try_into().map_err(|_| errno!(EINVAL))?,
1131                    size: user_capacity.try_into().map_err(|_| errno!(EINVAL))?,
1132                    read_flags: 0,
1133                    lock_owner: 0,
1134                    flags: 0,
1135                    padding: 0,
1136                },
1137                use_readdirplus,
1138            },
1139        )?;
1140        std::mem::drop(state);
1141        let FuseResponse::Readdir(dirents) = response else {
1142            return error!(EINVAL);
1143        };
1144        let mut sink_result = Ok(());
1145        for (dirent, name, entry) in dirents {
1146            if let Some(entry) = entry {
1147                // nodeid == 0 means the server doesn't want to send entry info.
1148                if entry.nodeid != 0 {
1149                    if let Err(e) = node.fs_node_from_entry(file.node(), name.as_ref(), &entry) {
1150                        log_error!("Unable to prefill entry: {e:?}");
1151                    }
1152                }
1153            }
1154            if sink_result.is_ok() {
1155                sink_result = sink.add(
1156                    dirent.ino,
1157                    dirent.off.try_into().map_err(|_| errno!(EINVAL))?,
1158                    DirectoryEntryType::from_bits(
1159                        dirent.type_.try_into().map_err(|_| errno!(EINVAL))?,
1160                    ),
1161                    name.as_ref(),
1162                );
1163            }
1164        }
1165        sink_result
1166    }
1167
1168    fn ioctl(
1169        &self,
1170        _file: &FileObject,
1171        _current_task: &CurrentTask,
1172        _request: u32,
1173        _arg: SyscallArg,
1174    ) -> Result<SyscallResult, Errno> {
1175        track_stub!(TODO("https://fxbug.dev/322875259"), "fuse ioctl");
1176        error!(ENOTTY)
1177    }
1178
1179    fn fcntl(
1180        &self,
1181        _file: &FileObject,
1182        _current_task: &CurrentTask,
1183        cmd: u32,
1184        _arg: u64,
1185    ) -> Result<SyscallResult, Errno> {
1186        track_stub!(TODO("https://fxbug.dev/322875764"), "fuse fcntl");
1187        default_fcntl(cmd)
1188    }
1189}
1190
1191struct FuseDirEntry {
1192    valid_until: AtomicMonotonicInstant,
1193}
1194
1195impl DirEntryOps for FuseDirEntry {
1196    fn revalidate(&self, current_task: &CurrentTask, dir_entry: &DirEntry) -> Result<bool, Errno> {
1197        // Relaxed because the attributes valid until atomic is not used to synchronize
1198        // anything.
1199        const VALID_UNTIL_ORDERING: Ordering = Ordering::Relaxed;
1200
1201        let now = zx::MonotonicInstant::get();
1202        if self.valid_until.load(VALID_UNTIL_ORDERING) >= now {
1203            return Ok(true);
1204        }
1205
1206        let node = FuseNode::from_node(&dir_entry.node);
1207        if node.nodeid == FUSE_ROOT_ID_U64 {
1208            // The root node entry is always valid.
1209            return Ok(true);
1210        }
1211
1212        // Perform a lookup on this entry's parent FUSE node to revalidate this
1213        // entry.
1214        let (parent, name) = {
1215            let scope = RcuReadScope::new();
1216            let parent = dir_entry.parent().expect("non-root nodes always has a parent");
1217            let name = dir_entry.local_name(&scope).to_owned();
1218            (parent, name)
1219        };
1220        let parent = FuseNode::from_node(&parent.node);
1221        let uapi::fuse_entry_out {
1222            nodeid,
1223            generation,
1224            entry_valid,
1225            entry_valid_nsec,
1226            attr,
1227            attr_valid,
1228            attr_valid_nsec,
1229        } = match parent.connection.lock().execute_operation(
1230            current_task,
1231            parent,
1232            FuseOperation::Lookup { name },
1233        ) {
1234            Ok(FuseResponse::Entry(entry)) => entry,
1235            Ok(_) => return error!(EINVAL),
1236            Err(errno) => {
1237                if errno == ENOENT {
1238                    // The entry no longer exists.
1239                    return Ok(false);
1240                } else {
1241                    return Err(errno);
1242                };
1243            }
1244        };
1245
1246        if (nodeid != node.nodeid) || (generation != node.generation) {
1247            // A new entry exists with the name. This `DirEntry` is no longer
1248            // valid. The caller should attempt to restart the path walk at this
1249            // node.
1250            return Ok(false);
1251        }
1252
1253        dir_entry.node.update_info(|info| {
1254            FuseNode::update_node_info_from_attr(
1255                info,
1256                attr,
1257                attr_valid_to_duration(attr_valid, attr_valid_nsec)?,
1258                &node.attributes_valid_until,
1259            )?;
1260
1261            self.valid_until.store(
1262                zx::MonotonicInstant::after(attr_valid_to_duration(entry_valid, entry_valid_nsec)?),
1263                VALID_UNTIL_ORDERING,
1264            );
1265
1266            Ok(true)
1267        })
1268    }
1269}
1270
1271// `FuseFs.default_permissions` is not used to synchronize anything.
1272const DEFAULT_PERMISSIONS_ATOMIC_ORDERING: Ordering = Ordering::Relaxed;
1273
1274impl FsNodeOps for FuseNode {
1275    fn check_access(
1276        &self,
1277        node: &FsNode,
1278        current_task: &CurrentTask,
1279        permission_flags: security::PermissionFlags,
1280        info: &DynamicLockDepRwLock<FsNodeInfo>,
1281        reason: CheckAccessReason,
1282        audit_context: security::Auditable<'_>,
1283    ) -> Result<(), Errno> {
1284        // Perform access checks regardless of the reason when userspace configured
1285        // the kernel to perform its default access checks on behalf of the FUSE fs.
1286        if FuseFs::from_fs(&node.fs()).default_permissions.load(DEFAULT_PERMISSIONS_ATOMIC_ORDERING)
1287        {
1288            return self.default_check_access_with_valid_node_attributes(
1289                node,
1290                current_task,
1291                permission_flags,
1292                reason,
1293                info,
1294                audit_context,
1295            );
1296        }
1297
1298        match reason {
1299            CheckAccessReason::Access | CheckAccessReason::Chdir | CheckAccessReason::Chroot => {
1300                // Per `libfuse`'s low-level handler for `FUSE_ACCESS` requests, the kernel
1301                // is only expected to send `FUSE_ACCESS` requests for the `access` and `chdir`
1302                // family of syscalls when the `default_permissions` flag isn't set on the FUSE
1303                // fs. Seems like `chroot` also triggers a `FUSE_ACCESS` request on Linux.
1304                let response = self.connection.lock().execute_operation(
1305                    current_task,
1306                    self,
1307                    FuseOperation::Access {
1308                        mask: (permission_flags.as_access() & Access::ACCESS_MASK).bits() as u32,
1309                    },
1310                )?;
1311
1312                if let FuseResponse::Access(result) = response { result } else { error!(EINVAL) }
1313            }
1314            CheckAccessReason::Exec => self.default_check_access_with_valid_node_attributes(
1315                node,
1316                current_task,
1317                permission_flags,
1318                reason,
1319                info,
1320                audit_context,
1321            ),
1322            CheckAccessReason::ChangeTimestamps { .. }
1323            | CheckAccessReason::InternalPermissionChecks => {
1324                // Per FUSE's mount options, the kernel does not check file access
1325                // permissions unless the default permissions mount option is set.
1326                //
1327                // See https://www.kernel.org/doc/html/v5.6/filesystems/fuse.html#mount-options.
1328                Ok(())
1329            }
1330        }
1331    }
1332
1333    fn create_dir_entry_ops(&self) -> Box<dyn DirEntryOps> {
1334        let valid_until = self
1335            .state
1336            .lock()
1337            .entry_valid_until
1338            .take()
1339            .unwrap_or(zx::MonotonicInstant::INFINITE_PAST);
1340        Box::new(FuseDirEntry { valid_until: valid_until.into() })
1341    }
1342
1343    fn create_file_ops(
1344        &self,
1345        node: &FsNode,
1346        current_task: &CurrentTask,
1347        flags: OpenFlags,
1348    ) -> Result<Box<dyn FileOps>, Errno> {
1349        // The node already exists. The creation has been handled before calling this method.
1350        let flags = flags & !(OpenFlags::CREAT | OpenFlags::EXCL);
1351        let mode = node.info().mode;
1352        let response = self.connection.lock().execute_operation(
1353            current_task,
1354            self,
1355            FuseOperation::Open { flags, mode },
1356        )?;
1357        let FuseResponse::Open(open_out) = response else {
1358            return error!(EINVAL);
1359        };
1360        // SAFETY: The data has been read with zerocopy which ensures every bits have been
1361        // initialized.
1362        let passthrough_fh = unsafe { open_out.__bindgen_anon_1.passthrough_fh };
1363        let passthrough_file = if passthrough_fh != 0 {
1364            let mut connection = self.connection.lock();
1365            connection.registered_passthrough.remove(&passthrough_fh).unwrap_or_default()
1366        } else {
1367            Weak::new()
1368        };
1369        Ok(Box::new(FuseFileObject {
1370            connection: self.connection.clone(),
1371            passthrough_file,
1372            open_out,
1373        }))
1374    }
1375
1376    fn lookup(
1377        &self,
1378        entry: &DirEntry,
1379        current_task: &CurrentTask,
1380        name: &FsStr,
1381    ) -> Result<FsNodeHandle, Errno> {
1382        let response = self.connection.lock().execute_operation(
1383            current_task,
1384            self,
1385            FuseOperation::Lookup { name: name.to_owned() },
1386        )?;
1387        self.fs_node_from_entry(&entry.node, name, response.entry().ok_or_else(|| errno!(EINVAL))?)
1388    }
1389
1390    fn mknod(
1391        &self,
1392        node: &FsNode,
1393        current_task: &CurrentTask,
1394        name: &FsStr,
1395        mode: FileMode,
1396        dev: DeviceId,
1397        _owner: FsCred,
1398    ) -> Result<FsNodeHandle, Errno> {
1399        let get_entry = || {
1400            let umask = current_task.fs().umask().bits();
1401            let mut connection = self.connection.lock();
1402
1403            if dev == DeviceId::NONE && !connection.no_create {
1404                match connection.execute_operation(
1405                    current_task,
1406                    self,
1407                    FuseOperation::Create(
1408                        uapi::fuse_create_in {
1409                            flags: OpenFlags::CREAT.bits(),
1410                            mode: mode.bits(),
1411                            umask,
1412                            open_flags: 0,
1413                        },
1414                        name.to_owned(),
1415                    ),
1416                ) {
1417                    Ok(response) => {
1418                        let FuseResponse::Create(response) = response else {
1419                            return error!(EINVAL);
1420                        };
1421
1422                        let fuse_node = FuseNode::new(
1423                            self.connection.clone(),
1424                            response.entry.nodeid,
1425                            response.entry.generation,
1426                        );
1427
1428                        // It is unfortunate that we have to immediately release the file (only for
1429                        // it to typically be reopened a short time later), but it will be a little
1430                        // tricky to fix this properly, and there are Fuse implementations that rely
1431                        // on us using create rather than mknod to create regular files.  We will
1432                        // have to tackle this if it shows up as a performance issue.
1433                        if let Err(e) = connection.execute_operation(
1434                            current_task,
1435                            &fuse_node,
1436                            FuseOperation::Release(response.open),
1437                        ) {
1438                            log_error!("Error when releasing fh: {e:?}");
1439                        }
1440
1441                        return Ok(response.entry);
1442                    }
1443                    Err(e) if e == ENOSYS => {
1444                        connection.no_create = true;
1445                        // Fall through to use mknod below.
1446                    }
1447                    Err(e) => return Err(e),
1448                }
1449            }
1450
1451            connection
1452                .execute_operation(
1453                    current_task,
1454                    self,
1455                    FuseOperation::Mknod {
1456                        mknod_in: uapi::fuse_mknod_in {
1457                            mode: mode.bits(),
1458                            rdev: dev.bits() as u32,
1459                            umask,
1460                            padding: 0,
1461                        },
1462                        name: name.to_owned(),
1463                    },
1464                )?
1465                .entry()
1466                .copied()
1467                .ok_or_else(|| errno!(EINVAL))
1468        };
1469
1470        let entry = get_entry()?;
1471        self.fs_node_from_entry(node, name, &entry)
1472    }
1473
1474    fn mkdir(
1475        &self,
1476        node: &FsNode,
1477        current_task: &CurrentTask,
1478        name: &FsStr,
1479        mode: FileMode,
1480        _owner: FsCred,
1481    ) -> Result<FsNodeHandle, Errno> {
1482        let response = self.connection.lock().execute_operation(
1483            current_task,
1484            self,
1485            FuseOperation::Mkdir {
1486                mkdir_in: uapi::fuse_mkdir_in {
1487                    mode: mode.bits(),
1488                    umask: current_task.fs().umask().bits(),
1489                },
1490                name: name.to_owned(),
1491            },
1492        )?;
1493        self.fs_node_from_entry(node, name, response.entry().ok_or_else(|| errno!(EINVAL))?)
1494    }
1495
1496    fn create_symlink(
1497        &self,
1498        node: &FsNode,
1499        current_task: &CurrentTask,
1500        name: &FsStr,
1501        target: &FsStr,
1502        _owner: FsCred,
1503    ) -> Result<FsNodeHandle, Errno> {
1504        let response = self.connection.lock().execute_operation(
1505            current_task,
1506            self,
1507            FuseOperation::Symlink { target: target.to_owned(), name: name.to_owned() },
1508        )?;
1509        self.fs_node_from_entry(node, name, response.entry().ok_or_else(|| errno!(EINVAL))?)
1510    }
1511
1512    fn readlink(&self, _node: &FsNode, current_task: &CurrentTask) -> Result<SymlinkTarget, Errno> {
1513        let response = self.connection.lock().execute_operation(
1514            current_task,
1515            self,
1516            FuseOperation::Readlink,
1517        )?;
1518        let FuseResponse::Read(read_out) = response else {
1519            return error!(EINVAL);
1520        };
1521        Ok(SymlinkTarget::Path(read_out.into()))
1522    }
1523
1524    fn link(
1525        &self,
1526        node: &FsNode,
1527        current_task: &CurrentTask,
1528        name: &FsStr,
1529        child: &FsNodeHandle,
1530    ) -> Result<(), Errno> {
1531        let child_node = FuseNode::from_node(child);
1532        let response = self.connection.lock().execute_operation(
1533            current_task,
1534            self,
1535            FuseOperation::Link {
1536                link_in: uapi::fuse_link_in { oldnodeid: child_node.nodeid },
1537                name: name.to_owned(),
1538            },
1539        )?;
1540        let entry = response.entry().ok_or_else(|| errno!(EINVAL))?;
1541        if entry.nodeid != child_node.nodeid || entry.generation != child_node.generation {
1542            return error!(EINVAL);
1543        }
1544        self.fs_node_from_entry(node, name, entry).map(|_| ())
1545    }
1546
1547    fn unlink(
1548        &self,
1549        _node: &FsNode,
1550        current_task: &CurrentTask,
1551        name: &FsStr,
1552        child: &FsNodeHandle,
1553    ) -> Result<(), Errno> {
1554        let is_dir = child.is_dir();
1555        self.connection
1556            .lock()
1557            .execute_operation(
1558                current_task,
1559                self,
1560                if is_dir {
1561                    FuseOperation::Rmdir { name: name.to_owned() }
1562                } else {
1563                    FuseOperation::Unlink { name: name.to_owned() }
1564                },
1565            )
1566            .map(|_| ())
1567    }
1568
1569    fn truncate(
1570        &self,
1571        _guard: &AppendLockWriteGuard<'_>,
1572        node: &FsNode,
1573        current_task: &CurrentTask,
1574        length: u64,
1575    ) -> Result<(), Errno> {
1576        node.update_info(|info| {
1577            // Truncate is implemented by updating the attributes of the file.
1578            let attributes = uapi::fuse_setattr_in {
1579                size: length,
1580                valid: uapi::FATTR_SIZE,
1581                ..Default::default()
1582            };
1583
1584            let response = self.connection.lock().execute_operation(
1585                current_task,
1586                self,
1587                FuseOperation::SetAttr(attributes),
1588            )?;
1589            let uapi::fuse_attr_out { attr_valid, attr_valid_nsec, attr, .. } =
1590                if let FuseResponse::Attr(attr) = response {
1591                    attr
1592                } else {
1593                    return error!(EINVAL);
1594                };
1595            FuseNode::update_node_info_from_attr(
1596                info,
1597                attr,
1598                attr_valid_to_duration(attr_valid, attr_valid_nsec)?,
1599                &self.attributes_valid_until,
1600            )?;
1601            Ok(())
1602        })
1603    }
1604
1605    fn allocate(
1606        &self,
1607        _guard: &AppendLockWriteGuard<'_>,
1608        _node: &FsNode,
1609        _current_task: &CurrentTask,
1610        _mode: FallocMode,
1611        _offset: u64,
1612        _length: u64,
1613    ) -> Result<(), Errno> {
1614        track_stub!(TODO("https://fxbug.dev/322875414"), "FsNodeOps::allocate");
1615        error!(ENOTSUP)
1616    }
1617
1618    fn fetch_and_refresh_info<'a>(
1619        &self,
1620        _node: &FsNode,
1621        current_task: &CurrentTask,
1622        info: &'a DynamicLockDepRwLock<FsNodeInfo>,
1623        flags: StatxFlags,
1624    ) -> Result<LockDepReadGuard<'a, FsNodeInfo>, Errno> {
1625        if flags.contains(StatxFlags::AT_STATX_DONT_SYNC) {
1626            return Ok(info.read());
1627        }
1628        // NOTE: Do not be tempted to always refresh information here; sadly, there are CTS tests
1629        // that rely on this only updating attributes if they have expired, and this matches what
1630        // Linux appears to do.
1631        self.refresh_expired_node_attributes(current_task, info)
1632    }
1633
1634    fn update_attributes(
1635        &self,
1636        _node: &FsNode,
1637        current_task: &CurrentTask,
1638        info: &FsNodeInfo,
1639        has: zxio_node_attr_has_t,
1640    ) -> Result<(), Errno> {
1641        let mut valid = 0u32;
1642        // Nb: We don't have a mechanism for 'FATTR_*TIME_NOW'.
1643        if has.modification_time {
1644            valid |= uapi::FATTR_MTIME;
1645        }
1646        if has.access_time {
1647            valid |= uapi::FATTR_ATIME;
1648        }
1649        if has.mode {
1650            valid |= uapi::FATTR_MODE;
1651        }
1652        if has.uid {
1653            valid |= uapi::FATTR_UID;
1654        }
1655        if has.gid {
1656            valid |= uapi::FATTR_GID;
1657        }
1658
1659        let attributes = uapi::fuse_setattr_in {
1660            valid,
1661            atime: (info.time_access.into_nanos() / NANOS_PER_SECOND) as u64,
1662            mtime: (info.time_modify.into_nanos() / NANOS_PER_SECOND) as u64,
1663            ctime: (info.time_status_change.into_nanos() / NANOS_PER_SECOND) as u64,
1664            atimensec: (info.time_access.into_nanos() % NANOS_PER_SECOND) as u32,
1665            mtimensec: (info.time_modify.into_nanos() % NANOS_PER_SECOND) as u32,
1666            ctimensec: (info.time_status_change.into_nanos() % NANOS_PER_SECOND) as u32,
1667            mode: info.mode.bits(),
1668            uid: info.uid,
1669            gid: info.gid,
1670            ..Default::default()
1671        };
1672
1673        let response = self.connection.lock().execute_operation(
1674            current_task,
1675            self,
1676            FuseOperation::SetAttr(attributes),
1677        )?;
1678        if let FuseResponse::Attr(_attr) = response { Ok(()) } else { error!(EINVAL) }
1679    }
1680
1681    fn get_xattr(
1682        &self,
1683        _node: &FsNode,
1684        current_task: &CurrentTask,
1685        name: &FsStr,
1686        max_size: usize,
1687    ) -> Result<ValueOrSize<FsString>, Errno> {
1688        let response = self.connection.lock().execute_operation(
1689            current_task,
1690            self,
1691            FuseOperation::GetXAttr {
1692                getxattr_in: uapi::fuse_getxattr_in {
1693                    size: max_size.try_into().map_err(|_| errno!(EINVAL))?,
1694                    padding: 0,
1695                },
1696                name: name.to_owned(),
1697            },
1698        )?;
1699        if let FuseResponse::GetXAttr(result) = response { Ok(result) } else { error!(EINVAL) }
1700    }
1701
1702    fn set_xattr(
1703        &self,
1704        _node: &FsNode,
1705        current_task: &CurrentTask,
1706        name: &FsStr,
1707        value: &FsStr,
1708        op: XattrOp,
1709    ) -> Result<(), Errno> {
1710        let mut state = self.connection.lock();
1711        let configuration = state.get_configuration(current_task)?;
1712        state.execute_operation(
1713            current_task,
1714            self,
1715            FuseOperation::SetXAttr {
1716                setxattr_in: uapi::fuse_setxattr_in {
1717                    size: value.len().try_into().map_err(|_| errno!(EINVAL))?,
1718                    flags: op.into_flags(),
1719                    setxattr_flags: 0,
1720                    padding: 0,
1721                },
1722                is_ext: configuration.flags.contains(FuseInitFlags::SETXATTR_EXT),
1723                name: name.to_owned(),
1724                value: value.to_owned(),
1725            },
1726        )?;
1727        Ok(())
1728    }
1729
1730    fn remove_xattr(
1731        &self,
1732        _node: &FsNode,
1733        current_task: &CurrentTask,
1734        name: &FsStr,
1735    ) -> Result<(), Errno> {
1736        self.connection.lock().execute_operation(
1737            current_task,
1738            self,
1739            FuseOperation::RemoveXAttr { name: name.to_owned() },
1740        )?;
1741        Ok(())
1742    }
1743
1744    fn list_xattrs(
1745        &self,
1746        _node: &FsNode,
1747        current_task: &CurrentTask,
1748        max_size: usize,
1749    ) -> Result<ValueOrSize<Vec<FsString>>, Errno> {
1750        let response = self.connection.lock().execute_operation(
1751            current_task,
1752            self,
1753            FuseOperation::ListXAttr(uapi::fuse_getxattr_in {
1754                size: max_size.try_into().map_err(|_| errno!(EINVAL))?,
1755                padding: 0,
1756            }),
1757        )?;
1758        if let FuseResponse::GetXAttr(result) = response {
1759            Ok(result.map(|s| {
1760                let mut result = s.split(|c| *c == 0).map(FsString::from).collect::<Vec<_>>();
1761                // The returned string ends with a '\0', so the split ends with an empty value that
1762                // needs to be removed.
1763                result.pop();
1764                result
1765            }))
1766        } else {
1767            error!(EINVAL)
1768        }
1769    }
1770
1771    fn forget(self: Box<Self>, current_task: &CurrentTask, _info: FsNodeInfo) -> Result<(), Errno> {
1772        let nlookup = self.state.lock().nlookup;
1773        let mut state = self.connection.lock();
1774        if !state.is_connected() {
1775            return Ok(());
1776        }
1777        if nlookup > 0 {
1778            state.execute_operation(
1779                current_task,
1780                self.as_ref(),
1781                FuseOperation::Forget(uapi::fuse_forget_in { nlookup }),
1782            )?;
1783        };
1784        Ok(())
1785    }
1786
1787    fn node_key(&self, _node: &FsNode) -> ino_t {
1788        self.nodeid
1789    }
1790}
1791
1792/// The state of the connection to the /dev/fuse file descriptor.
1793#[derive(Debug, Default)]
1794enum FuseConnectionState {
1795    #[default]
1796    /// The /dev/fuse device has been opened, but the filesystem has not been mounted yet.
1797    Waiting,
1798    /// The file system is mounted.
1799    Connected,
1800    /// The file system has been unmounted.
1801    Disconnected,
1802}
1803
1804#[derive(Debug)]
1805struct FuseConnection {
1806    /// Connection identifier for fusectl.
1807    id: u64,
1808
1809    /// Credentials of the task that opened the connection.
1810    creds: FsCred,
1811
1812    /// Mutable state of the connection.
1813    state: LockDepMutex<FuseMutableState, FuseConnectionStateLock>,
1814}
1815
1816struct FuseMutableStateGuard<'a>(Guard<'a, FuseConnection, LockDepGuard<'a, FuseMutableState>>);
1817
1818impl<'a> Deref for FuseMutableStateGuard<'a> {
1819    type Target = Guard<'a, FuseConnection, LockDepGuard<'a, FuseMutableState>>;
1820    fn deref(&self) -> &Self::Target {
1821        &self.0
1822    }
1823}
1824
1825impl<'a> DerefMut for FuseMutableStateGuard<'a> {
1826    fn deref_mut(&mut self) -> &mut Self::Target {
1827        &mut self.0
1828    }
1829}
1830
1831impl FuseConnection {
1832    fn lock<'a>(&'a self) -> FuseMutableStateGuard<'a> {
1833        FuseMutableStateGuard(Guard::<'a, FuseConnection, LockDepGuard<'a, FuseMutableState>>::new(
1834            self,
1835            self.state.lock(),
1836        ))
1837    }
1838
1839    fn max_read_size(&self) -> usize {
1840        self.lock()
1841            .configuration
1842            .map(|c| c.max_read_size())
1843            .unwrap_or((FUSE_DEFAULT_MAX_PAGES as usize) * (*PAGE_SIZE as usize))
1844    }
1845
1846    fn max_write_size(&self) -> usize {
1847        self.lock()
1848            .configuration
1849            .map(|c| c.max_write_size())
1850            .unwrap_or(*FUSE_DEFAULT_MAX_WRITE as usize)
1851    }
1852}
1853
1854#[derive(Clone, Copy, Debug)]
1855struct FuseConfiguration {
1856    flags: FuseInitFlags,
1857    max_write: u32,
1858    max_pages: u16,
1859}
1860
1861impl FuseConfiguration {
1862    // TODO: Support `max_read` mount option parsing if needed. For now, fall back
1863    // to page-based limitation (max_pages * PAGE_SIZE).
1864    fn max_read_size(&self) -> usize {
1865        (self.max_pages as usize) * (*PAGE_SIZE as usize)
1866    }
1867
1868    fn max_write_size(&self) -> usize {
1869        let limit_by_write = self.max_write as usize;
1870        let limit_by_pages = (self.max_pages as usize) * (*PAGE_SIZE as usize);
1871        std::cmp::min(limit_by_write, limit_by_pages)
1872    }
1873}
1874
1875impl TryFrom<uapi::fuse_init_out> for FuseConfiguration {
1876    type Error = Errno;
1877    fn try_from(init_out: uapi::fuse_init_out) -> Result<Self, Errno> {
1878        let flags = FuseInitFlags::try_from(init_out)?;
1879        let max_write =
1880            if init_out.max_write == 0 { *FUSE_DEFAULT_MAX_WRITE } else { init_out.max_write };
1881        let max_pages =
1882            if init_out.max_pages == 0 { FUSE_DEFAULT_MAX_PAGES } else { init_out.max_pages };
1883        Ok(Self { flags, max_write, max_pages })
1884    }
1885}
1886
1887/// A per connection state for operations that can be shortcircuited.
1888///
1889/// For a number of Fuse operation, Fuse protocol specifies that if they fail in a specific way,
1890/// they should not be sent to the server again and must be handled in a predefined way. This
1891/// map keep track of these operations for a given connection. If this map contains a result for a
1892/// given opcode, any further attempt to send this opcode to userspace will be answered with the
1893/// content of the map.
1894type OperationsState = HashMap<uapi::fuse_opcode, Result<FuseResponse, Errno>>;
1895
1896#[derive(Debug, Default)]
1897struct FuseMutableState {
1898    /// The state of the mount.
1899    state: FuseConnectionState,
1900
1901    /// Last unique id used to identify messages between the kernel and user space.
1902    last_unique_id: u64,
1903
1904    /// The configuration, negotiated with the client.
1905    configuration: Option<FuseConfiguration>,
1906
1907    /// In progress operations.
1908    operations: HashMap<u64, RunningOperation>,
1909
1910    /// Enqueued messages. These messages have not yet been sent to userspace. There should be
1911    /// multiple queues, but for now, push every messages to the same queue.
1912    /// New messages are added at the end of the queues. Read consume from the front of the queue.
1913    message_queue: VecDeque<FuseKernelMessage>,
1914
1915    /// Queue to notify of new messages.
1916    waiters: WaitQueue,
1917
1918    /// The state of the different operations, to allow short-circuiting the userspace process.
1919    operations_state: OperationsState,
1920
1921    /// If true, then the create operation is not supported in which case mknod will be used.
1922    no_create: bool,
1923
1924    /// Last used id for registered fd for passthrough.
1925    last_passthrough_id: u32,
1926
1927    /// All currently registered fd for passthrough, associated with their id. The elements are
1928    /// cleared when used and regularly to check for closed files.
1929    registered_passthrough: HashMap<u32, WeakFileHandle>,
1930}
1931
1932impl<'a> FuseMutableStateGuard<'a> {
1933    fn wait_for_configuration<T>(
1934        &mut self,
1935        current_task: &CurrentTask,
1936        f: impl Fn(&FuseConfiguration) -> T,
1937    ) -> Result<T, Errno> {
1938        if let Some(configuration) = self.configuration.as_ref() {
1939            return Ok(f(configuration));
1940        }
1941        loop {
1942            if !self.is_connected() {
1943                return error!(ECONNABORTED);
1944            }
1945            let waiter = Waiter::new();
1946            self.waiters.wait_async_value(&waiter, CONFIGURATION_AVAILABLE_EVENT);
1947            if let Some(configuration) = self.configuration.as_ref() {
1948                return Ok(f(configuration));
1949            }
1950            Guard::<'a, FuseConnection, LockDepGuard<'a, FuseMutableState>>::unlocked(
1951                self,
1952                || waiter.wait(current_task),
1953            )?;
1954        }
1955    }
1956
1957    fn get_configuration(
1958        &mut self,
1959        current_task: &CurrentTask,
1960    ) -> Result<FuseConfiguration, Errno> {
1961        self.wait_for_configuration(current_task, Clone::clone)
1962    }
1963
1964    fn wait_for_configuration_ready(&mut self, current_task: &CurrentTask) -> Result<(), Errno> {
1965        self.wait_for_configuration(current_task, |_| ())
1966    }
1967
1968    /// Execute the given operation on the `node`. If the operation is not asynchronous, this
1969    /// method will wait on the userspace process for a response. If the operation is interrupted,
1970    /// an interrupt will be sent to the userspace process and the operation will then block until
1971    /// the initial operation has a response. This block can only be interrupted by the filesystem
1972    /// being unmounted.
1973    fn execute_operation(
1974        &mut self,
1975        current_task: &CurrentTask,
1976        node: &FuseNode,
1977        operation: FuseOperation,
1978    ) -> Result<FuseResponse, Errno> {
1979        // Block until we have a valid configuration to make sure that the FUSE
1980        // implementation has initialized, indicated by its response to the
1981        // `FUSE_INIT` request. Obviously, we skip this check for the `FUSE_INIT`
1982        // request itself.
1983        if !matches!(operation, FuseOperation::Init { .. }) {
1984            self.wait_for_configuration_ready(current_task)?;
1985        }
1986
1987        if let Some(result) = self.operations_state.get(&operation.opcode()) {
1988            return result.clone();
1989        }
1990        if !operation.has_response() {
1991            self.queue_operation(current_task, node.nodeid, operation, None)?;
1992            return Ok(FuseResponse::None);
1993        }
1994        let waiter = Waiter::with_options(WaiterOptions::UNSAFE_CALLSTACK);
1995        let is_async = operation.is_async();
1996        let unique_id =
1997            self.queue_operation(current_task, node.nodeid, operation, Some(&waiter))?;
1998        if is_async {
1999            return Ok(FuseResponse::None);
2000        }
2001        let mut first_loop = true;
2002        loop {
2003            if !self.is_connected() {
2004                return error!(ECONNABORTED);
2005            }
2006            if let Some(response) = self.get_response(unique_id) {
2007                return response;
2008            }
2009            match Guard::<'a, FuseConnection, LockDepGuard<'a, FuseMutableState>>::unlocked(
2010                self,
2011                || waiter.wait(current_task),
2012            ) {
2013                Ok(()) => {}
2014                Err(e) if e == EINTR => {
2015                    // If interrupted by another process, send an interrupt command to the server
2016                    // the first time, then wait unconditionally.
2017                    if first_loop {
2018                        self.interrupt(current_task, node.nodeid, unique_id)?;
2019                        first_loop = false;
2020                    }
2021                }
2022                Err(e) => {
2023                    log_error!("Unexpected error: {e:?}");
2024                    return Err(e);
2025                }
2026            }
2027        }
2028    }
2029}
2030
2031impl FuseMutableState {
2032    fn wait_async(
2033        &self,
2034        waiter: &Waiter,
2035        events: FdEvents,
2036        handler: EventHandler,
2037    ) -> Option<WaitCanceler> {
2038        Some(self.waiters.wait_async_fd_events(waiter, events, handler))
2039    }
2040
2041    fn is_connected(&self) -> bool {
2042        matches!(self.state, FuseConnectionState::Connected)
2043    }
2044
2045    fn set_configuration(&mut self, configuration: FuseConfiguration) {
2046        debug_assert!(self.configuration.is_none());
2047        log_trace!("Fuse configuration: {configuration:?}");
2048        self.configuration = Some(configuration);
2049        self.waiters.notify_value(CONFIGURATION_AVAILABLE_EVENT);
2050    }
2051
2052    fn connect(&mut self) {
2053        debug_assert!(matches!(self.state, FuseConnectionState::Waiting));
2054        self.state = FuseConnectionState::Connected;
2055    }
2056
2057    /// Disconnect the mount. Happens on unmount. Every filesystem operation will fail with
2058    /// ECONNABORTED, and every read/write on the /dev/fuse fd will fail with ENODEV.
2059    fn disconnect(&mut self) {
2060        if matches!(self.state, FuseConnectionState::Disconnected) {
2061            return;
2062        }
2063        self.state = FuseConnectionState::Disconnected;
2064        self.message_queue.clear();
2065        self.operations.clear();
2066        self.waiters.notify_all();
2067    }
2068
2069    /// Queue the given operation on the internal queue for the userspace daemon to read. If
2070    /// `waiter` is not None, register `waiter` to be notified when userspace responds to the
2071    /// operation. This should only be used if the operation expects a response.
2072    fn queue_operation(
2073        &mut self,
2074        current_task: &CurrentTask,
2075        nodeid: u64,
2076        operation: FuseOperation,
2077        waiter: Option<&Waiter>,
2078    ) -> Result<u64, Errno> {
2079        debug_assert!(waiter.is_some() == operation.has_response(), "{operation:?}");
2080        if !self.is_connected() {
2081            return error!(ECONNABORTED);
2082        }
2083        self.last_unique_id += 1;
2084        let message = FuseKernelMessage::new(self.last_unique_id, current_task, nodeid, operation)?;
2085        if let Some(waiter) = waiter {
2086            self.waiters.wait_async_value(waiter, self.last_unique_id);
2087        }
2088        if message.operation.has_response() {
2089            self.operations.insert(self.last_unique_id, message.operation.as_running().into());
2090        }
2091        self.message_queue.push_back(message);
2092        self.waiters.notify_fd_events(FdEvents::POLLIN);
2093        Ok(self.last_unique_id)
2094    }
2095
2096    /// Interrupt the operation with the given unique_id.
2097    ///
2098    /// If the operation is still enqueued, this will immediately dequeue the operation and return
2099    /// with an EINTR error.
2100    ///
2101    /// If not, it will send an interrupt operation.
2102    fn interrupt(
2103        &mut self,
2104        current_task: &CurrentTask,
2105        nodeid: u64,
2106        unique_id: u64,
2107    ) -> Result<(), Errno> {
2108        debug_assert!(self.operations.contains_key(&unique_id));
2109
2110        let mut in_queue = false;
2111        self.message_queue.retain(|m| {
2112            if m.header.unique == unique_id {
2113                self.operations.remove(&unique_id);
2114                in_queue = true;
2115                false
2116            } else {
2117                true
2118            }
2119        });
2120        if in_queue {
2121            // Nothing to do, the operation has been cancelled before being sent.
2122            return error!(EINTR);
2123        }
2124        self.queue_operation(current_task, nodeid, FuseOperation::Interrupt { unique_id }, None)
2125            .map(|_| ())
2126    }
2127
2128    /// Returns the response for the operation with the given identifier. Returns None if the
2129    /// operation is still in flight.
2130    fn get_response(&mut self, unique_id: u64) -> Option<Result<FuseResponse, Errno>> {
2131        match self.operations.entry(unique_id) {
2132            Entry::Vacant(_) => Some(error!(EINVAL)),
2133            Entry::Occupied(mut entry) => {
2134                let result = entry.get_mut().response.take();
2135                if result.is_some() {
2136                    entry.remove();
2137                }
2138                result
2139            }
2140        }
2141    }
2142
2143    fn query_events(&self) -> FdEvents {
2144        let mut events = FdEvents::POLLOUT;
2145        if !self.is_connected() || !self.message_queue.is_empty() {
2146            events |= FdEvents::POLLIN
2147        };
2148        if !self.is_connected() {
2149            events |= FdEvents::POLLERR;
2150        }
2151        events
2152    }
2153
2154    fn read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
2155        match self.state {
2156            FuseConnectionState::Waiting => return error!(EPERM),
2157            FuseConnectionState::Disconnected => return error!(ENODEV),
2158            _ => {}
2159        }
2160        if let Some(message) = self.message_queue.pop_front() {
2161            message.serialize(data)
2162        } else {
2163            error!(EAGAIN)
2164        }
2165    }
2166
2167    fn write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
2168        match self.state {
2169            FuseConnectionState::Waiting => return error!(EPERM),
2170            FuseConnectionState::Disconnected => return error!(ENODEV),
2171            _ => {}
2172        }
2173        let header: uapi::fuse_out_header = data.read_to_object()?;
2174        let payload_size = (header.len as usize)
2175            .checked_sub(std::mem::size_of::<uapi::fuse_out_header>())
2176            .ok_or_else(|| errno!(EINVAL))?;
2177        if payload_size > data.available() {
2178            return error!(EINVAL);
2179        }
2180        if header.unique == 0 {
2181            track_stub!(TODO("https://fxbug.dev/322873416"), "Fuse notification from userspace");
2182            return error!(ENOTSUP);
2183        }
2184        self.waiters.notify_value(header.unique);
2185        let mut running_operation = match self.operations.entry(header.unique) {
2186            Entry::Occupied(e) => e,
2187            Entry::Vacant(_) => return error!(EINVAL),
2188        };
2189        let operation = &running_operation.get().operation;
2190        let is_async = operation.is_async();
2191        if header.error < 0 {
2192            log_trace!("Fuse: {operation:?} -> {header:?}");
2193            let code = i16::try_from(-header.error).unwrap_or_else(|_| EINVAL.error_code() as i16);
2194            let errno = errno_from_code!(code);
2195            let response = operation.handle_error(&mut self.operations_state, errno);
2196            if is_async {
2197                running_operation.remove();
2198            } else {
2199                running_operation.get_mut().response = Some(response);
2200            }
2201        } else {
2202            let buffer = data.read_to_vec_limited(payload_size)?;
2203            if buffer.len() != payload_size {
2204                return error!(EINVAL);
2205            }
2206            let response = operation.parse_response(buffer)?;
2207            log_trace!("Fuse: {operation:?} -> {response:?}");
2208            if is_async {
2209                let operation = running_operation.remove();
2210                self.handle_async(operation, response)?;
2211            } else {
2212                running_operation.get_mut().response = Some(Ok(response));
2213            }
2214        }
2215        Ok(data.bytes_read())
2216    }
2217
2218    fn handle_async(
2219        &mut self,
2220        operation: RunningOperation,
2221        response: FuseResponse,
2222    ) -> Result<(), Errno> {
2223        match (operation.operation, response) {
2224            (RunningOperationKind::Init { fs }, FuseResponse::Init(init_out)) => {
2225                let configuration = FuseConfiguration::try_from(init_out)?;
2226                if configuration.flags.contains(FuseInitFlags::POSIX_ACL) {
2227                    // Per libfuse's documentation on `FUSE_CAP_POSIX_ACL`,
2228                    // the POSIX_ACL flag implicitly enables the
2229                    // `default_permissions` mount option.
2230                    if let Some(fs) = fs.upgrade() {
2231                        FuseFs::from_fs(&fs)
2232                            .default_permissions
2233                            .store(true, DEFAULT_PERMISSIONS_ATOMIC_ORDERING)
2234                    } else {
2235                        log_warn!("failed to upgrade FuseFs when handling FUSE_INIT response");
2236                        return error!(ENOTCONN);
2237                    }
2238                }
2239                self.set_configuration(configuration);
2240                Ok(())
2241            }
2242            operation => {
2243                // Init is the only async operation.
2244                panic!("Incompatible operation={operation:?}");
2245            }
2246        }
2247    }
2248
2249    fn clear_released_passthrough_fds(&mut self) {
2250        self.registered_passthrough.retain(|_, s| s.strong_count() > 0);
2251    }
2252}
2253
2254/// An operation that is either queued to be send to userspace, or already sent to userspace and
2255/// waiting for a response.
2256#[derive(Debug)]
2257struct RunningOperation {
2258    operation: RunningOperationKind,
2259    response: Option<Result<FuseResponse, Errno>>,
2260}
2261
2262impl From<RunningOperationKind> for RunningOperation {
2263    fn from(operation: RunningOperationKind) -> Self {
2264        Self { operation, response: None }
2265    }
2266}
2267
2268#[derive(Debug)]
2269struct FuseKernelMessage {
2270    header: uapi::fuse_in_header,
2271    operation: FuseOperation,
2272}
2273
2274impl FuseKernelMessage {
2275    fn new(
2276        unique: u64,
2277        current_task: &CurrentTask,
2278        nodeid: u64,
2279        operation: FuseOperation,
2280    ) -> Result<Self, Errno> {
2281        let current_creds = current_task.current_creds();
2282        Ok(Self {
2283            header: uapi::fuse_in_header {
2284                len: u32::try_from(std::mem::size_of::<uapi::fuse_in_header>() + operation.len())
2285                    .map_err(|_| errno!(EINVAL))?,
2286                opcode: operation.opcode(),
2287                unique,
2288                nodeid,
2289                uid: current_creds.uid,
2290                gid: current_creds.gid,
2291                pid: current_task.get_tid() as u32,
2292                __bindgen_anon_1: Default::default(),
2293            },
2294            operation,
2295        })
2296    }
2297
2298    fn serialize(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
2299        let size = data.write(self.header.as_bytes())?;
2300        Ok(size + self.operation.serialize(data)?)
2301    }
2302}
2303
2304bitflags::bitflags! {
2305    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2306    pub struct FuseInitFlags : u64 {
2307        const BIG_WRITES = uapi::FUSE_BIG_WRITES as u64;
2308        const DONT_MASK = uapi::FUSE_DONT_MASK as u64;
2309        const SPLICE_WRITE = uapi::FUSE_SPLICE_WRITE as u64;
2310        const SPLICE_MOVE = uapi::FUSE_SPLICE_MOVE as u64;
2311        const SPLICE_READ = uapi::FUSE_SPLICE_READ as u64;
2312        const DO_READDIRPLUS = uapi::FUSE_DO_READDIRPLUS as u64;
2313        const READDIRPLUS_AUTO = uapi::FUSE_READDIRPLUS_AUTO as u64;
2314        const SETXATTR_EXT = uapi::FUSE_SETXATTR_EXT as u64;
2315        const POSIX_ACL = uapi::FUSE_POSIX_ACL as u64;
2316        const PASSTHROUGH = uapi::FUSE_PASSTHROUGH as u64;
2317        const INIT_EXT = uapi::FUSE_INIT_EXT as u64;
2318    }
2319}
2320
2321impl TryFrom<uapi::fuse_init_out> for FuseInitFlags {
2322    type Error = Errno;
2323    fn try_from(init_out: uapi::fuse_init_out) -> Result<Self, Errno> {
2324        let flags = (init_out.flags as u64) | ((init_out.flags2 as u64) << 32);
2325        let unknown_flags = flags & !Self::all().bits();
2326        if unknown_flags != 0 {
2327            track_stub!(
2328                TODO("https://fxbug.dev/322875725"),
2329                "FUSE unknown init flags",
2330                unknown_flags
2331            );
2332            log_warn!("FUSE daemon requested unknown flags in init: {unknown_flags}");
2333        }
2334        Ok(Self::from_bits_truncate(flags))
2335    }
2336}
2337
2338impl FuseInitFlags {
2339    /// Returns the 2 u32 components for these flags. The lowest part is returned first.
2340    fn get_u32_components(&self) -> (u32, u32) {
2341        let flags = (self.bits() & (u32::MAX as u64)) as u32;
2342        let flags2 = (self.bits() >> 32) as u32;
2343        (flags, flags2)
2344    }
2345}
2346
2347#[derive(Clone, Debug)]
2348enum RunningOperationKind {
2349    Access,
2350    Create,
2351    Flush,
2352    Forget,
2353    Fsync {
2354        dir: bool,
2355    },
2356    GetAttr,
2357    Init {
2358        /// The FUSE fs that triggered this operation.
2359        ///
2360        /// `Weak` because the `FuseFs` holds an `Arc<FuseConnection>` which
2361        /// may hold this operation.
2362        fs: Weak<FileSystem>,
2363    },
2364    Interrupt,
2365    GetXAttr {
2366        size: u32,
2367    },
2368    ListXAttr {
2369        size: u32,
2370    },
2371    Lookup,
2372    Mkdir,
2373    Mknod,
2374    Link,
2375    Open {
2376        dir: bool,
2377    },
2378    Poll,
2379    Read,
2380    Readdir {
2381        use_readdirplus: bool,
2382    },
2383    Readlink,
2384    Release {
2385        dir: bool,
2386    },
2387    RemoveXAttr,
2388    Rename,
2389    Rmdir,
2390    Seek,
2391    SetAttr,
2392    SetXAttr,
2393    Statfs,
2394    Symlink,
2395    Unlink,
2396    Write,
2397}
2398
2399impl RunningOperationKind {
2400    fn is_async(&self) -> bool {
2401        matches!(self, Self::Init { .. })
2402    }
2403
2404    fn opcode(&self) -> u32 {
2405        match self {
2406            Self::Access => uapi::fuse_opcode_FUSE_ACCESS,
2407            Self::Create => uapi::fuse_opcode_FUSE_CREATE,
2408            Self::Flush => uapi::fuse_opcode_FUSE_FLUSH,
2409            Self::Forget => uapi::fuse_opcode_FUSE_FORGET,
2410            Self::Fsync { dir } => {
2411                if *dir {
2412                    uapi::fuse_opcode_FUSE_FSYNCDIR
2413                } else {
2414                    uapi::fuse_opcode_FUSE_FSYNC
2415                }
2416            }
2417            Self::GetAttr => uapi::fuse_opcode_FUSE_GETATTR,
2418            Self::GetXAttr { .. } => uapi::fuse_opcode_FUSE_GETXATTR,
2419            Self::Init { .. } => uapi::fuse_opcode_FUSE_INIT,
2420            Self::Interrupt => uapi::fuse_opcode_FUSE_INTERRUPT,
2421            Self::ListXAttr { .. } => uapi::fuse_opcode_FUSE_LISTXATTR,
2422            Self::Lookup => uapi::fuse_opcode_FUSE_LOOKUP,
2423            Self::Mkdir => uapi::fuse_opcode_FUSE_MKDIR,
2424            Self::Mknod => uapi::fuse_opcode_FUSE_MKNOD,
2425            Self::Link => uapi::fuse_opcode_FUSE_LINK,
2426            Self::Open { dir } => {
2427                if *dir {
2428                    uapi::fuse_opcode_FUSE_OPENDIR
2429                } else {
2430                    uapi::fuse_opcode_FUSE_OPEN
2431                }
2432            }
2433            Self::Poll => uapi::fuse_opcode_FUSE_POLL,
2434            Self::Read => uapi::fuse_opcode_FUSE_READ,
2435            Self::Readdir { use_readdirplus } => {
2436                if *use_readdirplus {
2437                    uapi::fuse_opcode_FUSE_READDIRPLUS
2438                } else {
2439                    uapi::fuse_opcode_FUSE_READDIR
2440                }
2441            }
2442            Self::Readlink => uapi::fuse_opcode_FUSE_READLINK,
2443            Self::Release { dir } => {
2444                if *dir {
2445                    uapi::fuse_opcode_FUSE_RELEASEDIR
2446                } else {
2447                    uapi::fuse_opcode_FUSE_RELEASE
2448                }
2449            }
2450            Self::RemoveXAttr => uapi::fuse_opcode_FUSE_REMOVEXATTR,
2451            Self::Rename => uapi::fuse_opcode_FUSE_RENAME2,
2452            Self::Rmdir => uapi::fuse_opcode_FUSE_RMDIR,
2453            Self::Seek => uapi::fuse_opcode_FUSE_LSEEK,
2454            Self::SetAttr => uapi::fuse_opcode_FUSE_SETATTR,
2455            Self::SetXAttr => uapi::fuse_opcode_FUSE_SETXATTR,
2456            Self::Statfs => uapi::fuse_opcode_FUSE_STATFS,
2457            Self::Symlink => uapi::fuse_opcode_FUSE_SYMLINK,
2458            Self::Unlink => uapi::fuse_opcode_FUSE_UNLINK,
2459            Self::Write => uapi::fuse_opcode_FUSE_WRITE,
2460        }
2461    }
2462
2463    fn to_response<T: FromBytes + IntoBytes + Immutable>(buffer: &[u8]) -> T {
2464        let mut result = T::new_zeroed();
2465        let length_to_copy = std::cmp::min(buffer.len(), std::mem::size_of::<T>());
2466        result.as_mut_bytes()[..length_to_copy].copy_from_slice(&buffer[..length_to_copy]);
2467        result
2468    }
2469
2470    fn parse_response(&self, buffer: Vec<u8>) -> Result<FuseResponse, Errno> {
2471        match self {
2472            Self::Access => Ok(FuseResponse::Access(Ok(()))),
2473            Self::Create { .. } => {
2474                Ok(FuseResponse::Create(Self::to_response::<CreateResponse>(&buffer)))
2475            }
2476            Self::GetAttr | Self::SetAttr => {
2477                Ok(FuseResponse::Attr(Self::to_response::<uapi::fuse_attr_out>(&buffer)))
2478            }
2479            Self::GetXAttr { size } | Self::ListXAttr { size } => {
2480                if *size == 0 {
2481                    if buffer.len() < std::mem::size_of::<uapi::fuse_getxattr_out>() {
2482                        return error!(EINVAL);
2483                    }
2484                    let getxattr_out = Self::to_response::<uapi::fuse_getxattr_out>(&buffer);
2485                    Ok(FuseResponse::GetXAttr(ValueOrSize::Size(getxattr_out.size as usize)))
2486                } else {
2487                    Ok(FuseResponse::GetXAttr(FsString::new(buffer).into()))
2488                }
2489            }
2490            Self::Init { .. } => {
2491                Ok(FuseResponse::Init(Self::to_response::<uapi::fuse_init_out>(&buffer)))
2492            }
2493            Self::Lookup | Self::Mkdir | Self::Mknod | Self::Link | Self::Symlink => {
2494                Ok(FuseResponse::Entry(Self::to_response::<uapi::fuse_entry_out>(&buffer)))
2495            }
2496            Self::Open { .. } => {
2497                Ok(FuseResponse::Open(Self::to_response::<uapi::fuse_open_out>(&buffer)))
2498            }
2499            Self::Poll => Ok(FuseResponse::Poll(Self::to_response::<uapi::fuse_poll_out>(&buffer))),
2500            Self::Read | Self::Readlink => Ok(FuseResponse::Read(buffer)),
2501            Self::Readdir { use_readdirplus, .. } => {
2502                let mut result = vec![];
2503                let mut slice = &buffer[..];
2504                while !slice.is_empty() {
2505                    // If using READDIRPLUS, the data starts with the entry.
2506                    let entry = if *use_readdirplus {
2507                        if slice.len() < std::mem::size_of::<uapi::fuse_entry_out>() {
2508                            return error!(EINVAL);
2509                        }
2510                        let entry = Self::to_response::<uapi::fuse_entry_out>(slice);
2511                        slice = &slice[std::mem::size_of::<uapi::fuse_entry_out>()..];
2512                        Some(entry)
2513                    } else {
2514                        None
2515                    };
2516                    // The next item is the dirent.
2517                    if slice.len() < std::mem::size_of::<uapi::fuse_dirent>() {
2518                        return error!(EINVAL);
2519                    }
2520                    let dirent = Self::to_response::<uapi::fuse_dirent>(slice);
2521                    // And it ends with the name.
2522                    slice = &slice[std::mem::size_of::<uapi::fuse_dirent>()..];
2523                    let namelen = dirent.namelen as usize;
2524                    if slice.len() < namelen {
2525                        return error!(EINVAL);
2526                    }
2527                    let name = FsString::from(&slice[..namelen]);
2528                    result.push((dirent, name, entry));
2529                    let skipped = round_up_to_increment(namelen, 8)?;
2530                    if slice.len() < skipped {
2531                        return error!(EINVAL);
2532                    }
2533                    slice = &slice[skipped..];
2534                }
2535                Ok(FuseResponse::Readdir(result))
2536            }
2537            Self::Flush
2538            | Self::Fsync { .. }
2539            | Self::Release { .. }
2540            | Self::RemoveXAttr
2541            | Self::Rename
2542            | Self::Rmdir
2543            | Self::SetXAttr
2544            | Self::Unlink => Ok(FuseResponse::None),
2545            Self::Statfs => {
2546                Ok(FuseResponse::Statfs(Self::to_response::<uapi::fuse_statfs_out>(&buffer)))
2547            }
2548            Self::Seek => {
2549                Ok(FuseResponse::Seek(Self::to_response::<uapi::fuse_lseek_out>(&buffer)))
2550            }
2551            Self::Write => {
2552                Ok(FuseResponse::Write(Self::to_response::<uapi::fuse_write_out>(&buffer)))
2553            }
2554            Self::Interrupt | Self::Forget => {
2555                panic!("Response for operation without one");
2556            }
2557        }
2558    }
2559
2560    /// Handles an error from the userspace daemon.
2561    ///
2562    /// Given the `errno` returned by the userspace daemon, returns the response the caller should
2563    /// see. This can also update the `OperationState` to allow shortcircuit on future requests.
2564    fn handle_error(
2565        &self,
2566        state: &mut OperationsState,
2567        errno: Errno,
2568    ) -> Result<FuseResponse, Errno> {
2569        match self {
2570            Self::Access if errno == ENOSYS => {
2571                // Per libfuse, ENOSYS is interpreted as a "permanent success"
2572                // so we don't need to do anything further, including performing
2573                // the default/standard file permission checks like we do
2574                // when the `default_permissions` mount option is set.
2575                const UNIMPLEMENTED_ACCESS_RESPONSE: Result<FuseResponse, Errno> =
2576                    Ok(FuseResponse::Access(Ok(())));
2577                state.insert(self.opcode(), UNIMPLEMENTED_ACCESS_RESPONSE);
2578                UNIMPLEMENTED_ACCESS_RESPONSE
2579            }
2580            Self::Flush if errno == ENOSYS => {
2581                state.insert(self.opcode(), Ok(FuseResponse::None));
2582                Ok(FuseResponse::None)
2583            }
2584            Self::Seek if errno == ENOSYS => {
2585                state.insert(self.opcode(), Err(errno.clone()));
2586                Err(errno)
2587            }
2588            Self::Poll if errno == ENOSYS => {
2589                let response = FuseResponse::Poll(uapi::fuse_poll_out {
2590                    revents: (FdEvents::POLLIN | FdEvents::POLLOUT).bits(),
2591                    padding: 0,
2592                });
2593                state.insert(self.opcode(), Ok(response.clone()));
2594                Ok(response)
2595            }
2596            _ => Err(errno),
2597        }
2598    }
2599}
2600
2601#[derive(Debug)]
2602enum FuseOperation {
2603    Access {
2604        mask: u32,
2605    },
2606    Create(uapi::fuse_create_in, FsString),
2607    Flush(uapi::fuse_open_out),
2608    Forget(uapi::fuse_forget_in),
2609    Fsync {
2610        fh: u64,
2611        is_dir: bool,
2612        datasync: bool,
2613    },
2614    GetAttr,
2615    Init {
2616        /// The FUSE fs that triggered this operation.
2617        ///
2618        /// `Weak` because the `FuseFs` holds an `Arc<FuseConnection>` which
2619        /// may hold this operation.
2620        fs: Weak<FileSystem>,
2621    },
2622    Interrupt {
2623        /// Identifier of the operation to interrupt
2624        unique_id: u64,
2625    },
2626    GetXAttr {
2627        getxattr_in: uapi::fuse_getxattr_in,
2628        /// Name of the attribute
2629        name: FsString,
2630    },
2631    ListXAttr(uapi::fuse_getxattr_in),
2632    Lookup {
2633        /// Name of the entry to lookup
2634        name: FsString,
2635    },
2636    Mkdir {
2637        mkdir_in: uapi::fuse_mkdir_in,
2638        /// Name of the entry to create
2639        name: FsString,
2640    },
2641    Mknod {
2642        mknod_in: uapi::fuse_mknod_in,
2643        /// Name of the node to create
2644        name: FsString,
2645    },
2646    Link {
2647        link_in: uapi::fuse_link_in,
2648        /// Name of the link to create
2649        name: FsString,
2650    },
2651    Open {
2652        flags: OpenFlags,
2653        mode: FileMode,
2654    },
2655    Poll(uapi::fuse_poll_in),
2656    Read(uapi::fuse_read_in),
2657    Readdir {
2658        read_in: uapi::fuse_read_in,
2659        /// Whether to use the READDIRPLUS api
2660        use_readdirplus: bool,
2661    },
2662    Readlink,
2663    Release(uapi::fuse_open_out),
2664    ReleaseDir(uapi::fuse_open_out),
2665    RemoveXAttr {
2666        /// Name of the attribute
2667        name: FsString,
2668    },
2669    Rename {
2670        old_name: FsString,
2671        new_dir: u64,
2672        new_name: FsString,
2673    },
2674    Rmdir {
2675        name: FsString,
2676    },
2677    Seek(uapi::fuse_lseek_in),
2678    SetAttr(uapi::fuse_setattr_in),
2679    SetXAttr {
2680        setxattr_in: uapi::fuse_setxattr_in,
2681        /// Indicates if userspace supports the, most-recent/extended variant of
2682        /// `fuse_setxattr_in`.
2683        is_ext: bool,
2684        /// Name of the attribute
2685        name: FsString,
2686        /// Value of the attribute
2687        value: FsString,
2688    },
2689    Statfs,
2690    Symlink {
2691        /// Target of the link
2692        target: FsString,
2693        /// Name of the link
2694        name: FsString,
2695    },
2696    Unlink {
2697        /// Name of the file to unlink
2698        name: FsString,
2699    },
2700    Write {
2701        write_in: uapi::fuse_write_in,
2702        // Content to write
2703        content: Vec<u8>,
2704    },
2705}
2706
2707#[derive(Clone, Debug)]
2708enum FuseResponse {
2709    Access(Result<(), Errno>),
2710    Attr(uapi::fuse_attr_out),
2711    Create(CreateResponse),
2712    Entry(uapi::fuse_entry_out),
2713    GetXAttr(ValueOrSize<FsString>),
2714    Init(uapi::fuse_init_out),
2715    Open(uapi::fuse_open_out),
2716    Poll(uapi::fuse_poll_out),
2717    Read(
2718        // Content read
2719        Vec<u8>,
2720    ),
2721    Seek(uapi::fuse_lseek_out),
2722    Readdir(Vec<(uapi::fuse_dirent, FsString, Option<uapi::fuse_entry_out>)>),
2723    Statfs(uapi::fuse_statfs_out),
2724    Write(uapi::fuse_write_out),
2725    None,
2726}
2727
2728impl FuseResponse {
2729    fn entry(&self) -> Option<&uapi::fuse_entry_out> {
2730        if let Self::Entry(entry) = self { Some(entry) } else { None }
2731    }
2732}
2733
2734#[repr(C)]
2735#[derive(Clone, Debug, KnownLayout, FromBytes, IntoBytes, Immutable)]
2736struct CreateResponse {
2737    entry: uapi::fuse_entry_out,
2738    open: uapi::fuse_open_out,
2739}
2740
2741static_assertions::const_assert_eq!(
2742    std::mem::offset_of!(CreateResponse, open),
2743    std::mem::size_of::<uapi::fuse_entry_out>()
2744);
2745
2746impl FuseOperation {
2747    fn serialize(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
2748        match self {
2749            Self::Access { mask } => {
2750                let message = uapi::fuse_access_in { mask: *mask, padding: 0 };
2751                data.write_all(message.as_bytes())
2752            }
2753            Self::Create(create_in, name) => {
2754                Ok(data.write_all(create_in.as_bytes())? + Self::write_null_terminated(data, name)?)
2755            }
2756            Self::Flush(open_in) => {
2757                let message =
2758                    uapi::fuse_flush_in { fh: open_in.fh, unused: 0, padding: 0, lock_owner: 0 };
2759                data.write_all(message.as_bytes())
2760            }
2761            Self::Forget(forget_in) => data.write_all(forget_in.as_bytes()),
2762            Self::Fsync { fh, datasync, .. } => {
2763                let fsync_flags = if *datasync { uapi::FUSE_FSYNC_FDATASYNC } else { 0 };
2764                let message = uapi::fuse_fsync_in { fh: *fh, fsync_flags, padding: 0 };
2765                data.write_all(message.as_bytes())
2766            }
2767            Self::GetAttr | Self::Readlink | Self::Statfs => Ok(0),
2768            Self::GetXAttr { getxattr_in, name } => {
2769                let mut len = data.write_all(getxattr_in.as_bytes())?;
2770                len += Self::write_null_terminated(data, name)?;
2771                Ok(len)
2772            }
2773            Self::Init { .. } => {
2774                let (flags, flags2) = FuseInitFlags::all().get_u32_components();
2775                let message = uapi::fuse_init_in {
2776                    major: uapi::FUSE_KERNEL_VERSION,
2777                    minor: uapi::FUSE_KERNEL_MINOR_VERSION,
2778                    flags,
2779                    flags2,
2780                    ..Default::default()
2781                };
2782                data.write_all(message.as_bytes())
2783            }
2784            Self::Interrupt { unique_id } => {
2785                let message = uapi::fuse_interrupt_in { unique: *unique_id };
2786                data.write_all(message.as_bytes())
2787            }
2788            Self::ListXAttr(getxattr_in) => data.write_all(getxattr_in.as_bytes()),
2789            Self::Lookup { name } => Self::write_null_terminated(data, name),
2790            Self::Open { flags, .. } => {
2791                let message = uapi::fuse_open_in { flags: flags.bits(), open_flags: 0 };
2792                data.write_all(message.as_bytes())
2793            }
2794            Self::Poll(poll_in) => data.write_all(poll_in.as_bytes()),
2795            Self::Mkdir { mkdir_in, name } => {
2796                let mut len = data.write_all(mkdir_in.as_bytes())?;
2797                len += Self::write_null_terminated(data, name)?;
2798                Ok(len)
2799            }
2800            Self::Mknod { mknod_in, name } => {
2801                let mut len = data.write_all(mknod_in.as_bytes())?;
2802                len += Self::write_null_terminated(data, name)?;
2803                Ok(len)
2804            }
2805            Self::Link { link_in, name } => {
2806                let mut len = data.write_all(link_in.as_bytes())?;
2807                len += Self::write_null_terminated(data, name)?;
2808                Ok(len)
2809            }
2810            Self::Read(read_in) | Self::Readdir { read_in, .. } => {
2811                data.write_all(read_in.as_bytes())
2812            }
2813            Self::Release(open_out) | Self::ReleaseDir(open_out) => {
2814                let message = uapi::fuse_release_in {
2815                    fh: open_out.fh,
2816                    flags: 0,
2817                    release_flags: 0,
2818                    lock_owner: 0,
2819                };
2820                data.write_all(message.as_bytes())
2821            }
2822            Self::RemoveXAttr { name } => Self::write_null_terminated(data, name),
2823            Self::Rename { old_name, new_dir, new_name } => {
2824                Ok(data.write_all(
2825                    uapi::fuse_rename2_in { newdir: *new_dir, flags: 0, padding: 0 }.as_bytes(),
2826                )? + Self::write_null_terminated(data, old_name)?
2827                    + Self::write_null_terminated(data, new_name)?)
2828            }
2829            Self::Seek(seek_in) => data.write_all(seek_in.as_bytes()),
2830            Self::SetAttr(setattr_in) => data.write_all(setattr_in.as_bytes()),
2831            Self::SetXAttr { setxattr_in, is_ext, name, value } => {
2832                let header =
2833                    if *is_ext { setxattr_in.as_bytes() } else { &setxattr_in.as_bytes()[..8] };
2834                let mut len = data.write_all(header)?;
2835                len += Self::write_null_terminated(data, name)?;
2836                len += data.write_all(value.as_bytes())?;
2837                Ok(len)
2838            }
2839            Self::Symlink { target, name } => {
2840                let mut len = Self::write_null_terminated(data, name)?;
2841                len += Self::write_null_terminated(data, target)?;
2842                Ok(len)
2843            }
2844            Self::Rmdir { name } | Self::Unlink { name } => Self::write_null_terminated(data, name),
2845            &Self::Write { mut write_in, ref content } => {
2846                let mut write_in_size = write_in.size as usize;
2847                assert!(write_in_size == content.len());
2848                if write_in_size + write_in.as_bytes().len() > data.available() {
2849                    write_in_size = data.available() - write_in.as_bytes().len();
2850                    write_in.size = write_in_size as u32;
2851                }
2852                let mut len = data.write_all(write_in.as_bytes())?;
2853                len += data.write_all(&content[..write_in_size])?;
2854                Ok(len)
2855            }
2856        }
2857    }
2858
2859    fn write_null_terminated(
2860        data: &mut dyn OutputBuffer,
2861        content: &Vec<u8>,
2862    ) -> Result<usize, Errno> {
2863        let mut len = data.write_all(content.as_bytes())?;
2864        len += data.write_all(&[0])?;
2865        Ok(len)
2866    }
2867
2868    fn opcode(&self) -> u32 {
2869        match self {
2870            Self::Access { .. } => uapi::fuse_opcode_FUSE_ACCESS,
2871            Self::Create { .. } => uapi::fuse_opcode_FUSE_CREATE,
2872            Self::Flush(_) => uapi::fuse_opcode_FUSE_FLUSH,
2873            Self::Forget(_) => uapi::fuse_opcode_FUSE_FORGET,
2874            Self::Fsync { is_dir, .. } => {
2875                if *is_dir {
2876                    uapi::fuse_opcode_FUSE_FSYNCDIR
2877                } else {
2878                    uapi::fuse_opcode_FUSE_FSYNC
2879                }
2880            }
2881            Self::GetAttr => uapi::fuse_opcode_FUSE_GETATTR,
2882            Self::GetXAttr { .. } => uapi::fuse_opcode_FUSE_GETXATTR,
2883            Self::Init { .. } => uapi::fuse_opcode_FUSE_INIT,
2884            Self::Interrupt { .. } => uapi::fuse_opcode_FUSE_INTERRUPT,
2885            Self::ListXAttr(_) => uapi::fuse_opcode_FUSE_LISTXATTR,
2886            Self::Lookup { .. } => uapi::fuse_opcode_FUSE_LOOKUP,
2887            Self::Mkdir { .. } => uapi::fuse_opcode_FUSE_MKDIR,
2888            Self::Mknod { .. } => uapi::fuse_opcode_FUSE_MKNOD,
2889            Self::Link { .. } => uapi::fuse_opcode_FUSE_LINK,
2890            Self::Open { flags, mode } => {
2891                if mode.is_dir() || flags.contains(OpenFlags::DIRECTORY) {
2892                    uapi::fuse_opcode_FUSE_OPENDIR
2893                } else {
2894                    uapi::fuse_opcode_FUSE_OPEN
2895                }
2896            }
2897            Self::Poll(_) => uapi::fuse_opcode_FUSE_POLL,
2898            Self::Read(_) => uapi::fuse_opcode_FUSE_READ,
2899            Self::Readdir { use_readdirplus, .. } => {
2900                if *use_readdirplus {
2901                    uapi::fuse_opcode_FUSE_READDIRPLUS
2902                } else {
2903                    uapi::fuse_opcode_FUSE_READDIR
2904                }
2905            }
2906            Self::Readlink => uapi::fuse_opcode_FUSE_READLINK,
2907            Self::Release(_) => uapi::fuse_opcode_FUSE_RELEASE,
2908            Self::ReleaseDir(_) => uapi::fuse_opcode_FUSE_RELEASEDIR,
2909            Self::RemoveXAttr { .. } => uapi::fuse_opcode_FUSE_REMOVEXATTR,
2910            Self::Rename { .. } => uapi::fuse_opcode_FUSE_RENAME2,
2911            Self::Rmdir { .. } => uapi::fuse_opcode_FUSE_RMDIR,
2912            Self::Seek(_) => uapi::fuse_opcode_FUSE_LSEEK,
2913            Self::SetAttr(_) => uapi::fuse_opcode_FUSE_SETATTR,
2914            Self::SetXAttr { .. } => uapi::fuse_opcode_FUSE_SETXATTR,
2915            Self::Statfs => uapi::fuse_opcode_FUSE_STATFS,
2916            Self::Symlink { .. } => uapi::fuse_opcode_FUSE_SYMLINK,
2917            Self::Unlink { .. } => uapi::fuse_opcode_FUSE_UNLINK,
2918            Self::Write { .. } => uapi::fuse_opcode_FUSE_WRITE,
2919        }
2920    }
2921
2922    fn as_running(&self) -> RunningOperationKind {
2923        match self {
2924            Self::Access { .. } => RunningOperationKind::Access,
2925            Self::Create { .. } => RunningOperationKind::Create,
2926            Self::Flush(_) => RunningOperationKind::Flush,
2927            Self::Forget(_) => RunningOperationKind::Forget,
2928            Self::Fsync { is_dir, .. } => RunningOperationKind::Fsync { dir: *is_dir },
2929            Self::GetAttr => RunningOperationKind::GetAttr,
2930            Self::GetXAttr { getxattr_in, .. } => {
2931                RunningOperationKind::GetXAttr { size: getxattr_in.size }
2932            }
2933            Self::Init { fs } => RunningOperationKind::Init { fs: fs.clone() },
2934            Self::Interrupt { .. } => RunningOperationKind::Interrupt,
2935            Self::ListXAttr(getxattr_in) => {
2936                RunningOperationKind::ListXAttr { size: getxattr_in.size }
2937            }
2938            Self::Lookup { .. } => RunningOperationKind::Lookup,
2939            Self::Mkdir { .. } => RunningOperationKind::Mkdir,
2940            Self::Mknod { .. } => RunningOperationKind::Mknod,
2941            Self::Link { .. } => RunningOperationKind::Link,
2942            Self::Open { flags, mode } => RunningOperationKind::Open {
2943                dir: mode.is_dir() || flags.contains(OpenFlags::DIRECTORY),
2944            },
2945            Self::Poll(_) => RunningOperationKind::Poll,
2946            Self::Read(_) => RunningOperationKind::Read,
2947            Self::Readdir { use_readdirplus, .. } => {
2948                RunningOperationKind::Readdir { use_readdirplus: *use_readdirplus }
2949            }
2950            Self::Readlink => RunningOperationKind::Readlink,
2951            Self::Release(_) => RunningOperationKind::Release { dir: false },
2952            Self::ReleaseDir(_) => RunningOperationKind::Release { dir: true },
2953            Self::RemoveXAttr { .. } => RunningOperationKind::RemoveXAttr,
2954            Self::Rename { .. } => RunningOperationKind::Rename,
2955            Self::Rmdir { .. } => RunningOperationKind::Rmdir,
2956            Self::Seek(_) => RunningOperationKind::Seek,
2957            Self::SetAttr(_) => RunningOperationKind::SetAttr,
2958            Self::SetXAttr { .. } => RunningOperationKind::SetXAttr,
2959            Self::Statfs => RunningOperationKind::Statfs,
2960            Self::Symlink { .. } => RunningOperationKind::Symlink,
2961            Self::Unlink { .. } => RunningOperationKind::Unlink,
2962            Self::Write { .. } => RunningOperationKind::Write,
2963        }
2964    }
2965
2966    fn len(&self) -> usize {
2967        #[derive(Debug, Default)]
2968        struct CountingOutputBuffer {
2969            written: usize,
2970        }
2971
2972        impl Buffer for CountingOutputBuffer {
2973            fn segments_count(&self) -> Result<usize, Errno> {
2974                panic!("Should not be called");
2975            }
2976
2977            fn peek_each_segment(
2978                &mut self,
2979                _callback: &mut PeekBufferSegmentsCallback<'_>,
2980            ) -> Result<(), Errno> {
2981                panic!("Should not be called");
2982            }
2983        }
2984
2985        impl OutputBuffer for CountingOutputBuffer {
2986            fn available(&self) -> usize {
2987                usize::MAX
2988            }
2989
2990            fn bytes_written(&self) -> usize {
2991                self.written
2992            }
2993
2994            fn zero(&mut self) -> Result<usize, Errno> {
2995                panic!("Should not be called");
2996            }
2997
2998            fn write_each(
2999                &mut self,
3000                _callback: &mut OutputBufferCallback<'_>,
3001            ) -> Result<usize, Errno> {
3002                panic!("Should not be called.");
3003            }
3004
3005            fn write_all(&mut self, buffer: &[u8]) -> Result<usize, Errno> {
3006                self.written += buffer.len();
3007                Ok(buffer.len())
3008            }
3009
3010            unsafe fn advance(&mut self, _length: usize) -> Result<(), Errno> {
3011                panic!("Should not be called.");
3012            }
3013        }
3014
3015        let mut counting_output_buffer = CountingOutputBuffer::default();
3016        self.serialize(&mut counting_output_buffer).expect("Serialization should not fail");
3017        counting_output_buffer.written
3018    }
3019
3020    fn has_response(&self) -> bool {
3021        !matches!(self, Self::Interrupt { .. } | Self::Forget(_))
3022    }
3023
3024    fn is_async(&self) -> bool {
3025        matches!(self, Self::Init { .. })
3026    }
3027}