You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/10/26 07:43:20 UTC

(opendal-yinyang) branch xuanwo/linux-fuse-foundation updated: fix: bridge FUSE inode newtypes to the inode table

This is an automated email from the ASF dual-hosted git repository.

Xuanwo pushed a commit to branch xuanwo/linux-fuse-foundation
in repository https://gitbox.apache.org/repos/asf/opendal-yinyang.git


The following commit(s) were added to refs/heads/xuanwo/linux-fuse-foundation by this push:
     new 9e3fe55  fix: bridge FUSE inode newtypes to the inode table
9e3fe55 is described below

commit 9e3fe555f9e0e50e9d24a44dbe53eab687af91aa
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Mon Oct 26 15:42:27 2026 +0800

    fix: bridge FUSE inode newtypes to the inode table
    
    fuser represents inode numbers with the `INodeNo` newtype while the
    volume-lifetime map keys plain u64 values. Convert at the adapter
    boundary so the root constant, table lookups, and kernel reference
    counters have matching types, and release the inode-table guard before
    reacquiring it in `resolve_entry` to avoid a cached-readdir deadlock.
    
    Co-authored-by: Chojan Shang <ps...@apache.org>
---
 src/fuse/frontend.rs | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/fuse/frontend.rs b/src/fuse/frontend.rs
index 903655b..9babe9d 100644
--- a/src/fuse/frontend.rs
+++ b/src/fuse/frontend.rs
@@ -42,7 +42,7 @@
 //! exit is the actual point where remaining tasks are dropped.
 
 use super::attrs::{ATTR_TTL, DIRECTORY_SIZE, attribute};
-use super::inode::{CachedInfo, InodeTable, ROOT_INODE};
+use super::inode::{CachedInfo, InodeTable};
 use crate::mount::{Mount, MountFile};
 use fuser::{
     AccessFlags, BsdFileFlags, FileAttr, FileHandle, FileType, Filesystem, FopenFlags, Generation,
@@ -122,19 +122,19 @@ impl Inner {
         if let Some(info) = info {
             inodes.cache(id, info);
         }
-        inodes.inode(id).map_err(|_| fuser::Errno::EIO)
+        inodes.inode(id).map(INodeNo).map_err(|_| fuser::Errno::EIO)
     }
 
     fn node(&self, ino: INodeNo) -> Option<NodeId> {
-        guard(&self.inodes).node(ino)
+        guard(&self.inodes).node(ino.0)
     }
 
     fn remember_lookup(&self, ino: INodeNo) {
-        guard(&self.inodes).remember_lookup(ino);
+        guard(&self.inodes).remember_lookup(ino.0);
     }
 
     fn forget(&self, ino: INodeNo, count: u64) {
-        guard(&self.inodes).forget(ino, count);
+        guard(&self.inodes).forget(ino.0, count);
     }
 
     fn open_file(&self, fh: FileHandle) -> Option<Arc<OpenFile>> {
@@ -187,7 +187,7 @@ impl Inner {
     /// `fstat` and read bytes describe the same pinned version.
     async fn handle_attr(&self, open: &OpenFile) -> Result<FileAttr, fuser::Errno> {
         let status = open.file.status().await.map_err(|e| runtime_errno(&e))?;
-        let cached = guard(&self.inodes).cached(open.node);
+        let cached = { guard(&self.inodes).cached(open.node) };
         let ino = self.inode_for(open.node, None)?;
         Ok(attribute(
             ino,
@@ -315,7 +315,7 @@ impl Inner {
                 Err(errno) => return reply.error(errno),
             },
             // The root's "." and ".." both denote itself.
-            None => ROOT_INODE,
+            None => INodeNo::ROOT,
         };
         guard(&self.inodes).cache(
             id,
@@ -423,7 +423,10 @@ impl Inner {
         snapshot: &Snapshot,
         id: NodeId,
     ) -> Result<(INodeNo, FileType), fuser::Errno> {
-        if let Some(info) = guard(&self.inodes).cached(id) {
+        // Release the inode-table guard before `inode_for` reacquires it;
+        // an `if let` scrutinee would keep the temporary guard alive.
+        let cached = { guard(&self.inodes).cached(id) };
+        if let Some(info) = cached {
             let ino = self.inode_for(id, None)?;
             return Ok((ino, entry_kind(info.directory)));
         }