xref: /DragonOS/kernel/src/filesystem/kernfs/mod.rs (revision 83ed0ebc293d5a10245089f627f52770fd5b9dd4)
1 use core::{cmp::min, fmt::Debug, intrinsics::unlikely};
2 
3 use alloc::{
4     string::String,
5     sync::{Arc, Weak},
6     vec::Vec,
7 };
8 use hashbrown::HashMap;
9 
10 use crate::{
11     libs::{
12         casting::DowncastArc,
13         rwlock::RwLock,
14         spinlock::{SpinLock, SpinLockGuard},
15     },
16     syscall::SystemError,
17     time::TimeSpec,
18 };
19 
20 use self::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData};
21 
22 use super::vfs::{
23     core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem,
24     FileType, FsInfo, IndexNode, InodeId, Metadata, PollStatus,
25 };
26 
27 pub mod callback;
28 
29 #[derive(Debug)]
30 pub struct KernFS {
31     root_inode: Arc<KernFSInode>,
32 }
33 
34 impl FileSystem for KernFS {
35     fn as_any_ref(&self) -> &dyn core::any::Any {
36         self
37     }
38 
39     fn info(&self) -> FsInfo {
40         return FsInfo {
41             blk_dev_id: 0,
42             max_name_len: KernFS::MAX_NAMELEN,
43         };
44     }
45 
46     fn root_inode(&self) -> Arc<dyn IndexNode> {
47         return self.root_inode.clone();
48     }
49 }
50 
51 impl KernFS {
52     pub const MAX_NAMELEN: usize = 4096;
53 
54     #[allow(dead_code)]
55     pub fn new() -> Arc<Self> {
56         let root_inode = Self::create_root_inode();
57         let fs = Arc::new(Self {
58             root_inode: root_inode.clone(),
59         });
60 
61         {
62             let ptr = root_inode.as_ref() as *const KernFSInode as *mut KernFSInode;
63             unsafe {
64                 (*ptr).self_ref = Arc::downgrade(&root_inode);
65             }
66         }
67         root_inode.inner.write().parent = Arc::downgrade(&root_inode);
68         *root_inode.fs.write() = Arc::downgrade(&fs);
69         return fs;
70     }
71 
72     fn create_root_inode() -> Arc<KernFSInode> {
73         let metadata = Metadata {
74             size: 0,
75             mode: ModeType::from_bits_truncate(0o755),
76             uid: 0,
77             gid: 0,
78             blk_size: 0,
79             blocks: 0,
80             atime: TimeSpec::new(0, 0),
81             mtime: TimeSpec::new(0, 0),
82             ctime: TimeSpec::new(0, 0),
83             dev_id: 0,
84             inode_id: generate_inode_id(),
85             file_type: FileType::Dir,
86             nlinks: 1,
87             raw_dev: 0,
88         };
89         let root_inode = Arc::new(KernFSInode {
90             name: String::from(""),
91             inner: RwLock::new(InnerKernFSInode {
92                 parent: Weak::new(),
93                 metadata,
94                 symlink_target: None,
95                 symlink_target_absolute_path: None,
96             }),
97             self_ref: Weak::new(),
98             fs: RwLock::new(Weak::new()),
99             private_data: SpinLock::new(None),
100             callback: None,
101             children: SpinLock::new(HashMap::new()),
102             inode_type: KernInodeType::Dir,
103         });
104 
105         return root_inode;
106     }
107 }
108 
109 #[derive(Debug)]
110 pub struct KernFSInode {
111     inner: RwLock<InnerKernFSInode>,
112     /// 指向当前Inode所属的文件系统的弱引用
113     fs: RwLock<Weak<KernFS>>,
114     /// 指向自身的弱引用
115     self_ref: Weak<KernFSInode>,
116     /// 私有数据
117     private_data: SpinLock<Option<KernInodePrivateData>>,
118     /// 回调函数
119     callback: Option<&'static dyn KernFSCallback>,
120     /// 子Inode
121     children: SpinLock<HashMap<String, Arc<KernFSInode>>>,
122     /// Inode类型
123     inode_type: KernInodeType,
124     /// Inode名称
125     name: String,
126 }
127 
128 #[derive(Debug)]
129 pub struct InnerKernFSInode {
130     parent: Weak<KernFSInode>,
131 
132     /// 当前inode的元数据
133     metadata: Metadata,
134     /// 符号链接指向的inode(仅当inode_type为SymLink时有效)
135     symlink_target: Option<Weak<KernFSInode>>,
136     symlink_target_absolute_path: Option<String>,
137 }
138 
139 impl IndexNode for KernFSInode {
140     fn as_any_ref(&self) -> &dyn core::any::Any {
141         self
142     }
143 
144     fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
145         if let Some(callback) = self.callback {
146             let callback_data =
147                 KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
148             return callback.open(callback_data);
149         }
150 
151         return Ok(());
152     }
153 
154     fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
155         return Ok(());
156     }
157 
158     fn metadata(&self) -> Result<Metadata, SystemError> {
159         return Ok(self.inner.read().metadata.clone());
160     }
161 
162     fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> {
163         // 若文件系统没有实现此方法,则返回“不支持”
164         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
165     }
166 
167     fn resize(&self, _len: usize) -> Result<(), SystemError> {
168         return Ok(());
169     }
170 
171     fn create_with_data(
172         &self,
173         _name: &str,
174         _file_type: FileType,
175         _mode: ModeType,
176         _data: usize,
177     ) -> Result<Arc<dyn IndexNode>, SystemError> {
178         // 应当通过kernfs的其它方法来创建文件,而不能从用户态直接调用此方法。
179         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
180     }
181 
182     fn link(&self, _name: &str, _other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
183         // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
184         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
185     }
186 
187     fn unlink(&self, _name: &str) -> Result<(), SystemError> {
188         // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
189         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
190     }
191 
192     fn rmdir(&self, _name: &str) -> Result<(), SystemError> {
193         // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
194         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
195     }
196 
197     fn move_(
198         &self,
199         _old_name: &str,
200         _target: &Arc<dyn IndexNode>,
201         _new_name: &str,
202     ) -> Result<(), SystemError> {
203         // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
204         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
205     }
206 
207     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
208         if unlikely(name.len() > KernFS::MAX_NAMELEN) {
209             return Err(SystemError::ENAMETOOLONG);
210         }
211         if unlikely(self.inode_type != KernInodeType::Dir) {
212             return Err(SystemError::ENOTDIR);
213         }
214         match name {
215             "" | "." => {
216                 return Ok(self.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
217             }
218 
219             ".." => {
220                 return Ok(self
221                     .inner
222                     .read()
223                     .parent
224                     .upgrade()
225                     .ok_or(SystemError::ENOENT)?);
226             }
227             name => {
228                 // 在子目录项中查找
229                 return Ok(self
230                     .children
231                     .lock()
232                     .get(name)
233                     .ok_or(SystemError::ENOENT)?
234                     .clone());
235             }
236         }
237     }
238 
239     fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
240         if self.inode_type != KernInodeType::Dir {
241             return Err(SystemError::ENOTDIR);
242         }
243 
244         let children = self.children.lock();
245         let r = children
246             .iter()
247             .find(|(_, v)| v.metadata().unwrap().inode_id == ino)
248             .map(|(k, _)| k.clone());
249 
250         return r.ok_or(SystemError::ENOENT);
251     }
252 
253     fn get_entry_name_and_metadata(&self, ino: InodeId) -> Result<(String, Metadata), SystemError> {
254         // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
255         let name = self.get_entry_name(ino)?;
256         let entry = self.find(&name)?;
257         return Ok((name, entry.metadata()?));
258     }
259 
260     fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
261         // 若文件系统没有实现此方法,则返回“不支持”
262         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
263     }
264 
265     fn truncate(&self, _len: usize) -> Result<(), SystemError> {
266         // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
267         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
268     }
269 
270     fn sync(&self) -> Result<(), SystemError> {
271         return Ok(());
272     }
273 
274     fn fs(&self) -> Arc<dyn FileSystem> {
275         return self.fs.read().upgrade().unwrap();
276     }
277 
278     fn list(&self) -> Result<Vec<String>, SystemError> {
279         let info = self.metadata()?;
280         if info.file_type != FileType::Dir {
281             return Err(SystemError::ENOTDIR);
282         }
283 
284         let mut keys: Vec<String> = Vec::new();
285         keys.push(String::from("."));
286         keys.push(String::from(".."));
287         self.children
288             .lock()
289             .keys()
290             .into_iter()
291             .for_each(|x| keys.push(x.clone()));
292 
293         return Ok(keys);
294     }
295 
296     fn poll(&self) -> Result<PollStatus, SystemError> {
297         // todo: 根据inode的具体attribute,返回PollStatus
298         return Ok(PollStatus::READ | PollStatus::WRITE);
299     }
300 
301     fn read_at(
302         &self,
303         offset: usize,
304         len: usize,
305         buf: &mut [u8],
306         _data: &mut FilePrivateData,
307     ) -> Result<usize, SystemError> {
308         if self.inode_type == KernInodeType::SymLink {
309             let inner = self.inner.read();
310             if offset >= inner.symlink_target_absolute_path.as_ref().unwrap().len() {
311                 return Ok(0);
312             }
313             let len = min(len, buf.len());
314             let len = min(
315                 len,
316                 inner.symlink_target_absolute_path.as_ref().unwrap().len() - offset,
317             );
318             buf[0..len].copy_from_slice(
319                 &inner
320                     .symlink_target_absolute_path
321                     .as_ref()
322                     .unwrap()
323                     .as_bytes()[offset..offset + len],
324             );
325             return Ok(len);
326         }
327         if self.inode_type != KernInodeType::File {
328             return Err(SystemError::EISDIR);
329         }
330 
331         if self.callback.is_none() {
332             kwarn!("kernfs: callback is none");
333             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
334         }
335 
336         let callback_data =
337             KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
338         return self
339             .callback
340             .as_ref()
341             .unwrap()
342             .read(callback_data, &mut buf[..len], offset);
343     }
344 
345     fn write_at(
346         &self,
347         offset: usize,
348         len: usize,
349         buf: &[u8],
350         _data: &mut FilePrivateData,
351     ) -> Result<usize, SystemError> {
352         if self.inode_type != KernInodeType::File {
353             return Err(SystemError::EISDIR);
354         }
355 
356         if self.callback.is_none() {
357             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
358         }
359 
360         let callback_data =
361             KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
362         return self
363             .callback
364             .as_ref()
365             .unwrap()
366             .write(callback_data, &buf[..len], offset);
367     }
368 }
369 
370 impl KernFSInode {
371     pub fn new(
372         parent: Option<Arc<KernFSInode>>,
373         name: String,
374         mut metadata: Metadata,
375         inode_type: KernInodeType,
376         private_data: Option<KernInodePrivateData>,
377         callback: Option<&'static dyn KernFSCallback>,
378     ) -> Arc<KernFSInode> {
379         metadata.file_type = inode_type.into();
380         let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
381 
382         let inode = Arc::new(KernFSInode {
383             name,
384             inner: RwLock::new(InnerKernFSInode {
385                 parent: parent.clone(),
386                 metadata,
387                 symlink_target: None,
388                 symlink_target_absolute_path: None,
389             }),
390             self_ref: Weak::new(),
391             fs: RwLock::new(Weak::new()),
392             private_data: SpinLock::new(private_data),
393             callback,
394             children: SpinLock::new(HashMap::new()),
395             inode_type,
396         });
397 
398         {
399             let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
400             unsafe {
401                 (*ptr).self_ref = Arc::downgrade(&inode);
402             }
403         }
404         if parent.strong_count() > 0 {
405             let kernfs = parent
406                 .upgrade()
407                 .unwrap()
408                 .fs()
409                 .downcast_arc::<KernFS>()
410                 .expect("KernFSInode::new: parent is not a KernFS instance");
411             *inode.fs.write() = Arc::downgrade(&kernfs);
412         }
413         return inode;
414     }
415 
416     /// 在当前inode下增加子目录
417     ///
418     /// ## 参数
419     ///
420     /// - `name`:子目录名称
421     /// - `mode`:子目录权限
422     /// - `private_data`:子目录私有数据
423     /// - `callback`:子目录回调函数
424     ///
425     /// ## 返回值
426     ///
427     /// - 成功:子目录inode
428     /// - 失败:错误码
429     #[allow(dead_code)]
430     #[inline]
431     pub fn add_dir(
432         &self,
433         name: String,
434         mode: ModeType,
435         private_data: Option<KernInodePrivateData>,
436         callback: Option<&'static dyn KernFSCallback>,
437     ) -> Result<Arc<KernFSInode>, SystemError> {
438         if unlikely(self.inode_type != KernInodeType::Dir) {
439             return Err(SystemError::ENOTDIR);
440         }
441 
442         return self.inner_create(name, KernInodeType::Dir, mode, 0, private_data, callback);
443     }
444 
445     /// 在当前inode下增加文件
446     ///
447     /// ## 参数
448     ///
449     /// - `name`:文件名称
450     /// - `mode`:文件权限
451     /// - `size`:文件大小(如果不指定,则默认为4096)
452     /// - `private_data`:文件私有数据
453     /// - `callback`:文件回调函数
454     ///
455     ///
456     /// ## 返回值
457     ///
458     /// - 成功:文件inode
459     /// - 失败:错误码
460     #[allow(dead_code)]
461     #[inline]
462     pub fn add_file(
463         &self,
464         name: String,
465         mode: ModeType,
466         size: Option<usize>,
467         private_data: Option<KernInodePrivateData>,
468         callback: Option<&'static dyn KernFSCallback>,
469     ) -> Result<Arc<KernFSInode>, SystemError> {
470         if unlikely(self.inode_type != KernInodeType::Dir) {
471             return Err(SystemError::ENOTDIR);
472         }
473 
474         let size = size.unwrap_or(4096);
475         return self.inner_create(
476             name,
477             KernInodeType::File,
478             mode,
479             size,
480             private_data,
481             callback,
482         );
483     }
484 
485     fn inner_create(
486         &self,
487         name: String,
488         file_type: KernInodeType,
489         mode: ModeType,
490         mut size: usize,
491         private_data: Option<KernInodePrivateData>,
492         callback: Option<&'static dyn KernFSCallback>,
493     ) -> Result<Arc<KernFSInode>, SystemError> {
494         match file_type {
495             KernInodeType::Dir | KernInodeType::SymLink => {
496                 size = 0;
497             }
498             _ => {}
499         }
500 
501         let metadata = Metadata {
502             size: size as i64,
503             mode,
504             uid: 0,
505             gid: 0,
506             blk_size: 0,
507             blocks: 0,
508             atime: TimeSpec::new(0, 0),
509             mtime: TimeSpec::new(0, 0),
510             ctime: TimeSpec::new(0, 0),
511             dev_id: 0,
512             inode_id: generate_inode_id(),
513             file_type: file_type.into(),
514             nlinks: 1,
515             raw_dev: 0,
516         };
517 
518         let new_inode: Arc<KernFSInode> = Self::new(
519             Some(self.self_ref.upgrade().unwrap()),
520             name.clone(),
521             metadata,
522             file_type,
523             private_data,
524             callback,
525         );
526 
527         self.children.lock().insert(name, new_inode.clone());
528 
529         return Ok(new_inode);
530     }
531 
532     /// 在当前inode下删除子目录或者文件
533     ///
534     /// 如果要删除的是子目录,且子目录不为空,则返回ENOTEMPTY
535     ///
536     /// ## 参数
537     ///
538     /// - `name`:子目录或者文件名称
539     ///
540     /// ## 返回值
541     ///
542     /// - 成功:()
543     /// - 失败:错误码
544     #[allow(dead_code)]
545     pub fn remove(&self, name: &str) -> Result<(), SystemError> {
546         if unlikely(self.inode_type != KernInodeType::Dir) {
547             return Err(SystemError::ENOTDIR);
548         }
549 
550         let mut children = self.children.lock();
551         let inode = children.get(name).ok_or(SystemError::ENOENT)?;
552         if inode.children.lock().is_empty() {
553             children.remove(name);
554             return Ok(());
555         } else {
556             return Err(SystemError::ENOTEMPTY);
557         }
558     }
559 
560     /// add_link - create a symlink in kernfs
561     ///
562     /// ## 参数
563     ///
564     /// - `parent`: directory to create the symlink in
565     /// - `name`: name of the symlink
566     /// - `target`: target node for the symlink to point to
567     ///
568     /// Returns the created node on success
569     ///
570     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/kernfs/symlink.c#25
571     pub fn add_link(
572         &self,
573         name: String,
574         target: &Arc<KernFSInode>,
575         target_absolute_path: String,
576     ) -> Result<Arc<KernFSInode>, SystemError> {
577         // kdebug!("kernfs add link: name:{name}, target path={target_absolute_path}");
578         let inode = self.inner_create(
579             name,
580             KernInodeType::SymLink,
581             ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
582             0,
583             None,
584             None,
585         )?;
586 
587         inode.inner.write().symlink_target = Some(Arc::downgrade(target));
588         inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path);
589         return Ok(inode);
590     }
591 
592     pub fn name(&self) -> &str {
593         return &self.name;
594     }
595 
596     pub fn parent(&self) -> Option<Arc<KernFSInode>> {
597         return self.inner.read().parent.upgrade();
598     }
599 
600     pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
601         return self.private_data.lock();
602     }
603 
604     #[allow(dead_code)]
605     pub fn symlink_target(&self) -> Option<Arc<KernFSInode>> {
606         return self.inner.read().symlink_target.as_ref()?.upgrade();
607     }
608 
609     /// remove a kernfs_node recursively
610     pub fn remove_recursive(&self) {
611         let mut children = self.children.lock().drain().collect::<Vec<_>>();
612         while let Some((_, child)) = children.pop() {
613             children.append(&mut child.children.lock().drain().collect::<Vec<_>>());
614         }
615     }
616 
617     /// 删除当前的inode(包括其自身、子目录和子文件)
618     #[allow(dead_code)]
619     pub fn remove_inode_include_self(&self) {
620         let parent = self.parent();
621         if let Some(parent) = parent {
622             parent.children.lock().remove(self.name());
623         }
624         self.remove_recursive();
625     }
626 }
627 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
628 pub enum KernInodeType {
629     Dir,
630     File,
631     SymLink,
632 }
633 
634 impl Into<FileType> for KernInodeType {
635     fn into(self) -> FileType {
636         match self {
637             KernInodeType::Dir => FileType::Dir,
638             KernInodeType::File => FileType::File,
639             KernInodeType::SymLink => FileType::SymLink,
640         }
641     }
642 }
643