Skip to content

Commit c093957

Browse files
committed
add notify_inval_inode and extend get_rootfs to return fs_idx for unmount
- Add notify_inval_inode method to fusedev to explicitly invalidate inode caches in the kernel, ensuring cache coherence when backend files change outside guest VFS. - Extend get_rootfs to return both Arc<BackFileSystem> and u8 fs_idx. This is necessary for correct unmount handling and cache invalidation. The implementation follows fuse kernel and libfuse protocols and maintains compatibility with existing patterns like notify_inval_entry. Signed-off-by: sidneychang <[email protected]>
1 parent 22cf6a6 commit c093957

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

src/api/server/sync_io.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,36 @@ impl<F: FileSystem + Sync> Server<F> {
5757
.map_err(Error::FailedToWrite)?;
5858
buffer_writer.commit(None).map_err(Error::InvalidMessage)
5959
}
60+
/// Notify the kernel that an inode's data has been invalidated.
61+
#[cfg(feature = "fusedev")]
62+
pub fn notify_inval_inode<S: BitmapSlice>(
63+
&self,
64+
mut w: FuseDevWriter<'_, S>,
65+
ino: u64,
66+
off: u64,
67+
len: u64,
68+
) -> Result<usize> {
69+
let mut buffer_writer = w.split_at(0).map_err(Error::FailedToSplitWriter)?;
70+
let mut header = OutHeader::default();
71+
let mut inode = NotifyInvalInodeOut::default();
72+
73+
header.unique = 0;
74+
header.error = NotifyOpcode::InvalInode as i32;
75+
header.len = std::mem::size_of::<OutHeader>() as u32
76+
+ std::mem::size_of::<NotifyInvalInodeOut>() as u32;
6077

78+
inode.ino = ino;
79+
inode.off = off as i64;
80+
inode.len = len as i64;
81+
82+
buffer_writer
83+
.write_obj(header)
84+
.map_err(Error::FailedToWrite)?;
85+
buffer_writer
86+
.write_obj(inode)
87+
.map_err(Error::FailedToWrite)?;
88+
buffer_writer.commit(None).map_err(Error::InvalidMessage)
89+
}
6190
#[cfg(feature = "fusedev")]
6291
/// Send a resend notification message to the kernel via FUSE. This function should be invoked as part of
6392
/// the crash recovery routine. Given that FUSE initialization does not occur again during recovery,

src/api/vfs/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,8 @@ impl Vfs {
499499
Ok((inode, parent))
500500
}
501501

502-
/// Get the mounted backend file system alongside the path if there's one.
503-
pub fn get_rootfs(&self, path: &str) -> VfsResult<Option<Arc<BackFileSystem>>> {
502+
/// Get the mounted backend file system and its fs_idx alongside the path if there's one.
503+
pub fn get_rootfs(&self, path: &str) -> VfsResult<Option<(Arc<BackFileSystem>, u8)>> {
504504
// Serialize mount operations. Do not expect poisoned lock here.
505505
let _guard = self.lock.lock().unwrap();
506506
let inode = match self.root.path_walk(path).map_err(VfsError::PathWalk)? {
@@ -509,9 +509,10 @@ impl Vfs {
509509
};
510510

511511
if let Some(mnt) = self.mountpoints.load().get(&inode) {
512-
Ok(Some(self.get_fs_by_idx(mnt.fs_idx).map_err(|e| {
513-
VfsError::NotFound(format!("fs index {}, {:?}", mnt.fs_idx, e))
514-
})?))
512+
let fs = self
513+
.get_fs_by_idx(mnt.fs_idx)
514+
.map_err(|e| VfsError::NotFound(format!("fs index {}, {:?}", mnt.fs_idx, e)))?;
515+
Ok(Some((fs, mnt.fs_idx)))
515516
} else {
516517
// Pseudo fs dir inode exists, but that no backend is ever mounted
517518
// is a normal case.

0 commit comments

Comments
 (0)