xref: /DragonOS/kernel/src/filesystem/devfs/mod.rs (revision dd9f1fc1a42406461e6f0d38cce1e56e22a1a15f)
1 /// 导出devfs的模块
2 pub mod null_dev;
3 pub mod zero_dev;
4 
5 use super::vfs::{
6     core::{generate_inode_id, ROOT_INODE},
7     file::FileMode,
8     FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus,
9 };
10 use crate::{
11     kerror,
12     libs::spinlock::{SpinLock, SpinLockGuard},
13     syscall::SystemError,
14     time::TimeSpec,
15 };
16 use alloc::{
17     collections::BTreeMap,
18     string::{String, ToString},
19     sync::{Arc, Weak},
20     vec::Vec,
21 };
22 
23 const DEVFS_MAX_NAMELEN: usize = 64;
24 
25 /// @brief dev文件系统
26 #[derive(Debug)]
27 pub struct DevFS {
28     // 文件系统根节点
29     root_inode: Arc<LockedDevFSInode>,
30 }
31 
32 impl FileSystem for DevFS {
33     fn as_any_ref(&self) -> &dyn core::any::Any {
34         self
35     }
36 
37     fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> {
38         return self.root_inode.clone();
39     }
40 
41     fn info(&self) -> super::vfs::FsInfo {
42         return FsInfo {
43             blk_dev_id: 0,
44             max_name_len: DEVFS_MAX_NAMELEN,
45         };
46     }
47 }
48 
49 impl DevFS {
50     pub fn new() -> Arc<Self> {
51         // 初始化root inode
52         let root: Arc<LockedDevFSInode> = Arc::new(LockedDevFSInode(SpinLock::new(
53             // /dev 的权限设置为 读+执行,root 可以读写
54             // root 的 parent 是空指针
55             DevFSInode::new(FileType::Dir, 0o755 as u32, 0),
56         )));
57 
58         let devfs: Arc<DevFS> = Arc::new(DevFS { root_inode: root });
59 
60         // 对root inode加锁,并继续完成初始化工作
61         let mut root_guard: SpinLockGuard<DevFSInode> = devfs.root_inode.0.lock();
62         root_guard.parent = Arc::downgrade(&devfs.root_inode);
63         root_guard.self_ref = Arc::downgrade(&devfs.root_inode);
64         root_guard.fs = Arc::downgrade(&devfs);
65         // 释放锁
66         drop(root_guard);
67 
68         // 创建文件夹
69         let root: &Arc<LockedDevFSInode> = &devfs.root_inode;
70         root.add_dir("char")
71             .expect("DevFS: Failed to create /dev/char");
72 
73         root.add_dir("block")
74             .expect("DevFS: Failed to create /dev/block");
75         devfs.register_bultinin_device();
76 
77         // kdebug!("ls /dev: {:?}", root.list());
78         return devfs;
79     }
80 
81     /// @brief 注册系统内部自带的设备
82     fn register_bultinin_device(&self) {
83         use null_dev::LockedNullInode;
84         use zero_dev::LockedZeroInode;
85         let dev_root: Arc<LockedDevFSInode> = self.root_inode.clone();
86         dev_root
87             .add_dev("null", LockedNullInode::new())
88             .expect("DevFS: Failed to register /dev/null");
89         dev_root
90             .add_dev("zero", LockedZeroInode::new())
91             .expect("DevFS: Failed to register /dev/zero");
92     }
93 
94     /// @brief 在devfs内注册设备
95     ///
96     /// @param name 设备名称
97     /// @param device 设备节点的结构体
98     pub fn register_device<T: DeviceINode>(
99         &self,
100         name: &str,
101         device: Arc<T>,
102     ) -> Result<(), SystemError> {
103         let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
104         let metadata = device.metadata()?;
105         match metadata.file_type {
106             // 字节设备挂载在 /dev/char
107             FileType::CharDevice => {
108                 if let Err(_) = dev_root_inode.find("char") {
109                     dev_root_inode.create("char", FileType::Dir, 0o755)?;
110                 }
111 
112                 let any_char_inode = dev_root_inode.find("char")?;
113                 let dev_char_inode: &LockedDevFSInode = any_char_inode
114                     .as_any_ref()
115                     .downcast_ref::<LockedDevFSInode>()
116                     .unwrap();
117                 // 在 /dev/char 下创建设备节点
118                 dev_char_inode.add_dev(name, device.clone())?;
119 
120                 // 特殊处理 tty 设备,挂载在 /dev 下
121                 if name.starts_with("tty") && name.len() > 3 {
122                     dev_root_inode.add_dev(name, device.clone())?;
123                 }
124                 device.set_fs(dev_char_inode.0.lock().fs.clone());
125             }
126             FileType::BlockDevice => {
127                 if let Err(_) = dev_root_inode.find("block") {
128                     dev_root_inode.create("block", FileType::Dir, 0o755)?;
129                 }
130 
131                 let any_block_inode = dev_root_inode.find("block")?;
132                 let dev_block_inode: &LockedDevFSInode = any_block_inode
133                     .as_any_ref()
134                     .downcast_ref::<LockedDevFSInode>()
135                     .unwrap();
136 
137                 dev_block_inode.add_dev(name, device.clone())?;
138                 device.set_fs(dev_block_inode.0.lock().fs.clone());
139             }
140             _ => {
141                 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
142             }
143         }
144 
145         return Ok(());
146     }
147 
148     /// @brief 卸载设备
149     pub fn unregister_device<T: DeviceINode>(
150         &self,
151         name: &str,
152         device: Arc<T>,
153     ) -> Result<(), SystemError> {
154         let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
155         match device.metadata().unwrap().file_type {
156             // 字节设备挂载在 /dev/char
157             FileType::CharDevice => {
158                 if let Err(_) = dev_root_inode.find("char") {
159                     return Err(SystemError::ENOENT);
160                 }
161 
162                 let any_char_inode = dev_root_inode.find("char")?;
163                 let dev_char_inode = any_char_inode
164                     .as_any_ref()
165                     .downcast_ref::<LockedDevFSInode>()
166                     .unwrap();
167                 // TODO: 调用设备的卸载接口(当引入卸载接口之后)
168                 dev_char_inode.remove(name)?;
169             }
170             FileType::BlockDevice => {
171                 if let Err(_) = dev_root_inode.find("block") {
172                     return Err(SystemError::ENOENT);
173                 }
174 
175                 let any_block_inode = dev_root_inode.find("block")?;
176                 let dev_block_inode = any_block_inode
177                     .as_any_ref()
178                     .downcast_ref::<LockedDevFSInode>()
179                     .unwrap();
180 
181                 dev_block_inode.remove(name)?;
182             }
183             _ => {
184                 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
185             }
186         }
187 
188         return Ok(());
189     }
190 }
191 
192 /// @brief dev文件i节点(锁)
193 #[derive(Debug)]
194 pub struct LockedDevFSInode(SpinLock<DevFSInode>);
195 
196 /// @brief dev文件i节点(无锁)
197 #[derive(Debug)]
198 pub struct DevFSInode {
199     /// 指向父Inode的弱引用
200     parent: Weak<LockedDevFSInode>,
201     /// 指向自身的弱引用
202     self_ref: Weak<LockedDevFSInode>,
203     /// 子Inode的B树
204     children: BTreeMap<String, Arc<dyn IndexNode>>,
205     /// 指向inode所在的文件系统对象的指针
206     fs: Weak<DevFS>,
207     /// INode 元数据
208     metadata: Metadata,
209 }
210 
211 impl DevFSInode {
212     pub fn new(dev_type_: FileType, mode_: u32, data_: usize) -> Self {
213         return Self::new_with_parent(Weak::default(), dev_type_, mode_, data_);
214     }
215 
216     pub fn new_with_parent(
217         parent: Weak<LockedDevFSInode>,
218         dev_type_: FileType,
219         mode_: u32,
220         data_: usize,
221     ) -> Self {
222         return DevFSInode {
223             parent: parent,
224             self_ref: Weak::default(),
225             children: BTreeMap::new(),
226             metadata: Metadata {
227                 dev_id: 1,
228                 inode_id: generate_inode_id(),
229                 size: 0,
230                 blk_size: 0,
231                 blocks: 0,
232                 atime: TimeSpec::default(),
233                 mtime: TimeSpec::default(),
234                 ctime: TimeSpec::default(),
235                 file_type: dev_type_, // 文件夹
236                 mode: mode_,
237                 nlinks: 1,
238                 uid: 0,
239                 gid: 0,
240                 raw_dev: data_,
241             },
242             fs: Weak::default(),
243         };
244     }
245 }
246 
247 impl LockedDevFSInode {
248     pub fn add_dir(&self, name: &str) -> Result<(), SystemError> {
249         let guard: SpinLockGuard<DevFSInode> = self.0.lock();
250 
251         if guard.children.contains_key(name) {
252             return Err(SystemError::EEXIST);
253         }
254 
255         match self.do_create_with_data(guard, name, FileType::Dir, 0o755 as u32, 0) {
256             Ok(inode) => inode,
257             Err(err) => {
258                 return Err(err);
259             }
260         };
261 
262         return Ok(());
263     }
264 
265     pub fn add_dev(&self, name: &str, dev: Arc<dyn IndexNode>) -> Result<(), SystemError> {
266         let mut this = self.0.lock();
267 
268         if this.children.contains_key(name) {
269             return Err(SystemError::EEXIST);
270         }
271 
272         this.children.insert(name.to_string(), dev);
273         return Ok(());
274     }
275 
276     pub fn remove(&self, name: &str) -> Result<(), SystemError> {
277         let x = self
278             .0
279             .lock()
280             .children
281             .remove(name)
282             .ok_or(SystemError::ENOENT)?;
283 
284         drop(x);
285         return Ok(());
286     }
287 
288     fn do_create_with_data(
289         &self,
290         mut guard: SpinLockGuard<DevFSInode>,
291         _name: &str,
292         _file_type: FileType,
293         _mode: u32,
294         _data: usize,
295     ) -> Result<Arc<dyn IndexNode>, SystemError> {
296         if guard.metadata.file_type != FileType::Dir {
297             return Err(SystemError::ENOTDIR);
298         }
299 
300         // 如果有重名的,则返回
301         if guard.children.contains_key(_name) {
302             return Err(SystemError::EEXIST);
303         }
304 
305         // 创建inode
306         let result: Arc<LockedDevFSInode> = Arc::new(LockedDevFSInode(SpinLock::new(DevFSInode {
307             parent: guard.self_ref.clone(),
308             self_ref: Weak::default(),
309             children: BTreeMap::new(),
310             metadata: Metadata {
311                 dev_id: 0,
312                 inode_id: generate_inode_id(),
313                 size: 0,
314                 blk_size: 0,
315                 blocks: 0,
316                 atime: TimeSpec::default(),
317                 mtime: TimeSpec::default(),
318                 ctime: TimeSpec::default(),
319                 file_type: _file_type,
320                 mode: _mode,
321                 nlinks: 1,
322                 uid: 0,
323                 gid: 0,
324                 raw_dev: _data,
325             },
326             fs: guard.fs.clone(),
327         })));
328 
329         // 初始化inode的自引用的weak指针
330         result.0.lock().self_ref = Arc::downgrade(&result);
331 
332         // 将子inode插入父inode的B树中
333         guard.children.insert(String::from(_name), result.clone());
334         return Ok(result);
335     }
336 }
337 
338 impl IndexNode for LockedDevFSInode {
339     fn as_any_ref(&self) -> &dyn core::any::Any {
340         self
341     }
342 
343     fn open(
344         &self,
345         _data: &mut super::vfs::FilePrivateData,
346         _mode: &FileMode,
347     ) -> Result<(), SystemError> {
348         return Ok(());
349     }
350 
351     fn close(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), SystemError> {
352         return Ok(());
353     }
354 
355     fn create_with_data(
356         &self,
357         name: &str,
358         file_type: FileType,
359         mode: u32,
360         data: usize,
361     ) -> Result<Arc<dyn IndexNode>, SystemError> {
362         // 获取当前inode
363         let guard: SpinLockGuard<DevFSInode> = self.0.lock();
364         // 如果当前inode不是文件夹,则返回
365         return self.do_create_with_data(guard, name, file_type, mode, data);
366     }
367 
368     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
369         let inode = self.0.lock();
370 
371         if inode.metadata.file_type != FileType::Dir {
372             return Err(SystemError::ENOTDIR);
373         }
374 
375         match name {
376             "" | "." => {
377                 return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
378             }
379             ".." => {
380                 return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?);
381             }
382             name => {
383                 // 在子目录项中查找
384                 return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone());
385             }
386         }
387     }
388 
389     fn fs(&self) -> Arc<dyn FileSystem> {
390         return self.0.lock().fs.upgrade().unwrap();
391     }
392 
393     fn get_entry_name(&self, ino: super::vfs::InodeId) -> Result<String, SystemError> {
394         let inode: SpinLockGuard<DevFSInode> = self.0.lock();
395         if inode.metadata.file_type != FileType::Dir {
396             return Err(SystemError::ENOTDIR);
397         }
398 
399         match ino {
400             0 => {
401                 return Ok(String::from("."));
402             }
403             1 => {
404                 return Ok(String::from(".."));
405             }
406             ino => {
407                 // 暴力遍历所有的children,判断inode id是否相同
408                 // TODO: 优化这里,这个地方性能很差!
409                 let mut key: Vec<String> = inode
410                     .children
411                     .keys()
412                     .filter(|k| inode.children.get(*k).unwrap().metadata().unwrap().inode_id == ino)
413                     .cloned()
414                     .collect();
415 
416                 match key.len() {
417                     0=>{return Err(SystemError::ENOENT);}
418                     1=>{return Ok(key.remove(0));}
419                     _ => panic!("Devfs get_entry_name: key.len()={key_len}>1, current inode_id={inode_id}, to find={to_find}", key_len=key.len(), inode_id = inode.metadata.inode_id, to_find=ino)
420                 }
421             }
422         }
423     }
424 
425     fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
426         Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
427     }
428 
429     fn list(&self) -> Result<Vec<String>, SystemError> {
430         let info = self.metadata()?;
431         if info.file_type != FileType::Dir {
432             return Err(SystemError::ENOTDIR);
433         }
434 
435         let mut keys: Vec<String> = Vec::new();
436         keys.push(String::from("."));
437         keys.push(String::from(".."));
438         keys.append(&mut self.0.lock().children.keys().cloned().collect());
439 
440         return Ok(keys);
441     }
442 
443     fn metadata(&self) -> Result<Metadata, SystemError> {
444         return Ok(self.0.lock().metadata.clone());
445     }
446 
447     fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
448         let mut inode = self.0.lock();
449         inode.metadata.atime = metadata.atime;
450         inode.metadata.mtime = metadata.mtime;
451         inode.metadata.ctime = metadata.ctime;
452         inode.metadata.mode = metadata.mode;
453         inode.metadata.uid = metadata.uid;
454         inode.metadata.gid = metadata.gid;
455 
456         return Ok(());
457     }
458 
459     fn poll(&self) -> Result<super::vfs::PollStatus, SystemError> {
460         // 加锁
461         let inode: SpinLockGuard<DevFSInode> = self.0.lock();
462 
463         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
464         if inode.metadata.file_type == FileType::Dir {
465             return Err(SystemError::EISDIR);
466         }
467 
468         return Ok(PollStatus::READ | PollStatus::WRITE);
469     }
470 
471     /// 读设备 - 应该调用设备的函数读写,而不是通过文件系统读写
472     fn read_at(
473         &self,
474         _offset: usize,
475         _len: usize,
476         _buf: &mut [u8],
477         _data: &mut super::vfs::file::FilePrivateData,
478     ) -> Result<usize, SystemError> {
479         kerror!("DevFS: read_at is not supported!");
480         Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
481     }
482 
483     /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写
484     fn write_at(
485         &self,
486         _offset: usize,
487         _len: usize,
488         _buf: &[u8],
489         _data: &mut super::vfs::file::FilePrivateData,
490     ) -> Result<usize, SystemError> {
491         Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
492     }
493 }
494 
495 /// @brief 所有的设备INode都需要额外实现这个trait
496 pub trait DeviceINode: IndexNode {
497     fn set_fs(&self, fs: Weak<DevFS>);
498     // TODO: 增加 unregister 方法
499 }
500 
501 /// @brief 获取devfs实例的强类型不可变引用
502 macro_rules! devfs_exact_ref {
503     () => {{
504         let devfs_inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().find("dev");
505         if let Err(e) = devfs_inode {
506             kerror!("failed to get DevFS ref. errcode = {:?}", e);
507             return Err(SystemError::ENOENT);
508         }
509 
510         let binding = devfs_inode.unwrap();
511         let devfs_inode: &LockedDevFSInode = binding
512             .as_any_ref()
513             .downcast_ref::<LockedDevFSInode>()
514             .unwrap();
515         let binding = devfs_inode.fs();
516         binding
517     }
518     .as_any_ref()
519     .downcast_ref::<DevFS>()
520     .unwrap()};
521 }
522 /// @brief devfs的设备注册函数
523 pub fn devfs_register<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), SystemError> {
524     return devfs_exact_ref!().register_device(name, device);
525 }
526 
527 /// @brief devfs的设备卸载函数
528 #[allow(dead_code)]
529 pub fn devfs_unregister<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), SystemError> {
530     return devfs_exact_ref!().unregister_device(name, device);
531 }
532