xref: /DragonOS/kernel/src/filesystem/devfs/mod.rs (revision 45b8371173b070028457f7ee64be33f68b4f9ada)
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     include::bindings::bindings::{EEXIST, EISDIR, ENOENT, ENOTDIR, ENOTSUP},
12     kerror,
13     libs::spinlock::{SpinLock, SpinLockGuard},
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>(&self, name: &str, device: Arc<T>) -> Result<(), i32> {
99         let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
100         match device.metadata().unwrap().file_type {
101             // 字节设备挂载在 /dev/char
102             FileType::CharDevice => {
103                 if let Err(_) = dev_root_inode.find("char") {
104                     dev_root_inode.create("char", FileType::Dir, 0o755)?;
105                 }
106 
107                 let any_char_inode = dev_root_inode.find("char")?;
108                 let dev_char_inode: &LockedDevFSInode = any_char_inode
109                     .as_any_ref()
110                     .downcast_ref::<LockedDevFSInode>()
111                     .unwrap();
112 
113                 dev_char_inode.add_dev(name, device.clone())?;
114                 device.set_fs(dev_char_inode.0.lock().fs.clone());
115             }
116             FileType::BlockDevice => {
117                 if let Err(_) = dev_root_inode.find("block") {
118                     dev_root_inode.create("block", FileType::Dir, 0o755)?;
119                 }
120 
121                 let any_block_inode = dev_root_inode.find("block")?;
122                 let dev_block_inode: &LockedDevFSInode = any_block_inode
123                     .as_any_ref()
124                     .downcast_ref::<LockedDevFSInode>()
125                     .unwrap();
126 
127                 dev_block_inode.add_dev(name, device.clone())?;
128                 device.set_fs(dev_block_inode.0.lock().fs.clone());
129             }
130             _ => {
131                 return Err(-(ENOTSUP as i32));
132             }
133         }
134 
135         return Ok(());
136     }
137 
138     /// @brief 卸载设备
139     pub fn unregister_device<T: DeviceINode>(&self, name: &str, device: Arc<T>) -> Result<(), i32> {
140         let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
141         match device.metadata().unwrap().file_type {
142             // 字节设备挂载在 /dev/char
143             FileType::CharDevice => {
144                 if let Err(_) = dev_root_inode.find("char") {
145                     return Err(-(ENOENT as i32));
146                 }
147 
148                 let any_char_inode = dev_root_inode.find("char")?;
149                 let dev_char_inode = any_char_inode
150                     .as_any_ref()
151                     .downcast_ref::<LockedDevFSInode>()
152                     .unwrap();
153                 // TODO: 调用设备的卸载接口(当引入卸载接口之后)
154                 dev_char_inode.remove(name)?;
155             }
156             FileType::BlockDevice => {
157                 if let Err(_) = dev_root_inode.find("block") {
158                     return Err(-(ENOENT as i32));
159                 }
160 
161                 let any_block_inode = dev_root_inode.find("block")?;
162                 let dev_block_inode = any_block_inode
163                     .as_any_ref()
164                     .downcast_ref::<LockedDevFSInode>()
165                     .unwrap();
166 
167                 dev_block_inode.remove(name)?;
168             }
169             _ => {
170                 return Err(-(ENOTSUP as i32));
171             }
172         }
173 
174         return Ok(());
175     }
176 }
177 
178 /// @brief dev文件i节点(锁)
179 #[derive(Debug)]
180 pub struct LockedDevFSInode(SpinLock<DevFSInode>);
181 
182 /// @brief dev文件i节点(无锁)
183 #[derive(Debug)]
184 pub struct DevFSInode {
185     /// 指向父Inode的弱引用
186     parent: Weak<LockedDevFSInode>,
187     /// 指向自身的弱引用
188     self_ref: Weak<LockedDevFSInode>,
189     /// 子Inode的B树
190     children: BTreeMap<String, Arc<dyn IndexNode>>,
191     /// 指向inode所在的文件系统对象的指针
192     fs: Weak<DevFS>,
193     /// INode 元数据
194     metadata: Metadata,
195 }
196 
197 impl DevFSInode {
198     pub fn new(dev_type_: FileType, mode_: u32, data_: usize) -> Self {
199         return Self::new_with_parent(Weak::default(), dev_type_, mode_, data_);
200     }
201 
202     pub fn new_with_parent(
203         parent: Weak<LockedDevFSInode>,
204         dev_type_: FileType,
205         mode_: u32,
206         data_: usize,
207     ) -> Self {
208         return DevFSInode {
209             parent: parent,
210             self_ref: Weak::default(),
211             children: BTreeMap::new(),
212             metadata: Metadata {
213                 dev_id: 1,
214                 inode_id: generate_inode_id(),
215                 size: 0,
216                 blk_size: 0,
217                 blocks: 0,
218                 atime: TimeSpec::default(),
219                 mtime: TimeSpec::default(),
220                 ctime: TimeSpec::default(),
221                 file_type: dev_type_, // 文件夹
222                 mode: mode_,
223                 nlinks: 1,
224                 uid: 0,
225                 gid: 0,
226                 raw_dev: data_,
227             },
228             fs: Weak::default(),
229         };
230     }
231 }
232 
233 impl LockedDevFSInode {
234     pub fn add_dir(&self, name: &str) -> Result<(), i32> {
235         let guard: SpinLockGuard<DevFSInode> = self.0.lock();
236 
237         if guard.children.contains_key(name) {
238             return Err(-(EEXIST as i32));
239         }
240 
241         match self.do_create_with_data(guard, name, FileType::Dir, 0o755 as u32, 0) {
242             Ok(inode) => inode,
243             Err(err) => {
244                 return Err(err);
245             }
246         };
247 
248         return Ok(());
249     }
250 
251     pub fn add_dev(&self, name: &str, dev: Arc<dyn IndexNode>) -> Result<(), i32> {
252         let mut this = self.0.lock();
253 
254         if this.children.contains_key(name) {
255             return Err(-(EEXIST as i32));
256         }
257 
258         this.children.insert(name.to_string(), dev);
259         return Ok(());
260     }
261 
262     pub fn remove(&self, name: &str) -> Result<(), i32> {
263         let x = self
264             .0
265             .lock()
266             .children
267             .remove(name)
268             .ok_or(-(ENOENT as i32))?;
269 
270         drop(x);
271         return Ok(());
272     }
273 
274     fn do_create_with_data(
275         &self,
276         mut guard: SpinLockGuard<DevFSInode>,
277         _name: &str,
278         _file_type: FileType,
279         _mode: u32,
280         _data: usize,
281     ) -> Result<Arc<dyn IndexNode>, i32> {
282         if guard.metadata.file_type != FileType::Dir {
283             return Err(-(ENOTDIR as i32));
284         }
285 
286         // 如果有重名的,则返回
287         if guard.children.contains_key(_name) {
288             return Err(-(EEXIST as i32));
289         }
290 
291         // 创建inode
292         let result: Arc<LockedDevFSInode> = Arc::new(LockedDevFSInode(SpinLock::new(DevFSInode {
293             parent: guard.self_ref.clone(),
294             self_ref: Weak::default(),
295             children: BTreeMap::new(),
296             metadata: Metadata {
297                 dev_id: 0,
298                 inode_id: generate_inode_id(),
299                 size: 0,
300                 blk_size: 0,
301                 blocks: 0,
302                 atime: TimeSpec::default(),
303                 mtime: TimeSpec::default(),
304                 ctime: TimeSpec::default(),
305                 file_type: _file_type,
306                 mode: _mode,
307                 nlinks: 1,
308                 uid: 0,
309                 gid: 0,
310                 raw_dev: _data,
311             },
312             fs: guard.fs.clone(),
313         })));
314 
315         // 初始化inode的自引用的weak指针
316         result.0.lock().self_ref = Arc::downgrade(&result);
317 
318         // 将子inode插入父inode的B树中
319         guard.children.insert(String::from(_name), result.clone());
320         return Ok(result);
321     }
322 }
323 
324 impl IndexNode for LockedDevFSInode {
325     fn as_any_ref(&self) -> &dyn core::any::Any {
326         self
327     }
328 
329     fn open(&self, _data: &mut super::vfs::FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
330         return Ok(());
331     }
332 
333     fn close(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), i32> {
334         return Ok(());
335     }
336 
337     fn create_with_data(
338         &self,
339         name: &str,
340         file_type: FileType,
341         mode: u32,
342         data: usize,
343     ) -> Result<Arc<dyn IndexNode>, i32> {
344         // 获取当前inode
345         let guard: SpinLockGuard<DevFSInode> = self.0.lock();
346         // 如果当前inode不是文件夹,则返回
347         return self.do_create_with_data(guard, name, file_type, mode, data);
348     }
349 
350     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, i32> {
351         let inode = self.0.lock();
352 
353         if inode.metadata.file_type != FileType::Dir {
354             return Err(-(ENOTDIR as i32));
355         }
356 
357         match name {
358             "" | "." => {
359                 return Ok(inode.self_ref.upgrade().ok_or(-(ENOENT as i32))?);
360             }
361             ".." => {
362                 return Ok(inode.parent.upgrade().ok_or(-(ENOENT as i32))?);
363             }
364             name => {
365                 // 在子目录项中查找
366                 return Ok(inode.children.get(name).ok_or(-(ENOENT as i32))?.clone());
367             }
368         }
369     }
370 
371     fn fs(&self) -> Arc<dyn FileSystem> {
372         return self.0.lock().fs.upgrade().unwrap();
373     }
374 
375     fn get_entry_name(&self, ino: super::vfs::InodeId) -> Result<String, i32> {
376         let inode: SpinLockGuard<DevFSInode> = self.0.lock();
377         if inode.metadata.file_type != FileType::Dir {
378             return Err(-(ENOTDIR as i32));
379         }
380 
381         match ino {
382             0 => {
383                 return Ok(String::from("."));
384             }
385             1 => {
386                 return Ok(String::from(".."));
387             }
388             ino => {
389                 // 暴力遍历所有的children,判断inode id是否相同
390                 // TODO: 优化这里,这个地方性能很差!
391                 let mut key: Vec<String> = inode
392                     .children
393                     .keys()
394                     .filter(|k| inode.children.get(*k).unwrap().metadata().unwrap().inode_id == ino)
395                     .cloned()
396                     .collect();
397 
398                 match key.len() {
399                     0=>{return Err(-(ENOENT as i32));}
400                     1=>{return Ok(key.remove(0));}
401                     _ => 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)
402                 }
403             }
404         }
405     }
406 
407     fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, i32> {
408         Err(-(ENOTSUP as i32))
409     }
410 
411     fn list(&self) -> Result<Vec<String>, i32> {
412         let info = self.metadata()?;
413         if info.file_type != FileType::Dir {
414             return Err(-(ENOTDIR as i32));
415         }
416 
417         let mut keys: Vec<String> = Vec::new();
418         keys.push(String::from("."));
419         keys.push(String::from(".."));
420         keys.append(&mut self.0.lock().children.keys().cloned().collect());
421 
422         return Ok(keys);
423     }
424 
425     fn metadata(&self) -> Result<Metadata, i32> {
426         return Ok(self.0.lock().metadata.clone());
427     }
428 
429     fn set_metadata(&self, metadata: &Metadata) -> Result<(), i32> {
430         let mut inode = self.0.lock();
431         inode.metadata.atime = metadata.atime;
432         inode.metadata.mtime = metadata.mtime;
433         inode.metadata.ctime = metadata.ctime;
434         inode.metadata.mode = metadata.mode;
435         inode.metadata.uid = metadata.uid;
436         inode.metadata.gid = metadata.gid;
437 
438         return Ok(());
439     }
440 
441     fn poll(&self) -> Result<super::vfs::PollStatus, i32> {
442         // 加锁
443         let inode: SpinLockGuard<DevFSInode> = self.0.lock();
444 
445         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
446         if inode.metadata.file_type == FileType::Dir {
447             return Err(-(EISDIR as i32));
448         }
449 
450         return Ok(PollStatus {
451             flags: PollStatus::READ_MASK | PollStatus::WRITE_MASK,
452         });
453     }
454 
455     /// 读设备 - 应该调用设备的函数读写,而不是通过文件系统读写
456     fn read_at(
457         &self,
458         _offset: usize,
459         _len: usize,
460         _buf: &mut [u8],
461         _data: &mut super::vfs::file::FilePrivateData,
462     ) -> Result<usize, i32> {
463         Err(-(ENOTSUP as i32))
464     }
465 
466     /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写
467     fn write_at(
468         &self,
469         _offset: usize,
470         _len: usize,
471         _buf: &[u8],
472         _data: &mut super::vfs::file::FilePrivateData,
473     ) -> Result<usize, i32> {
474         Err(-(ENOTSUP as i32))
475     }
476 }
477 
478 /// @brief 所有的设备INode都需要额外实现这个trait
479 pub trait DeviceINode: IndexNode {
480     fn set_fs(&self, fs: Weak<DevFS>);
481     // TODO: 增加 unregister 方法
482 }
483 
484 /// @brief 获取devfs实例的强类型不可变引用
485 macro_rules! devfs_exact_ref {
486     () => {{
487         let devfs_inode: Result<Arc<dyn IndexNode>, i32> = ROOT_INODE().find("dev");
488         if let Err(e) = devfs_inode {
489             kerror!("failed to get DevFS ref. errcode = {e}");
490             return Err(-(ENOENT as i32));
491         }
492 
493         let binding = devfs_inode.unwrap();
494         let devfs_inode: &LockedDevFSInode = binding
495             .as_any_ref()
496             .downcast_ref::<LockedDevFSInode>()
497             .unwrap();
498         let binding = devfs_inode.fs();
499         binding
500     }
501     .as_any_ref()
502     .downcast_ref::<DevFS>()
503     .unwrap()};
504 }
505 /// @brief devfs的设备注册函数
506 pub fn devfs_register<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), i32> {
507     return devfs_exact_ref!().register_device(name, device);
508 }
509 
510 /// @brief devfs的设备卸载函数
511 #[allow(dead_code)]
512 pub fn devfs_unregister<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), i32> {
513     return devfs_exact_ref!().unregister_device(name, device);
514 }
515