xref: /DragonOS/kernel/src/filesystem/kernfs/mod.rs (revision e7071df6a47c100381a8bc2000022e82d422361a)
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     libs::{
13         casting::DowncastArc,
14         rwlock::RwLock,
15         spinlock::{SpinLock, SpinLockGuard},
16     },
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,
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 read_at(
297         &self,
298         offset: usize,
299         len: usize,
300         buf: &mut [u8],
301         _data: &mut FilePrivateData,
302     ) -> Result<usize, SystemError> {
303         if self.inode_type == KernInodeType::SymLink {
304             let inner = self.inner.read();
305             if offset >= inner.symlink_target_absolute_path.as_ref().unwrap().len() {
306                 return Ok(0);
307             }
308             let len = min(len, buf.len());
309             let len = min(
310                 len,
311                 inner.symlink_target_absolute_path.as_ref().unwrap().len() - offset,
312             );
313             buf[0..len].copy_from_slice(
314                 &inner
315                     .symlink_target_absolute_path
316                     .as_ref()
317                     .unwrap()
318                     .as_bytes()[offset..offset + len],
319             );
320             return Ok(len);
321         }
322         if self.inode_type != KernInodeType::File {
323             return Err(SystemError::EISDIR);
324         }
325 
326         if self.callback.is_none() {
327             kwarn!("kernfs: callback is none");
328             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
329         }
330 
331         let callback_data =
332             KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
333         return self
334             .callback
335             .as_ref()
336             .unwrap()
337             .read(callback_data, &mut buf[..len], offset);
338     }
339 
340     fn write_at(
341         &self,
342         offset: usize,
343         len: usize,
344         buf: &[u8],
345         _data: &mut FilePrivateData,
346     ) -> Result<usize, SystemError> {
347         if self.inode_type != KernInodeType::File {
348             return Err(SystemError::EISDIR);
349         }
350 
351         if self.callback.is_none() {
352             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
353         }
354 
355         let callback_data =
356             KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
357         return self
358             .callback
359             .as_ref()
360             .unwrap()
361             .write(callback_data, &buf[..len], offset);
362     }
363 }
364 
365 impl KernFSInode {
366     pub fn new(
367         parent: Option<Arc<KernFSInode>>,
368         name: String,
369         mut metadata: Metadata,
370         inode_type: KernInodeType,
371         private_data: Option<KernInodePrivateData>,
372         callback: Option<&'static dyn KernFSCallback>,
373     ) -> Arc<KernFSInode> {
374         metadata.file_type = inode_type.into();
375         let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
376 
377         let inode = Arc::new(KernFSInode {
378             name,
379             inner: RwLock::new(InnerKernFSInode {
380                 parent: parent.clone(),
381                 metadata,
382                 symlink_target: None,
383                 symlink_target_absolute_path: None,
384             }),
385             self_ref: Weak::new(),
386             fs: RwLock::new(Weak::new()),
387             private_data: SpinLock::new(private_data),
388             callback,
389             children: SpinLock::new(HashMap::new()),
390             inode_type,
391         });
392 
393         {
394             let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
395             unsafe {
396                 (*ptr).self_ref = Arc::downgrade(&inode);
397             }
398         }
399         if parent.strong_count() > 0 {
400             let kernfs = parent
401                 .upgrade()
402                 .unwrap()
403                 .fs()
404                 .downcast_arc::<KernFS>()
405                 .expect("KernFSInode::new: parent is not a KernFS instance");
406             *inode.fs.write() = Arc::downgrade(&kernfs);
407         }
408         return inode;
409     }
410 
411     /// 在当前inode下增加子目录
412     ///
413     /// ## 参数
414     ///
415     /// - `name`:子目录名称
416     /// - `mode`:子目录权限
417     /// - `private_data`:子目录私有数据
418     /// - `callback`:子目录回调函数
419     ///
420     /// ## 返回值
421     ///
422     /// - 成功:子目录inode
423     /// - 失败:错误码
424     #[allow(dead_code)]
425     #[inline]
426     pub fn add_dir(
427         &self,
428         name: String,
429         mode: ModeType,
430         private_data: Option<KernInodePrivateData>,
431         callback: Option<&'static dyn KernFSCallback>,
432     ) -> Result<Arc<KernFSInode>, SystemError> {
433         if unlikely(self.inode_type != KernInodeType::Dir) {
434             return Err(SystemError::ENOTDIR);
435         }
436 
437         return self.inner_create(name, KernInodeType::Dir, mode, 0, private_data, callback);
438     }
439 
440     /// 在当前inode下增加文件
441     ///
442     /// ## 参数
443     ///
444     /// - `name`:文件名称
445     /// - `mode`:文件权限
446     /// - `size`:文件大小(如果不指定,则默认为4096)
447     /// - `private_data`:文件私有数据
448     /// - `callback`:文件回调函数
449     ///
450     ///
451     /// ## 返回值
452     ///
453     /// - 成功:文件inode
454     /// - 失败:错误码
455     #[allow(dead_code)]
456     #[inline]
457     pub fn add_file(
458         &self,
459         name: String,
460         mode: ModeType,
461         size: Option<usize>,
462         private_data: Option<KernInodePrivateData>,
463         callback: Option<&'static dyn KernFSCallback>,
464     ) -> Result<Arc<KernFSInode>, SystemError> {
465         if unlikely(self.inode_type != KernInodeType::Dir) {
466             return Err(SystemError::ENOTDIR);
467         }
468 
469         let size = size.unwrap_or(4096);
470         return self.inner_create(
471             name,
472             KernInodeType::File,
473             mode,
474             size,
475             private_data,
476             callback,
477         );
478     }
479 
480     fn inner_create(
481         &self,
482         name: String,
483         file_type: KernInodeType,
484         mode: ModeType,
485         mut size: usize,
486         private_data: Option<KernInodePrivateData>,
487         callback: Option<&'static dyn KernFSCallback>,
488     ) -> Result<Arc<KernFSInode>, SystemError> {
489         match file_type {
490             KernInodeType::Dir | KernInodeType::SymLink => {
491                 size = 0;
492             }
493             _ => {}
494         }
495 
496         let metadata = Metadata {
497             size: size as i64,
498             mode,
499             uid: 0,
500             gid: 0,
501             blk_size: 0,
502             blocks: 0,
503             atime: TimeSpec::new(0, 0),
504             mtime: TimeSpec::new(0, 0),
505             ctime: TimeSpec::new(0, 0),
506             dev_id: 0,
507             inode_id: generate_inode_id(),
508             file_type: file_type.into(),
509             nlinks: 1,
510             raw_dev: 0,
511         };
512 
513         let new_inode: Arc<KernFSInode> = Self::new(
514             Some(self.self_ref.upgrade().unwrap()),
515             name.clone(),
516             metadata,
517             file_type,
518             private_data,
519             callback,
520         );
521 
522         self.children.lock().insert(name, new_inode.clone());
523 
524         return Ok(new_inode);
525     }
526 
527     /// 在当前inode下删除子目录或者文件
528     ///
529     /// 如果要删除的是子目录,且子目录不为空,则返回ENOTEMPTY
530     ///
531     /// ## 参数
532     ///
533     /// - `name`:子目录或者文件名称
534     ///
535     /// ## 返回值
536     ///
537     /// - 成功:()
538     /// - 失败:错误码
539     #[allow(dead_code)]
540     pub fn remove(&self, name: &str) -> Result<(), SystemError> {
541         if unlikely(self.inode_type != KernInodeType::Dir) {
542             return Err(SystemError::ENOTDIR);
543         }
544 
545         let mut children = self.children.lock();
546         let inode = children.get(name).ok_or(SystemError::ENOENT)?;
547         if inode.children.lock().is_empty() {
548             children.remove(name);
549             return Ok(());
550         } else {
551             return Err(SystemError::ENOTEMPTY);
552         }
553     }
554 
555     /// add_link - create a symlink in kernfs
556     ///
557     /// ## 参数
558     ///
559     /// - `parent`: directory to create the symlink in
560     /// - `name`: name of the symlink
561     /// - `target`: target node for the symlink to point to
562     ///
563     /// Returns the created node on success
564     ///
565     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/kernfs/symlink.c#25
566     pub fn add_link(
567         &self,
568         name: String,
569         target: &Arc<KernFSInode>,
570         target_absolute_path: String,
571     ) -> Result<Arc<KernFSInode>, SystemError> {
572         // kdebug!("kernfs add link: name:{name}, target path={target_absolute_path}");
573         let inode = self.inner_create(
574             name,
575             KernInodeType::SymLink,
576             ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
577             0,
578             None,
579             None,
580         )?;
581 
582         inode.inner.write().symlink_target = Some(Arc::downgrade(target));
583         inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path);
584         return Ok(inode);
585     }
586 
587     pub fn name(&self) -> &str {
588         return &self.name;
589     }
590 
591     pub fn parent(&self) -> Option<Arc<KernFSInode>> {
592         return self.inner.read().parent.upgrade();
593     }
594 
595     pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
596         return self.private_data.lock();
597     }
598 
599     #[allow(dead_code)]
600     pub fn symlink_target(&self) -> Option<Arc<KernFSInode>> {
601         return self.inner.read().symlink_target.as_ref()?.upgrade();
602     }
603 
604     /// remove a kernfs_node recursively
605     pub fn remove_recursive(&self) {
606         let mut children = self.children.lock().drain().collect::<Vec<_>>();
607         while let Some((_, child)) = children.pop() {
608             children.append(&mut child.children.lock().drain().collect::<Vec<_>>());
609         }
610     }
611 
612     /// 删除当前的inode(包括其自身、子目录和子文件)
613     #[allow(dead_code)]
614     pub fn remove_inode_include_self(&self) {
615         let parent = self.parent();
616         if let Some(parent) = parent {
617             parent.children.lock().remove(self.name());
618         }
619         self.remove_recursive();
620     }
621 }
622 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
623 pub enum KernInodeType {
624     Dir,
625     File,
626     SymLink,
627 }
628 
629 impl Into<FileType> for KernInodeType {
630     fn into(self) -> FileType {
631         match self {
632             KernInodeType::Dir => FileType::Dir,
633             KernInodeType::File => FileType::File,
634             KernInodeType::SymLink => FileType::SymLink,
635         }
636     }
637 }
638