os/fs/tmpfs/
tmpfs.rs

1//! Tmpfs 文件系统实现
2
3use alloc::sync::Arc;
4
5use crate::config::PAGE_SIZE;
6use crate::sync::Mutex;
7use crate::vfs::{FileSystem, FsError, Inode, StatFs};
8
9use super::inode::{TmpfsInode, TmpfsStats};
10
11/// Tmpfs 文件系统
12pub struct TmpFs {
13    /// 根 inode
14    root: Arc<TmpfsInode>,
15
16    /// 统计信息
17    stats: Arc<Mutex<TmpfsStats>>,
18}
19
20impl TmpFs {
21    /// 创建新的 tmpfs 文件系统
22    ///
23    /// # 参数
24    ///
25    /// - `max_size_mb`: 最大容量(MB),0 表示无限制
26    pub fn new(max_size_mb: usize) -> Arc<Self> {
27        let max_pages = if max_size_mb == 0 {
28            0 // 无限制
29        } else {
30            max_size_mb * 1024 * 1024 / PAGE_SIZE
31        };
32
33        let stats = Arc::new(Mutex::new(TmpfsStats {
34            allocated_pages: 0,
35            max_pages,
36            next_inode_no: 1,
37        }));
38
39        let root = TmpfsInode::new_root(stats.clone());
40
41        Arc::new(Self { root, stats })
42    }
43
44    /// 获取已使用的容量(字节)
45    pub fn used_size(&self) -> usize {
46        let stats = self.stats.lock();
47        stats.allocated_pages * PAGE_SIZE
48    }
49
50    /// 获取总容量(字节,0 表示无限制)
51    pub fn total_size(&self) -> usize {
52        let stats = self.stats.lock();
53        if stats.max_pages == 0 {
54            0
55        } else {
56            stats.max_pages * PAGE_SIZE
57        }
58    }
59}
60
61impl FileSystem for TmpFs {
62    fn fs_type(&self) -> &'static str {
63        "tmpfs"
64    }
65
66    fn root_inode(&self) -> Arc<dyn Inode> {
67        self.root.clone() as Arc<dyn Inode>
68    }
69
70    fn sync(&self) -> Result<(), FsError> {
71        // tmpfs 完全在内存中,无需同步
72        Ok(())
73    }
74
75    fn statfs(&self) -> Result<StatFs, FsError> {
76        let stats = self.stats.lock();
77
78        let total_blocks = if stats.max_pages == 0 {
79            // 无限制时,使用一个较大的值
80            usize::MAX / PAGE_SIZE
81        } else {
82            stats.max_pages
83        };
84
85        let free_blocks = if stats.max_pages == 0 {
86            total_blocks
87        } else {
88            stats.max_pages.saturating_sub(stats.allocated_pages)
89        };
90
91        Ok(StatFs {
92            block_size: PAGE_SIZE,
93            total_blocks,
94            free_blocks,
95            available_blocks: free_blocks,
96            total_inodes: 0, // tmpfs 动态分配,无上限
97            free_inodes: 0,
98            fsid: 0,
99            max_filename_len: 255,
100        })
101    }
102
103    fn umount(&self) -> Result<(), FsError> {
104        // tmpfs 卸载时自动释放所有内存(通过 Drop)
105        Ok(())
106    }
107}