starnix_core/vfs/
fs_node_cache.rs1use crate::vfs::{FsNode, FsNodeHandle, WeakFsNodeHandle};
6use fuchsia_rcu::RcuReadScope;
7use starnix_lifecycle::AtomicU64Counter;
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<AtomicU64Counter>,
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 { None } else { Some(AtomicU64Counter::new(1)) },
32 nodes: RcuHashMap::default(),
33 }
34 }
35
36 pub fn uses_external_node_ids(&self) -> bool {
37 self.next_ino.is_none()
38 }
39
40 pub fn allocate_ino(&self) -> Option<ino_t> {
41 self.next_ino.as_ref().map(|counter| counter.next())
42 }
43
44 pub fn allocate_ino_range(&self, size: usize) -> Option<Range<ino_t>> {
45 assert!(size > 0);
46 self.next_ino.as_ref().map(|counter| {
47 let start = counter.add(size as u64);
48 Range { start: start as ino_t, end: start + size as ino_t }
49 })
50 }
51
52 pub fn insert_node(&self, node: &FsNodeHandle) {
53 let node_key = node.node_key();
54 self.nodes.insert(node_key, Arc::downgrade(node));
55 }
56
57 pub fn remove_node(&self, node: &FsNode) {
58 let node_key = node.node_key();
59 let mut nodes = self.nodes.lock();
60 if let Some(weak_node) = nodes.get(&node_key) {
61 if weak_node.strong_count() == 0 {
62 nodes.remove(&node_key);
63 }
64 }
65 }
66
67 pub fn get_and_validate_or_create_node<V, C>(
68 &self,
69 node_key: ino_t,
70 validate_fn: V,
71 create_fn: C,
72 ) -> Result<FsNodeHandle, Errno>
73 where
74 V: Fn(&FsNodeHandle) -> bool,
75 C: FnOnce() -> Result<FsNodeHandle, Errno>,
76 {
77 {
79 let scope = RcuReadScope::new();
80 if let Some(weak_node) = self.nodes.get(&scope, &node_key) {
81 if let Some(node) = weak_node.upgrade() {
82 if validate_fn(&node) {
83 return Ok(node);
84 }
85 }
86 }
87 }
88
89 let mut nodes = self.nodes.lock();
91 match nodes.entry(node_key) {
92 Entry::Vacant(entry) => {
93 let node = create_fn()?;
94 entry.insert(Arc::downgrade(&node));
95 Ok(node)
96 }
97 Entry::Occupied(mut entry) => {
98 if let Some(node) = entry.get().upgrade() {
99 if validate_fn(&node) {
100 return Ok(node);
101 }
102 }
103 let node = create_fn()?;
104 entry.insert(Arc::downgrade(&node));
105 Ok(node)
106 }
107 }
108 }
109}