Skip to content

Commit

Permalink
implement stable unique inode for passthroughfs
Browse files Browse the repository at this point in the history
In the current passthroughfs implementation, temporary inodes are allocated and then stored in memory,
But a FORGET request causes the inode to be removed from memory, new anodes are reassigned,
resulting in the instability of the inodes of a file. this PR implements a stable inode,
Limited by the current implementation limitations of VFS, Host inode + mnt + dev needs to be controlled in 56bit,
and it is not supported beyond the range.

Signed-off-by: zyfjeff <[email protected]>
  • Loading branch information
zyfjeff committed May 10, 2023
1 parent 2d286b2 commit 30d9ea3
Show file tree
Hide file tree
Showing 3 changed files with 338 additions and 18 deletions.
28 changes: 18 additions & 10 deletions src/passthrough/inode_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,15 @@ impl InodeStore {
self.data.insert(data.inode, data);
}

pub fn remove(&mut self, inode: &Inode) -> Option<Arc<InodeData>> {
pub fn remove(&mut self, inode: &Inode, remove_data_only: bool) -> Option<Arc<InodeData>> {
let data = self.data.remove(inode);
if remove_data_only {
// Don't remove by_ids and by_handle, we need use it to store inode
// record the mapping of inodes using these two structures to ensure
// that the same files always use the same inode
return data;
}

if let Some(data) = data.as_ref() {
if let FileOrHandle::Handle(handle) = &data.file_or_handle {
self.by_handle.remove(handle);
Expand All @@ -45,16 +52,17 @@ impl InodeStore {
}

pub fn get_by_ids(&self, ids: &InodeAltKey) -> Option<&Arc<InodeData>> {
// safe to unwrap, inode must be in data map if found by ids, otherwise unwrap on
// corruption.
self.inode_by_ids(ids).map(|inode| self.get(inode).unwrap())
match self.inode_by_ids(ids) {
Some(inode) => self.get(inode),
None => None,
}
}

pub fn get_by_handle(&self, handle: &FileHandle) -> Option<&Arc<InodeData>> {
// safe to unwrap, inode must be in data map if found by ids, otherwise unwrap on
// corruption.
self.inode_by_handle(handle)
.map(|inode| self.get(inode).unwrap())
match self.inode_by_handle(handle) {
Some(inode) => self.get(inode),
None => None,
}
}

pub fn inode_by_ids(&self, ids: &InodeAltKey) -> Option<&Inode> {
Expand Down Expand Up @@ -176,10 +184,10 @@ mod test {
assert_eq!(m.get_by_ids(&ids2).unwrap(), &data2);

// remove non-present key
assert!(m.remove(&1).is_none());
assert!(m.remove(&1, false).is_none());

// remove present key, return its value
assert_eq!(m.remove(&inode1).unwrap(), data1.clone());
assert_eq!(m.remove(&inode1, false).unwrap(), data1.clone());
assert!(m.get(&inode1).is_none());
assert!(m.get_by_ids(&ids1).is_none());
assert_eq!(m.get(&inode2).unwrap(), &data2);
Expand Down
Loading

0 comments on commit 30d9ea3

Please sign in to comment.