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