xref: /DragonOS/kernel/src/filesystem/ramfs/mod.rs (revision b5b571e02693d91eb6918d3b7561e088c3e7ee81)
1 use core::any::Any;
2 use core::intrinsics::unlikely;
3 
4 use crate::filesystem::vfs::FSMAKER;
5 use crate::{
6     driver::base::device::device_number::DeviceNumber,
7     filesystem::vfs::{core::generate_inode_id, FileType},
8     ipc::pipe::LockedPipeInode,
9     libs::spinlock::{SpinLock, SpinLockGuard},
10     time::TimeSpec,
11 };
12 use alloc::{
13     collections::BTreeMap,
14     string::String,
15     sync::{Arc, Weak},
16     vec::Vec,
17 };
18 use system_error::SystemError;
19 
20 use super::vfs::{
21     file::FilePrivateData, syscall::ModeType, FileSystem, FileSystemMaker, FsInfo, IndexNode,
22     InodeId, Metadata, SpecialNodeData,
23 };
24 
25 /// RamFS的inode名称的最大长度
26 const RAMFS_MAX_NAMELEN: usize = 64;
27 
28 /// @brief 内存文件系统的Inode结构体
29 #[derive(Debug)]
30 struct LockedRamFSInode(SpinLock<RamFSInode>);
31 
32 /// @brief 内存文件系统结构体
33 #[derive(Debug)]
34 pub struct RamFS {
35     /// RamFS的root inode
36     root_inode: Arc<LockedRamFSInode>,
37 }
38 
39 /// @brief 内存文件系统的Inode结构体(不包含锁)
40 #[derive(Debug)]
41 pub struct RamFSInode {
42     // parent变量目前只在find函数中使用到
43     // 所以只有当inode是文件夹的时候,parent才会生效
44     // 对于文件来说,parent就没什么作用了
45     // 关于parent的说明: 目录不允许有硬链接
46     /// 指向父Inode的弱引用
47     parent: Weak<LockedRamFSInode>,
48     /// 指向自身的弱引用
49     self_ref: Weak<LockedRamFSInode>,
50     /// 子Inode的B树
51     children: BTreeMap<String, Arc<LockedRamFSInode>>,
52     /// 当前inode的数据部分
53     data: Vec<u8>,
54     /// 当前inode的元数据
55     metadata: Metadata,
56     /// 指向inode所在的文件系统对象的指针
57     fs: Weak<RamFS>,
58     /// 指向特殊节点
59     special_node: Option<SpecialNodeData>,
60 }
61 
62 impl FileSystem for RamFS {
63     fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> {
64         return self.root_inode.clone();
65     }
66 
67     fn info(&self) -> FsInfo {
68         return FsInfo {
69             blk_dev_id: 0,
70             max_name_len: RAMFS_MAX_NAMELEN,
71         };
72     }
73 
74     /// @brief 本函数用于实现动态转换。
75     /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
76     fn as_any_ref(&self) -> &dyn Any {
77         self
78     }
79 
80     fn name(&self) -> &str {
81         "ramfs"
82     }
83 }
84 
85 impl RamFS {
86     pub fn new() -> Arc<Self> {
87         // 初始化root inode
88         let root: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode {
89             parent: Weak::default(),
90             self_ref: Weak::default(),
91             children: BTreeMap::new(),
92             data: Vec::new(),
93             metadata: Metadata {
94                 dev_id: 0,
95                 inode_id: generate_inode_id(),
96                 size: 0,
97                 blk_size: 0,
98                 blocks: 0,
99                 atime: TimeSpec::default(),
100                 mtime: TimeSpec::default(),
101                 ctime: TimeSpec::default(),
102                 file_type: FileType::Dir,
103                 mode: ModeType::from_bits_truncate(0o777),
104                 nlinks: 1,
105                 uid: 0,
106                 gid: 0,
107                 raw_dev: DeviceNumber::default(),
108             },
109             fs: Weak::default(),
110             special_node: None,
111         })));
112 
113         let result: Arc<RamFS> = Arc::new(RamFS { root_inode: root });
114 
115         // 对root inode加锁,并继续完成初始化工作
116         let mut root_guard: SpinLockGuard<RamFSInode> = result.root_inode.0.lock();
117         root_guard.parent = Arc::downgrade(&result.root_inode);
118         root_guard.self_ref = Arc::downgrade(&result.root_inode);
119         root_guard.fs = Arc::downgrade(&result);
120         // 释放锁
121         drop(root_guard);
122 
123         return result;
124     }
125 
126     pub fn make_ramfs() -> Result<Arc<dyn FileSystem + 'static>, SystemError> {
127         let fs = RamFS::new();
128         return Ok(fs);
129     }
130 }
131 
132 #[distributed_slice(FSMAKER)]
133 static RAMFSMAKER: FileSystemMaker = FileSystemMaker::new(
134     "ramfs",
135     &(RamFS::make_ramfs as fn() -> Result<Arc<dyn FileSystem + 'static>, SystemError>),
136 );
137 
138 impl IndexNode for LockedRamFSInode {
139     fn truncate(&self, len: usize) -> Result<(), SystemError> {
140         let mut inode = self.0.lock();
141 
142         //如果是文件夹,则报错
143         if inode.metadata.file_type == FileType::Dir {
144             return Err(SystemError::EINVAL);
145         }
146 
147         //当前文件长度大于_len才进行截断,否则不操作
148         if inode.data.len() > len {
149             inode.data.resize(len, 0);
150         }
151         return Ok(());
152     }
153 
154     fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
155         return Ok(());
156     }
157 
158     fn open(
159         &self,
160         _data: &mut FilePrivateData,
161         _mode: &super::vfs::file::FileMode,
162     ) -> Result<(), SystemError> {
163         return Ok(());
164     }
165 
166     fn read_at(
167         &self,
168         offset: usize,
169         len: usize,
170         buf: &mut [u8],
171         _data: &mut FilePrivateData,
172     ) -> Result<usize, SystemError> {
173         if buf.len() < len {
174             return Err(SystemError::EINVAL);
175         }
176         // 加锁
177         let inode: SpinLockGuard<RamFSInode> = self.0.lock();
178 
179         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
180         if inode.metadata.file_type == FileType::Dir {
181             return Err(SystemError::EISDIR);
182         }
183 
184         let start = inode.data.len().min(offset);
185         let end = inode.data.len().min(offset + len);
186 
187         // buffer空间不足
188         if buf.len() < (end - start) {
189             return Err(SystemError::ENOBUFS);
190         }
191 
192         // 拷贝数据
193         let src = &inode.data[start..end];
194         buf[0..src.len()].copy_from_slice(src);
195         return Ok(src.len());
196     }
197 
198     fn write_at(
199         &self,
200         offset: usize,
201         len: usize,
202         buf: &[u8],
203         _data: &mut FilePrivateData,
204     ) -> Result<usize, SystemError> {
205         if buf.len() < len {
206             return Err(SystemError::EINVAL);
207         }
208 
209         // 加锁
210         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
211 
212         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
213         if inode.metadata.file_type == FileType::Dir {
214             return Err(SystemError::EISDIR);
215         }
216 
217         let data: &mut Vec<u8> = &mut inode.data;
218 
219         // 如果文件大小比原来的大,那就resize这个数组
220         if offset + len > data.len() {
221             data.resize(offset + len, 0);
222         }
223 
224         let target = &mut data[offset..offset + len];
225         target.copy_from_slice(&buf[0..len]);
226         return Ok(len);
227     }
228 
229     fn fs(&self) -> Arc<dyn FileSystem> {
230         return self.0.lock().fs.upgrade().unwrap();
231     }
232 
233     fn as_any_ref(&self) -> &dyn core::any::Any {
234         self
235     }
236 
237     fn metadata(&self) -> Result<Metadata, SystemError> {
238         let inode = self.0.lock();
239         let mut metadata = inode.metadata.clone();
240         metadata.size = inode.data.len() as i64;
241 
242         return Ok(metadata);
243     }
244 
245     fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
246         let mut inode = self.0.lock();
247         inode.metadata.atime = metadata.atime;
248         inode.metadata.mtime = metadata.mtime;
249         inode.metadata.ctime = metadata.ctime;
250         inode.metadata.mode = metadata.mode;
251         inode.metadata.uid = metadata.uid;
252         inode.metadata.gid = metadata.gid;
253 
254         return Ok(());
255     }
256 
257     fn resize(&self, len: usize) -> Result<(), SystemError> {
258         let mut inode = self.0.lock();
259         if inode.metadata.file_type == FileType::File {
260             inode.data.resize(len, 0);
261             return Ok(());
262         } else {
263             return Err(SystemError::EINVAL);
264         }
265     }
266 
267     fn create_with_data(
268         &self,
269         name: &str,
270         file_type: FileType,
271         mode: ModeType,
272         data: usize,
273     ) -> Result<Arc<dyn IndexNode>, SystemError> {
274         // 获取当前inode
275         let mut inode = self.0.lock();
276         // 如果当前inode不是文件夹,则返回
277         if inode.metadata.file_type != FileType::Dir {
278             return Err(SystemError::ENOTDIR);
279         }
280         // 如果有重名的,则返回
281         if inode.children.contains_key(name) {
282             return Err(SystemError::EEXIST);
283         }
284 
285         // 创建inode
286         let result: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode {
287             parent: inode.self_ref.clone(),
288             self_ref: Weak::default(),
289             children: BTreeMap::new(),
290             data: Vec::new(),
291             metadata: Metadata {
292                 dev_id: 0,
293                 inode_id: generate_inode_id(),
294                 size: 0,
295                 blk_size: 0,
296                 blocks: 0,
297                 atime: TimeSpec::default(),
298                 mtime: TimeSpec::default(),
299                 ctime: TimeSpec::default(),
300                 file_type,
301                 mode,
302                 nlinks: 1,
303                 uid: 0,
304                 gid: 0,
305                 raw_dev: DeviceNumber::from(data as u32),
306             },
307             fs: inode.fs.clone(),
308             special_node: None,
309         })));
310 
311         // 初始化inode的自引用的weak指针
312         result.0.lock().self_ref = Arc::downgrade(&result);
313 
314         // 将子inode插入父inode的B树中
315         inode.children.insert(String::from(name), result.clone());
316 
317         return Ok(result);
318     }
319 
320     fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
321         let other: &LockedRamFSInode = other
322             .downcast_ref::<LockedRamFSInode>()
323             .ok_or(SystemError::EPERM)?;
324         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
325         let mut other_locked: SpinLockGuard<RamFSInode> = other.0.lock();
326 
327         // 如果当前inode不是文件夹,那么报错
328         if inode.metadata.file_type != FileType::Dir {
329             return Err(SystemError::ENOTDIR);
330         }
331 
332         // 如果另一个inode是文件夹,那么也报错
333         if other_locked.metadata.file_type == FileType::Dir {
334             return Err(SystemError::EISDIR);
335         }
336 
337         // 如果当前文件夹下已经有同名文件,也报错。
338         if inode.children.contains_key(name) {
339             return Err(SystemError::EEXIST);
340         }
341 
342         inode
343             .children
344             .insert(String::from(name), other_locked.self_ref.upgrade().unwrap());
345 
346         // 增加硬链接计数
347         other_locked.metadata.nlinks += 1;
348         return Ok(());
349     }
350 
351     fn unlink(&self, name: &str) -> Result<(), SystemError> {
352         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
353         // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录
354         if inode.metadata.file_type != FileType::Dir {
355             return Err(SystemError::ENOTDIR);
356         }
357         // 不允许删除当前文件夹,也不允许删除上一个目录
358         if name == "." || name == ".." {
359             return Err(SystemError::ENOTEMPTY);
360         }
361 
362         // 获得要删除的文件的inode
363         let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?;
364         if to_delete.0.lock().metadata.file_type == FileType::Dir {
365             return Err(SystemError::EPERM);
366         }
367         // 减少硬链接计数
368         to_delete.0.lock().metadata.nlinks -= 1;
369         // 在当前目录中删除这个子目录项
370         inode.children.remove(name);
371         return Ok(());
372     }
373 
374     fn rmdir(&self, name: &str) -> Result<(), SystemError> {
375         let mut inode: SpinLockGuard<RamFSInode> = self.0.lock();
376         // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录
377         if inode.metadata.file_type != FileType::Dir {
378             return Err(SystemError::ENOTDIR);
379         }
380         // 获得要删除的文件夹的inode
381         let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?;
382         if to_delete.0.lock().metadata.file_type != FileType::Dir {
383             return Err(SystemError::ENOTDIR);
384         }
385 
386         to_delete.0.lock().metadata.nlinks -= 1;
387         // 在当前目录中删除这个子目录项
388         inode.children.remove(name);
389         return Ok(());
390     }
391 
392     fn move_to(
393         &self,
394         old_name: &str,
395         target: &Arc<dyn IndexNode>,
396         new_name: &str,
397     ) -> Result<(), SystemError> {
398         let old_inode: Arc<dyn IndexNode> = self.find(old_name)?;
399 
400         // 在新的目录下创建一个硬链接
401         target.link(new_name, &old_inode)?;
402         // 取消现有的目录下的这个硬链接
403         if let Err(err) = self.unlink(old_name) {
404             // 如果取消失败,那就取消新的目录下的硬链接
405             target.unlink(new_name)?;
406             return Err(err);
407         }
408         return Ok(());
409     }
410 
411     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
412         let inode = self.0.lock();
413 
414         if inode.metadata.file_type != FileType::Dir {
415             return Err(SystemError::ENOTDIR);
416         }
417 
418         match name {
419             "" | "." => {
420                 return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
421             }
422 
423             ".." => {
424                 return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?);
425             }
426             name => {
427                 // 在子目录项中查找
428                 return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone());
429             }
430         }
431     }
432 
433     fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
434         let inode: SpinLockGuard<RamFSInode> = self.0.lock();
435         if inode.metadata.file_type != FileType::Dir {
436             return Err(SystemError::ENOTDIR);
437         }
438 
439         match ino.into() {
440             0 => {
441                 return Ok(String::from("."));
442             }
443             1 => {
444                 return Ok(String::from(".."));
445             }
446             ino => {
447                 // 暴力遍历所有的children,判断inode id是否相同
448                 // TODO: 优化这里,这个地方性能很差!
449                 let mut key: Vec<String> = inode
450                     .children
451                     .keys()
452                     .filter(|k| {
453                         inode
454                             .children
455                             .get(*k)
456                             .unwrap()
457                             .0
458                             .lock()
459                             .metadata
460                             .inode_id
461                             .into()
462                             == ino
463                     })
464                     .cloned()
465                     .collect();
466 
467                 match key.len() {
468                     0=>{return Err(SystemError::ENOENT);}
469                     1=>{return Ok(key.remove(0));}
470                     _ => 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)
471                 }
472             }
473         }
474     }
475 
476     fn list(&self) -> Result<Vec<String>, SystemError> {
477         let info = self.metadata()?;
478         if info.file_type != FileType::Dir {
479             return Err(SystemError::ENOTDIR);
480         }
481 
482         let mut keys: Vec<String> = Vec::new();
483         keys.push(String::from("."));
484         keys.push(String::from(".."));
485         keys.append(&mut self.0.lock().children.keys().cloned().collect());
486 
487         return Ok(keys);
488     }
489 
490     fn mknod(
491         &self,
492         filename: &str,
493         mode: ModeType,
494         _dev_t: DeviceNumber,
495     ) -> Result<Arc<dyn IndexNode>, SystemError> {
496         let mut inode = self.0.lock();
497         if inode.metadata.file_type != FileType::Dir {
498             return Err(SystemError::ENOTDIR);
499         }
500 
501         // 判断需要创建的类型
502         if unlikely(mode.contains(ModeType::S_IFREG)) {
503             // 普通文件
504             return self.create(filename, FileType::File, mode);
505         }
506 
507         let nod = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode {
508             parent: inode.self_ref.clone(),
509             self_ref: Weak::default(),
510             children: BTreeMap::new(),
511             data: Vec::new(),
512             metadata: Metadata {
513                 dev_id: 0,
514                 inode_id: generate_inode_id(),
515                 size: 0,
516                 blk_size: 0,
517                 blocks: 0,
518                 atime: TimeSpec::default(),
519                 mtime: TimeSpec::default(),
520                 ctime: TimeSpec::default(),
521                 file_type: FileType::Pipe,
522                 mode,
523                 nlinks: 1,
524                 uid: 0,
525                 gid: 0,
526                 raw_dev: DeviceNumber::default(),
527             },
528             fs: inode.fs.clone(),
529             special_node: None,
530         })));
531 
532         nod.0.lock().self_ref = Arc::downgrade(&nod);
533 
534         if mode.contains(ModeType::S_IFIFO) {
535             nod.0.lock().metadata.file_type = FileType::Pipe;
536             // 创建pipe文件
537             let pipe_inode = LockedPipeInode::new();
538             // 设置special_node
539             nod.0.lock().special_node = Some(SpecialNodeData::Pipe(pipe_inode));
540         } else if mode.contains(ModeType::S_IFBLK) {
541             nod.0.lock().metadata.file_type = FileType::BlockDevice;
542             unimplemented!()
543         } else if mode.contains(ModeType::S_IFCHR) {
544             nod.0.lock().metadata.file_type = FileType::CharDevice;
545             unimplemented!()
546         }
547 
548         inode
549             .children
550             .insert(String::from(filename).to_uppercase(), nod.clone());
551         Ok(nod)
552     }
553 
554     fn special_node(&self) -> Option<super::vfs::SpecialNodeData> {
555         return self.0.lock().special_node.clone();
556     }
557 
558     /// # 用于重命名内存中的文件或目录
559     fn rename(&self, _old_name: &str, _new_name: &str) -> Result<(), SystemError> {
560         let old_inode: Arc<dyn IndexNode> = self.find(_old_name)?;
561         // 在新的目录下创建一个硬链接
562         self.link(_new_name, &old_inode)?;
563 
564         // 取消现有的目录下的这个硬链接
565         if let Err(err) = self.unlink(_old_name) {
566             // 如果取消失败,那就取消新的目录下的硬链接
567             self.unlink(_new_name)?;
568             return Err(err);
569         }
570 
571         return Ok(());
572     }
573 }
574