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