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