Skip to content

Commit 48e7f75

Browse files
eryugeybergwolf
authored andcommitted
passthroughfs: convert MultiKeyBTreeMap to InodeStore for InodeMap
The implementation of MultiKeyBTreeMap is for generic usage and may not be efficient in passthroughfs, e.g. it has a vector in alt key and when InodeMap grows, it triggers many memory re-allocations, and hits performance. So introduce application-specific InodeStore struct to replace the generic MultiKeyBTreeMap. This follows virtiofsd-rs commit 4d27d3ec772f ("passthrough: Use application-specific inode storage") Signed-off-by: Eryu Guan <[email protected]>
1 parent f3a25b8 commit 48e7f75

File tree

3 files changed

+128
-455
lines changed

3 files changed

+128
-455
lines changed

src/passthrough/inode_store.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Use of this source code is governed by a BSD-style license that can be
2+
// found in the LICENSE-BSD-3-Clause file.
3+
4+
use std::collections::BTreeMap;
5+
use std::sync::Arc;
6+
7+
use super::file_handle::FileHandle;
8+
use super::{FileOrHandle, Inode, InodeAltKey, InodeData};
9+
10+
#[derive(Default)]
11+
pub struct InodeStore {
12+
data: BTreeMap<Inode, Arc<InodeData>>,
13+
by_ids: BTreeMap<InodeAltKey, Inode>,
14+
by_handle: BTreeMap<Arc<FileHandle>, Inode>,
15+
}
16+
17+
impl InodeStore {
18+
pub fn insert(&mut self, data: Arc<InodeData>) {
19+
self.by_ids.insert(data.altkey, data.inode);
20+
if let FileOrHandle::Handle(handle) = &data.file_or_handle {
21+
self.by_handle.insert(handle.clone(), data.inode);
22+
}
23+
self.data.insert(data.inode, data);
24+
}
25+
26+
pub fn remove(&mut self, inode: &Inode) -> Option<Arc<InodeData>> {
27+
let data = self.data.remove(inode);
28+
if let Some(data) = data.as_ref() {
29+
if let FileOrHandle::Handle(handle) = &data.file_or_handle {
30+
self.by_handle.remove(handle);
31+
}
32+
self.by_ids.remove(&data.altkey);
33+
}
34+
data
35+
}
36+
37+
pub fn clear(&mut self) {
38+
self.data.clear();
39+
self.by_handle.clear();
40+
self.by_ids.clear();
41+
}
42+
43+
pub fn get(&self, inode: &Inode) -> Option<&Arc<InodeData>> {
44+
self.data.get(inode)
45+
}
46+
47+
pub fn get_by_ids(&self, ids: &InodeAltKey) -> Option<&Arc<InodeData>> {
48+
// safe to unwrap, inode must be in data map if found by ids, otherwise unwrap on
49+
// corruption.
50+
self.inode_by_ids(ids).map(|inode| self.get(inode).unwrap())
51+
}
52+
53+
pub fn get_by_handle(&self, handle: &FileHandle) -> Option<&Arc<InodeData>> {
54+
// safe to unwrap, inode must be in data map if found by ids, otherwise unwrap on
55+
// corruption.
56+
self.inode_by_handle(handle)
57+
.map(|inode| self.get(inode).unwrap())
58+
}
59+
60+
pub fn inode_by_ids(&self, ids: &InodeAltKey) -> Option<&Inode> {
61+
self.by_ids.get(ids)
62+
}
63+
64+
pub fn inode_by_handle(&self, handle: &FileHandle) -> Option<&Inode> {
65+
self.by_handle.get(handle)
66+
}
67+
}

0 commit comments

Comments
 (0)