os/vfs/
dentry.rs

1//! 目录项(Dentry)与全局缓存
2//!
3//! 该模块实现了 VFS 路径层的核心组件,提供目录树结构管理和路径到 Inode 的映射缓存。
4//!
5//! # 组件
6//!
7//! - [`Dentry`] - 目录项结构,表示路径中的一个节点
8//! - [`DentryCache`] - 全局路径缓存,加速重复路径查找
9//! - [`DENTRY_CACHE`] - 全局缓存单例
10//!
11//! # 核心概念
12//!
13//! ## Dentry 的作用
14//!
15//! Dentry (Directory Entry) 是文件系统目录树中的一个节点,它:
16//! - 缓存文件名到 Inode 的映射
17//! - 维护父子关系,构成目录树
18//! - 标记挂载点信息
19//!
20//! ## 与 Inode 的关系
21//!
22//! - **Dentry**: 路径层组件,可能有多个 Dentry 指向同一个 Inode (硬链接)
23//! - **Inode**: 存储层组件,代表实际的文件或目录
24//!
25//! ```text
26//! /home/user/file.txt ──┐
27//!                       ├──> Dentry ──> Inode (文件数据)
28//! /tmp/link_to_file  ───┘
29//! ```
30//!
31//! # 引用计数设计
32//!
33//! Dentry 使用 `Arc` 和 `Weak` 管理生命周期,避免循环引用:
34//!
35//! - **parent**: `Weak<Dentry>` - 弱引用父节点,避免循环
36//! - **children**: `Arc<Dentry>` - 强引用子节点
37//! - **全局缓存**: `Weak<Dentry>` - 不延长生命周期
38//!
39//! ```text
40//! Arc<Dentry("/")>
41//!   └─> Arc<Dentry("/etc")> { parent: Weak<Dentry("/">") }
42//!         └─> Arc<Dentry("/etc/passwd")> { parent: Weak<Dentry("/etc")> }
43//! ```
44//!
45//! # 缓存机制
46//!
47//! ## 全局缓存 (DENTRY_CACHE)
48//!
49//! 维护路径字符串到 Dentry 的映射:
50//!
51//! - **插入**: 路径解析成功后自动插入
52//! - **查找**: O(log n) BTreeMap 查找
53//! - **失效**: Weak 引用自动失效,无需手动清理
54//!
55//! ## 树状缓存
56//!
57//! Dentry 内部维护子项缓存,加速相对路径查找:
58//!
59//! ```rust
60//! let parent = vfs_lookup("/etc")?;
61//! // 快速查找,不需要再次访问 Inode
62//! if let Some(child) = parent.lookup_child("passwd") {
63//!     // 缓存命中
64//! }
65//! ```
66//!
67//! # 使用示例
68//!
69//! ## 创建 Dentry
70//!
71//! ```rust
72//! use vfs::{Dentry, Inode};
73//!
74//! let inode = create_inode()?;
75//! let dentry = Dentry::new(String::from("file.txt"), inode);
76//! ```
77//!
78//! ## 管理父子关系
79//!
80//! ```rust
81//! // 添加子项
82//! parent.add_child(child_dentry.clone());
83//!
84//! // 查找子项
85//! if let Some(child) = parent.lookup_child("file.txt") {
86//!     println!("找到: {}", child.name);
87//! }
88//!
89//! // 删除子项
90//! parent.remove_child("file.txt");
91//! ```
92//!
93//! ## 使用全局缓存
94//!
95//! ```rust
96//! use vfs::DENTRY_CACHE;
97//!
98//! // 插入缓存
99//! DENTRY_CACHE.insert(&dentry);
100//!
101//! // 查找缓存
102//! if let Some(cached) = DENTRY_CACHE.lookup("/etc/passwd") {
103//!     // 缓存命中,避免重复路径解析
104//! }
105//!
106//! // 删除缓存
107//! DENTRY_CACHE.remove("/etc/passwd");
108//! ```
109
110use crate::sync::SpinLock;
111use crate::vfs::inode::Inode;
112use alloc::collections::BTreeMap;
113use alloc::string::String;
114use alloc::sync::{Arc, Weak};
115use core::fmt;
116
117/// 目录项(Dentry)
118///
119/// 表示路径中的一个组件,缓存文件名到 inode 的映射
120pub struct Dentry {
121    /// 文件名(不含路径)
122    pub name: String,
123
124    /// 关联的 inode
125    pub inode: Arc<dyn Inode>,
126
127    /// 父目录 dentry(弱引用避免循环)
128    parent: SpinLock<Weak<Dentry>>,
129
130    /// 子 dentry 映射(文件名 -> dentry)
131    children: SpinLock<BTreeMap<String, Arc<Dentry>>>,
132
133    /// 如果此 dentry 是挂载点,指向挂载的根 dentry
134    mount_point: SpinLock<Option<Weak<Dentry>>>,
135}
136
137impl fmt::Debug for Dentry {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        let parent_name = self.parent().map(|p| p.name.clone());
140        let child_names = {
141            let children = self.children.lock();
142            children.keys().cloned().collect::<alloc::vec::Vec<_>>()
143        };
144
145        f.debug_struct("Dentry")
146            .field("name", &self.name)
147            .field("parent", &parent_name)
148            .field("children", &child_names)
149            .finish()
150    }
151}
152
153impl Dentry {
154    /// 创建新的 dentry
155    pub fn new(name: String, inode: Arc<dyn Inode>) -> Arc<Self> {
156        let dentry = Arc::new(Self {
157            name,
158            inode,
159            parent: SpinLock::new(Weak::new()),
160            children: SpinLock::new(BTreeMap::new()),
161            mount_point: SpinLock::new(None),
162        });
163
164        dentry.inode.set_dentry(Arc::downgrade(&dentry));
165
166        dentry
167    }
168
169    /// 设置父 dentry
170    pub fn set_parent(&self, parent: &Arc<Dentry>) {
171        *self.parent.lock() = Arc::downgrade(parent);
172    }
173
174    /// 获取父 dentry
175    pub fn parent(&self) -> Option<Arc<Dentry>> {
176        self.parent.lock().upgrade()
177    }
178
179    /// 查找子 dentry
180    pub fn lookup_child(&self, name: &str) -> Option<Arc<Dentry>> {
181        self.children.lock().get(name).cloned()
182    }
183
184    /// 添加子 dentry
185    pub fn add_child(self: &Arc<Self>, child: Arc<Dentry>) {
186        child.set_parent(self);
187        self.children.lock().insert(child.name.clone(), child);
188    }
189
190    /// 删除子 dentry
191    pub fn remove_child(&self, name: &str) -> Option<Arc<Dentry>> {
192        self.children.lock().remove(name)
193    }
194
195    /// 获取完整路径(通过向上遍历父节点直到根目录)
196    pub fn full_path(&self) -> String {
197        let mut components = alloc::vec::Vec::new();
198        let mut current: *const Dentry = self;
199
200        // 向上遍历到根目录
201        loop {
202            let dentry = unsafe { &*current };
203
204            // 根目录的名字是 "/"
205            if dentry.name == "/" {
206                break;
207            }
208
209            components.push(dentry.name.clone());
210
211            // 获取父节点
212            match dentry.parent() {
213                Some(parent) => current = Arc::as_ptr(&parent),
214                None => break, // 到达根或孤立节点
215            }
216        }
217
218        // 反转(从根到当前)
219        components.reverse();
220
221        if components.is_empty() {
222            String::from("/")
223        } else {
224            String::from("/") + &components.join("/")
225        }
226    }
227
228    /// 设置挂载点
229    pub fn set_mount(&self, mounted_root: &Arc<Dentry>) {
230        *self.mount_point.lock() = Some(Arc::downgrade(mounted_root));
231    }
232
233    /// 清除挂载点
234    pub fn clear_mount(&self) {
235        *self.mount_point.lock() = None;
236    }
237
238    /// 获取挂载的根 dentry(如果有)
239    pub fn get_mount(&self) -> Option<Arc<Dentry>> {
240        self.mount_point.lock().as_ref()?.upgrade()
241    }
242}
243
244// 全局 dentry 缓存实例
245lazy_static::lazy_static! {
246    pub static ref DENTRY_CACHE: DentryCache = DentryCache::new();
247}
248
249/// 全局 Dentry 缓存
250pub struct DentryCache {
251    /// 路径 -> dentry 的弱引用映射
252    cache: SpinLock<BTreeMap<String, Weak<Dentry>>>,
253}
254
255impl DentryCache {
256    /// 创建新的缓存
257    pub const fn new() -> Self {
258        Self {
259            cache: SpinLock::new(BTreeMap::new()),
260        }
261    }
262
263    /// 从缓存中查找 dentry
264    pub fn lookup(&self, path: &str) -> Option<Arc<Dentry>> {
265        let cache = self.cache.lock();
266        let weak = cache.get(path)?;
267        weak.upgrade()
268    }
269
270    /// 插入 dentry 到缓存
271    pub fn insert(&self, dentry: &Arc<Dentry>) {
272        let path = dentry.full_path();
273        self.cache.lock().insert(path, Arc::downgrade(dentry));
274    }
275
276    /// 从缓存中移除
277    pub fn remove(&self, path: &str) {
278        self.cache.lock().remove(path);
279    }
280
281    /// 清空缓存
282    pub fn clear(&self) {
283        self.cache.lock().clear();
284    }
285}