starnix_core/vfs/
fs_node_cache.rs1use crate::vfs::{FsNode, FsNodeHandle, WeakFsNodeHandle};
6use fuchsia_rcu::RcuReadScope;
7use starnix_lifecycle::AtomicCounter;
8use starnix_rcu::rcu_hash_map::{Entry, RcuHashMap};
9use starnix_uapi::errors::Errno;
10use starnix_uapi::ino_t;
11use std::ops::Range;
12use std::sync::Arc;
13
14pub struct FsNodeCache {
15 next_ino: Option<AtomicCounter<u64>>,
17
18 nodes: RcuHashMap<ino_t, WeakFsNodeHandle>,
20}
21
22impl Default for FsNodeCache {
23 fn default() -> Self {
24 Self::new(false)
25 }
26}
27
28impl FsNodeCache {
29 pub fn new(uses_external_node_ids: bool) -> Self {
30 Self {
31 next_ino: if uses_external_node_ids {
32 None
33 } else {
34 Some(AtomicCounter::<u64>::new(1))
35 },
36 nodes: RcuHashMap::default(),
37 }
38 }
39
40 pub fn uses_external_node_ids(&self) -> bool {
41 self.next_ino.is_none()
42 }
43
44 pub fn allocate_ino(&self) -> Option<ino_t> {
45 self.next_ino.as_ref().map(|counter| counter.next())
46 }
47
48 pub fn allocate_ino_range(&self, size: usize) -> Option<Range<ino_t>> {
49 assert!(size > 0);
50 self.next_ino.as_ref().map(|counter| {
51 let start = counter.add(size as u64);
52 Range { start: start as ino_t, end: start + size as ino_t }
53 })
54 }
55
56 pub fn insert_node(&self, node: &FsNodeHandle) {
57 let node_key = node.node_key();
58 self.nodes.insert(node_key, Arc::downgrade(node));
59 }
60
61 pub fn remove_node(&self, node: &FsNode) {
62 let node_key = node.node_key();
63 let mut nodes = self.nodes.lock();
64 if let Some(weak_node) = nodes.get(&node_key) {
65 if weak_node.strong_count() == 0 {
66 nodes.remove(&node_key);
67 }
68 }
69 }
70
71 pub fn get_and_validate_or_create_node<V, C>(
72 &self,
73 node_key: ino_t,
74 validate_fn: V,
75 create_fn: C,
76 ) -> Result<FsNodeHandle, Errno>
77 where
78 V: Fn(&FsNodeHandle) -> bool,
79 C: FnOnce() -> Result<FsNodeHandle, Errno>,
80 {
81 {
83 let scope = RcuReadScope::new();
84 if let Some(weak_node) = self.nodes.get(&scope, &node_key) {
85 if let Some(node) = weak_node.upgrade() {
86 if validate_fn(&node) {
87 return Ok(node);
88 }
89 }
90 }
91 }
92
93 let mut nodes = self.nodes.lock();
95 match nodes.entry(node_key) {
96 Entry::Vacant(entry) => {
97 let node = create_fn()?;
98 entry.insert(Arc::downgrade(&node));
99 Ok(node)
100 }
101 Entry::Occupied(mut entry) => {
102 if let Some(node) = entry.get().upgrade() {
103 if validate_fn(&node) {
104 return Ok(node);
105 }
106 }
107 let node = create_fn()?;
108 entry.insert(Arc::downgrade(&node));
109 Ok(node)
110 }
111 }
112 }
113}