xref: /DragonOS/kernel/src/filesystem/ramfs/mod.rs (revision d8ad0a5e7724469abd5cc3cf271993538878033e)
1 use core::any::Any;
2 
3 use alloc::{
4     collections::BTreeMap,
5     string::String,
6     sync::{Arc, Weak},
7     vec::Vec,
8 };
9 
10 use crate::{
11     filesystem::vfs::{core::generate_inode_id, FileType},
12     libs::spinlock::{SpinLock, SpinLockGuard},
13     syscall::SystemError,
14     time::TimeSpec,
15 };
16 
17 use super::vfs::{
18     file::FilePrivateData, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
19 };
20 
21 /// RamFS的inode名称的最大长度
22 const RAMFS_MAX_NAMELEN: usize = 64;
23 
24 /// @brief 内存文件系统的Inode结构体
25 #[derive(Debug)]
26 struct LockedRamFSInode(SpinLock<RamFSInode>);
27 
28 /// @brief 内存文件系统结构体
29 #[derive(Debug)]
30 pub struct RamFS {
31     /// RamFS的root inode
32     root_inode: Arc<LockedRamFSInode>,
33 }
34 
35 /// @brief 内存文件系统的Inode结构体(不包含锁)
36 #[derive(Debug)]
37 pub struct RamFSInode {
38     // parent变量目前只在find函数中使用到
39     // 所以只有当inode是文件夹的时候,parent才会生效
40     // 对于文件来说,parent就没什么作用了
41     // 关于parent的说明: 目录不允许有硬链接
42     /// 指向父Inode的弱引用
43     parent: Weak<LockedRamFSInode>,
44     /// 指向自身的弱引用
45     self_ref: Weak<LockedRamFSInode>,
46     /// 子Inode的B树
47     children: BTreeMap<String, Arc<LockedRamFSInode>>,
48     /// 当前inode的数据部分
49     data: Vec<u8>,
50     /// 当前inode的元数据
51     metadata: Metadata,
52     /// 指向inode所在的文件系统对象的指针
53     fs: Weak<RamFS>,
54 }
55 
56 impl FileSystem for RamFS {
57     fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> {
58         return self.root_inode.clone();
59     }
60 
61     fn info(&self) -> FsInfo {
62         return FsInfo {
63             blk_dev_id: 0,
64             max_name_len: RAMFS_MAX_NAMELEN,
65         };
66     }
67 
68     /// @brief 本函数用于实现动态转换。
69     /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
70     fn as_any_ref(&self) -> &dyn Any {
71         self
72     }
73 }
74 
75 impl RamFS {
76     pub fn new() -> Arc<Self> {
77         // 初始化root inode
78         let root: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode {
79             parent: Weak::default(),
80             self_ref: Weak::default(),
81             children: BTreeMap::new(),
82             data: Vec::new(),
83             metadata: Metadata {
84                 dev_id: 0,
85                 inode_id: generate_inode_id(),
86                 size: 0,
87                 blk_size: 0,
88                 blocks: 0,
89                 atime: TimeSpec::default(),
90                 mtime: TimeSpec::default(),
91                 ctime: TimeSpec::default(),
92                 file_type: FileType::Dir,
93                 mode: 0o777,
94                 nlinks: 1,
95                 uid: 0,
96                 gid: 0,
97                 raw_dev: 0,
98             },
99             fs: Weak::default(),
100         })));
101 
102         let result: Arc<RamFS> = Arc::new(RamFS { root_inode: root });
103 
104         // 对root inode加锁,并继续完成初始化工作
105         let mut root_guard: SpinLockGuard<RamFSInode> = result.root_inode.0.lock();
106         root_guard.parent = Arc::downgrade(&result.root_inode);
107         root_guard.self_ref = Arc::downgrade(&result.root_inode);
108         root_guard.fs = Arc::downgrade(&result);
109         // 释放锁
110         drop(root_guard);
111 
112         return result;
113     }
114 }
115 
116 impl IndexNode for LockedRamFSInode {
117     fn read_at(
118         &self,
119         offset: usize,
120         len: usize,
121         buf: &mut [u8],
122         _data: &mut FilePrivateData,
123     ) -> Result<usize, SystemError> {
124         if buf.len() < len {
125             return Err(SystemError::EINVAL);
126         }
127         // 加锁
128         let inode: SpinLockGuard<RamFSInode> = self.0.lock();
129 
130         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
131         if inode.metadata.file_type == FileType::Dir {
132             return Err(SystemError::EISDIR);
133         }
134 
135         let start = inode.data.len().min(offset);
136         let end = inode.data.len().min(offset + len);
137 
138         // buffer空间不足
139         if buf.len() < (end - start) {
140             return Err(SystemError::ENOBUFS);
141         }
142 
143         // 拷贝数据
144         let src = &inode.data[start..end];
145         buf[0..src.len()].copy_from_slice(src);
146         return Ok(src.len());
147     }
148 
149     fn write_at(
150         &self,
151         offset: usize,
152         len: usize,
153         buf: &[u8],
154         _data: &mut FilePrivateData,
155     ) -> Result<usize, SystemError> {
156         if buf.len() < len {
157             return Err(SystemError::EINVAL);
158         }
159 
160         // 加锁
161         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
162 
163         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
164         if inode.metadata.file_type == FileType::Dir {
165             return Err(SystemError::EISDIR);
166         }
167 
168         let data: &mut Vec<u8> = &mut inode.data;
169 
170         // 如果文件大小比原来的大,那就resize这个数组
171         if offset + len > data.len() {
172             data.resize(offset + len, 0);
173         }
174 
175         let target = &mut data[offset..offset + len];
176         target.copy_from_slice(&buf[0..len]);
177         return Ok(len);
178     }
179 
180     fn poll(&self) -> Result<PollStatus, SystemError> {
181         // 加锁
182         let inode: SpinLockGuard<RamFSInode> = self.0.lock();
183 
184         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
185         if inode.metadata.file_type == FileType::Dir {
186             return Err(SystemError::EISDIR);
187         }
188 
189         return Ok(PollStatus::READ | PollStatus::WRITE);
190     }
191 
192     fn fs(&self) -> Arc<dyn FileSystem> {
193         return self.0.lock().fs.upgrade().unwrap();
194     }
195 
196     fn as_any_ref(&self) -> &dyn core::any::Any {
197         self
198     }
199 
200     fn metadata(&self) -> Result<Metadata, SystemError> {
201         let inode = self.0.lock();
202         let mut metadata = inode.metadata.clone();
203         metadata.size = inode.data.len() as i64;
204 
205         return Ok(metadata);
206     }
207 
208     fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
209         let mut inode = self.0.lock();
210         inode.metadata.atime = metadata.atime;
211         inode.metadata.mtime = metadata.mtime;
212         inode.metadata.ctime = metadata.ctime;
213         inode.metadata.mode = metadata.mode;
214         inode.metadata.uid = metadata.uid;
215         inode.metadata.gid = metadata.gid;
216 
217         return Ok(());
218     }
219 
220     fn resize(&self, len: usize) -> Result<(), SystemError> {
221         let mut inode = self.0.lock();
222         if inode.metadata.file_type == FileType::File {
223             inode.data.resize(len, 0);
224             return Ok(());
225         } else {
226             return Err(SystemError::EINVAL);
227         }
228     }
229 
230     fn create_with_data(
231         &self,
232         name: &str,
233         file_type: FileType,
234         mode: u32,
235         data: usize,
236     ) -> Result<Arc<dyn IndexNode>, SystemError> {
237         // 获取当前inode
238         let mut inode = self.0.lock();
239         // 如果当前inode不是文件夹,则返回
240         if inode.metadata.file_type != FileType::Dir {
241             return Err(SystemError::ENOTDIR);
242         }
243         // 如果有重名的,则返回
244         if inode.children.contains_key(name) {
245             return Err(SystemError::EEXIST);
246         }
247 
248         // 创建inode
249         let result: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode {
250             parent: inode.self_ref.clone(),
251             self_ref: Weak::default(),
252             children: BTreeMap::new(),
253             data: Vec::new(),
254             metadata: Metadata {
255                 dev_id: 0,
256                 inode_id: generate_inode_id(),
257                 size: 0,
258                 blk_size: 0,
259                 blocks: 0,
260                 atime: TimeSpec::default(),
261                 mtime: TimeSpec::default(),
262                 ctime: TimeSpec::default(),
263                 file_type: file_type,
264                 mode: mode,
265                 nlinks: 1,
266                 uid: 0,
267                 gid: 0,
268                 raw_dev: data,
269             },
270             fs: inode.fs.clone(),
271         })));
272 
273         // 初始化inode的自引用的weak指针
274         result.0.lock().self_ref = Arc::downgrade(&result);
275 
276         // 将子inode插入父inode的B树中
277         inode.children.insert(String::from(name), result.clone());
278 
279         return Ok(result);
280     }
281 
282     fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
283         let other: &LockedRamFSInode = other
284             .downcast_ref::<LockedRamFSInode>()
285             .ok_or(SystemError::EPERM)?;
286         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
287         let mut other_locked: SpinLockGuard<RamFSInode> = other.0.lock();
288 
289         // 如果当前inode不是文件夹,那么报错
290         if inode.metadata.file_type != FileType::Dir {
291             return Err(SystemError::ENOTDIR);
292         }
293 
294         // 如果另一个inode是文件夹,那么也报错
295         if other_locked.metadata.file_type == FileType::Dir {
296             return Err(SystemError::EISDIR);
297         }
298 
299         // 如果当前文件夹下已经有同名文件,也报错。
300         if inode.children.contains_key(name) {
301             return Err(SystemError::EEXIST);
302         }
303 
304         inode
305             .children
306             .insert(String::from(name), other_locked.self_ref.upgrade().unwrap());
307 
308         // 增加硬链接计数
309         other_locked.metadata.nlinks += 1;
310         return Ok(());
311     }
312 
313     fn unlink(&self, name: &str) -> Result<(), SystemError> {
314         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
315         // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录
316         if inode.metadata.file_type != FileType::Dir {
317             return Err(SystemError::ENOTDIR);
318         }
319         // 不允许删除当前文件夹,也不允许删除上一个目录
320         if name == "." || name == ".." {
321             return Err(SystemError::ENOTEMPTY);
322         }
323 
324         // 获得要删除的文件的inode
325         let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?;
326         if to_delete.0.lock().metadata.file_type == FileType::Dir {
327             return Err(SystemError::EPERM);
328         }
329         // 减少硬链接计数
330         to_delete.0.lock().metadata.nlinks -= 1;
331         // 在当前目录中删除这个子目录项
332         inode.children.remove(name);
333         return Ok(());
334     }
335 
336     fn rmdir(&self, name: &str) -> Result<(), SystemError> {
337         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
338         // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录
339         if inode.metadata.file_type != FileType::Dir {
340             return Err(SystemError::ENOTDIR);
341         }
342         // 获得要删除的文件夹的inode
343         let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?;
344         if to_delete.0.lock().metadata.file_type != FileType::Dir {
345             return Err(SystemError::ENOTDIR);
346         }
347 
348         to_delete.0.lock().metadata.nlinks -= 1;
349         // 在当前目录中删除这个子目录项
350         inode.children.remove(name);
351         return Ok(());
352     }
353 
354     fn move_(
355         &self,
356         old_name: &str,
357         target: &Arc<dyn IndexNode>,
358         new_name: &str,
359     ) -> Result<(), SystemError> {
360         let old_inode: Arc<dyn IndexNode> = self.find(old_name)?;
361 
362         // 在新的目录下创建一个硬链接
363         target.link(new_name, &old_inode)?;
364         // 取消现有的目录下的这个硬链接
365         if let Err(err) = self.unlink(old_name) {
366             // 如果取消失败,那就取消新的目录下的硬链接
367             target.unlink(new_name)?;
368             return Err(err);
369         }
370         return Ok(());
371     }
372 
373     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
374         let inode = self.0.lock();
375 
376         if inode.metadata.file_type != FileType::Dir {
377             return Err(SystemError::ENOTDIR);
378         }
379 
380         match name {
381             "" | "." => {
382                 return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
383             }
384 
385             ".." => {
386                 return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?);
387             }
388             name => {
389                 // 在子目录项中查找
390                 return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone());
391             }
392         }
393     }
394 
395     fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
396         let inode: SpinLockGuard<RamFSInode> = self.0.lock();
397         if inode.metadata.file_type != FileType::Dir {
398             return Err(SystemError::ENOTDIR);
399         }
400 
401         match ino {
402             0 => {
403                 return Ok(String::from("."));
404             }
405             1 => {
406                 return Ok(String::from(".."));
407             }
408             ino => {
409                 // 暴力遍历所有的children,判断inode id是否相同
410                 // TODO: 优化这里,这个地方性能很差!
411                 let mut key: Vec<String> = inode
412                     .children
413                     .keys()
414                     .filter(|k| inode.children.get(*k).unwrap().0.lock().metadata.inode_id == ino)
415                     .cloned()
416                     .collect();
417 
418                 match key.len() {
419                     0=>{return Err(SystemError::ENOENT);}
420                     1=>{return Ok(key.remove(0));}
421                     _ => panic!("Ramfs get_entry_name: key.len()={key_len}>1, current inode_id={inode_id}, to find={to_find}", key_len=key.len(), inode_id = inode.metadata.inode_id, to_find=ino)
422                 }
423             }
424         }
425     }
426 
427     fn list(&self) -> Result<Vec<String>, SystemError> {
428         let info = self.metadata()?;
429         if info.file_type != FileType::Dir {
430             return Err(SystemError::ENOTDIR);
431         }
432 
433         let mut keys: Vec<String> = Vec::new();
434         keys.push(String::from("."));
435         keys.push(String::from(".."));
436         keys.append(&mut self.0.lock().children.keys().cloned().collect());
437 
438         return Ok(keys);
439     }
440 }
441