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