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