1use 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
11pub struct TmpFs {
13 root: Arc<TmpfsInode>,
15
16 stats: Arc<Mutex<TmpfsStats>>,
18}
19
20impl TmpFs {
21 pub fn new(max_size_mb: usize) -> Arc<Self> {
27 let max_pages = if max_size_mb == 0 {
28 0 } 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 pub fn used_size(&self) -> usize {
46 let stats = self.stats.lock();
47 stats.allocated_pages * PAGE_SIZE
48 }
49
50 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 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 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, free_inodes: 0,
98 fsid: 0,
99 max_filename_len: 255,
100 })
101 }
102
103 fn umount(&self) -> Result<(), FsError> {
104 Ok(())
106 }
107}