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