xref: /DragonOS/kernel/src/filesystem/kernfs/mod.rs (revision a03c4f9dee5705207325c56629c0ccd219168f10)
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, private_data, callback);
443     }
444 
445     /// 在当前inode下增加文件
446     ///
447     /// ## 参数
448     ///
449     /// - `name`:文件名称
450     /// - `mode`:文件权限
451     /// - `private_data`:文件私有数据
452     /// - `callback`:文件回调函数
453     ///
454     /// ## 返回值
455     ///
456     /// - 成功:文件inode
457     /// - 失败:错误码
458     #[allow(dead_code)]
459     #[inline]
460     pub fn add_file(
461         &self,
462         name: String,
463         mode: ModeType,
464         private_data: Option<KernInodePrivateData>,
465         callback: Option<&'static dyn KernFSCallback>,
466     ) -> Result<Arc<KernFSInode>, SystemError> {
467         if unlikely(self.inode_type != KernInodeType::Dir) {
468             return Err(SystemError::ENOTDIR);
469         }
470 
471         return self.inner_create(name, KernInodeType::File, mode, private_data, callback);
472     }
473 
474     fn inner_create(
475         &self,
476         name: String,
477         file_type: KernInodeType,
478         mode: ModeType,
479         private_data: Option<KernInodePrivateData>,
480         callback: Option<&'static dyn KernFSCallback>,
481     ) -> Result<Arc<KernFSInode>, SystemError> {
482         let size;
483         match file_type {
484             KernInodeType::Dir | KernInodeType::SymLink => {
485                 size = 0;
486             }
487             KernInodeType::File => {
488                 size = 4096;
489             }
490         }
491 
492         let metadata = Metadata {
493             size,
494             mode,
495             uid: 0,
496             gid: 0,
497             blk_size: 0,
498             blocks: 0,
499             atime: TimeSpec::new(0, 0),
500             mtime: TimeSpec::new(0, 0),
501             ctime: TimeSpec::new(0, 0),
502             dev_id: 0,
503             inode_id: generate_inode_id(),
504             file_type: file_type.into(),
505             nlinks: 1,
506             raw_dev: 0,
507         };
508 
509         let new_inode: Arc<KernFSInode> = Self::new(
510             Some(self.self_ref.upgrade().unwrap()),
511             name.clone(),
512             metadata,
513             file_type,
514             private_data,
515             callback,
516         );
517 
518         self.children.lock().insert(name, new_inode.clone());
519 
520         return Ok(new_inode);
521     }
522 
523     /// 在当前inode下删除子目录或者文件
524     ///
525     /// 如果要删除的是子目录,且子目录不为空,则返回ENOTEMPTY
526     ///
527     /// ## 参数
528     ///
529     /// - `name`:子目录或者文件名称
530     ///
531     /// ## 返回值
532     ///
533     /// - 成功:()
534     /// - 失败:错误码
535     #[allow(dead_code)]
536     pub fn remove(&self, name: &str) -> Result<(), SystemError> {
537         if unlikely(self.inode_type != KernInodeType::Dir) {
538             return Err(SystemError::ENOTDIR);
539         }
540 
541         let mut children = self.children.lock();
542         let inode = children.get(name).ok_or(SystemError::ENOENT)?;
543         if inode.children.lock().is_empty() {
544             children.remove(name);
545             return Ok(());
546         } else {
547             return Err(SystemError::ENOTEMPTY);
548         }
549     }
550 
551     /// add_link - create a symlink in kernfs
552     ///
553     /// ## 参数
554     ///
555     /// - `parent`: directory to create the symlink in
556     /// - `name`: name of the symlink
557     /// - `target`: target node for the symlink to point to
558     ///
559     /// Returns the created node on success
560     ///
561     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/kernfs/symlink.c#25
562     pub fn add_link(
563         &self,
564         name: String,
565         target: &Arc<KernFSInode>,
566         target_absolute_path: String,
567     ) -> Result<Arc<KernFSInode>, SystemError> {
568         // kdebug!("kernfs add link: name:{name}, target path={target_absolute_path}");
569         let inode = self.inner_create(
570             name,
571             KernInodeType::SymLink,
572             ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
573             None,
574             None,
575         )?;
576 
577         inode.inner.write().symlink_target = Some(Arc::downgrade(target));
578         inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path);
579         return Ok(inode);
580     }
581 
582     pub fn name(&self) -> &str {
583         return &self.name;
584     }
585 
586     pub fn parent(&self) -> Option<Arc<KernFSInode>> {
587         return self.inner.read().parent.upgrade();
588     }
589 
590     pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
591         return self.private_data.lock();
592     }
593 
594     #[allow(dead_code)]
595     pub fn symlink_target(&self) -> Option<Arc<KernFSInode>> {
596         return self.inner.read().symlink_target.as_ref()?.upgrade();
597     }
598 
599     /// remove a kernfs_node recursively
600     pub fn remove_recursive(&self) {
601         let mut children = self.children.lock().drain().collect::<Vec<_>>();
602         while let Some((_, child)) = children.pop() {
603             children.append(&mut child.children.lock().drain().collect::<Vec<_>>());
604         }
605     }
606 
607     /// 删除当前的inode(包括其自身、子目录和子文件)
608     #[allow(dead_code)]
609     pub fn remove_inode_include_self(&self) {
610         let parent = self.parent();
611         if let Some(parent) = parent {
612             parent.children.lock().remove(self.name());
613         }
614         self.remove_recursive();
615     }
616 }
617 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
618 pub enum KernInodeType {
619     Dir,
620     File,
621     SymLink,
622 }
623 
624 impl Into<FileType> for KernInodeType {
625     fn into(self) -> FileType {
626         match self {
627             KernInodeType::Dir => FileType::Dir,
628             KernInodeType::File => FileType::File,
629             KernInodeType::SymLink => FileType::SymLink,
630         }
631     }
632 }
633