xref: /DragonOS/kernel/src/filesystem/sysfs/mod.rs (revision c757940bd61b0125e037a59eb77565e42470201b)
1 use super::vfs::{
2     core::generate_inode_id, file::FileMode, FileSystem, FileType, FsInfo, IndexNode, Metadata,
3     PollStatus,
4 };
5 use crate::{
6     libs::spinlock::{SpinLock, SpinLockGuard},
7     syscall::SystemError,
8     time::TimeSpec,
9 };
10 use alloc::{
11     boxed::Box,
12     collections::BTreeMap,
13     string::{String, ToString},
14     sync::{Arc, Weak},
15     vec::Vec,
16 };
17 use core::ptr::null_mut;
18 
19 pub mod bus;
20 pub mod class;
21 pub mod devices;
22 pub mod fs;
23 
24 const SYSFS_MAX_NAMELEN: usize = 64;
25 
26 static mut __SYS_DEVICES_INODE: *mut Arc<dyn IndexNode> = null_mut();
27 static mut __SYS_BUS_INODE: *mut Arc<dyn IndexNode> = null_mut();
28 static mut __SYS_CLASS_INODE: *mut Arc<dyn IndexNode> = null_mut();
29 static mut __SYS_FS_INODE: *mut Arc<dyn IndexNode> = null_mut();
30 
31 /// @brief 获取全局的sys/devices节点
32 #[inline(always)]
33 #[allow(non_snake_case)]
34 pub fn SYS_DEVICES_INODE() -> Arc<dyn IndexNode> {
35     unsafe {
36         return __SYS_DEVICES_INODE.as_ref().unwrap().clone();
37     }
38 }
39 
40 /// @brief 获取全局的sys/bus节点
41 #[inline(always)]
42 #[allow(non_snake_case)]
43 pub fn SYS_BUS_INODE() -> Arc<dyn IndexNode> {
44     unsafe {
45         return __SYS_BUS_INODE.as_ref().unwrap().clone();
46     }
47 }
48 
49 /// @brief 获取全局的sys/class节点
50 #[inline(always)]
51 #[allow(non_snake_case)]
52 pub fn SYS_CLASS_INODE() -> Arc<dyn IndexNode> {
53     unsafe {
54         return __SYS_CLASS_INODE.as_ref().unwrap().clone();
55     }
56 }
57 
58 /// @brief 获取全局的sys/fs节点
59 #[inline(always)]
60 #[allow(non_snake_case)]
61 pub fn SYS_FS_INODE() -> Arc<dyn IndexNode> {
62     unsafe {
63         return __SYS_FS_INODE.as_ref().unwrap().clone();
64     }
65 }
66 
67 /// @brief dev文件系统
68 #[derive(Debug)]
69 pub struct SysFS {
70     // 文件系统根节点
71     root_inode: Arc<LockedSysFSInode>,
72 }
73 
74 impl FileSystem for SysFS {
75     fn as_any_ref(&self) -> &dyn core::any::Any {
76         self
77     }
78 
79     fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> {
80         return self.root_inode.clone();
81     }
82 
83     fn info(&self) -> super::vfs::FsInfo {
84         return FsInfo {
85             blk_dev_id: 0,
86             max_name_len: SYSFS_MAX_NAMELEN,
87         };
88     }
89 }
90 
91 impl SysFS {
92     pub fn new() -> Arc<Self> {
93         // 初始化root inode
94         let root: Arc<LockedSysFSInode> = Arc::new(LockedSysFSInode(SpinLock::new(
95             // /sys 的权限设置为 读+执行,root 可以读写
96             // root 的 parent 是空指针
97             SysFSInode::new(FileType::Dir, 0o755 as u32, 0),
98         )));
99 
100         let sysfs: Arc<SysFS> = Arc::new(SysFS { root_inode: root });
101 
102         // 对root inode加锁,并继续完成初始化工作
103         let mut root_guard: SpinLockGuard<SysFSInode> = sysfs.root_inode.0.lock();
104         root_guard.parent = Arc::downgrade(&sysfs.root_inode);
105         root_guard.self_ref = Arc::downgrade(&sysfs.root_inode);
106         root_guard.fs = Arc::downgrade(&sysfs);
107         // 释放锁
108         drop(root_guard);
109 
110         // 创建文件夹
111         let root: &Arc<LockedSysFSInode> = &sysfs.root_inode;
112         match root.add_dir("devices") {
113             Ok(devices) => unsafe {
114                 __SYS_DEVICES_INODE = Box::leak(Box::new(devices));
115             },
116             Err(_) => panic!("SysFS: Failed to create /sys/devices"),
117         }
118 
119         match root.add_dir("bus") {
120             Ok(bus) => unsafe {
121                 __SYS_BUS_INODE = Box::leak(Box::new(bus));
122             },
123             Err(_) => panic!("SysFS: Failed to create /sys/bus"),
124         }
125 
126         match root.add_dir("class") {
127             Ok(class) => unsafe {
128                 __SYS_CLASS_INODE = Box::leak(Box::new(class));
129             },
130             Err(_) => panic!("SysFS: Failed to create /sys/class"),
131         }
132 
133         match root.add_dir("fs") {
134             Ok(fs) => unsafe {
135                 __SYS_FS_INODE = Box::leak(Box::new(fs));
136             },
137             Err(_) => panic!("SysFS: Failed to create /sys/fs"),
138         }
139         // 初始化platform总线
140         crate::driver::base::platform::platform_bus_init().expect("platform bus init failed");
141         // 初始化串口
142         crate::driver::uart::uart::uart_init().expect("initilize uart error");
143         return sysfs;
144     }
145 }
146 
147 /// @brief sys文件i节点(锁)
148 #[derive(Debug)]
149 pub struct LockedSysFSInode(SpinLock<SysFSInode>);
150 
151 impl IndexNode for LockedSysFSInode {
152     fn as_any_ref(&self) -> &dyn core::any::Any {
153         self
154     }
155 
156     fn open(
157         &self,
158         _data: &mut super::vfs::FilePrivateData,
159         _mode: &FileMode,
160     ) -> Result<(), SystemError> {
161         return Ok(());
162     }
163 
164     fn close(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), SystemError> {
165         return Ok(());
166     }
167 
168     fn read_at(
169         &self,
170         _offset: usize,
171         _len: usize,
172         _buf: &mut [u8],
173         _data: &mut super::vfs::FilePrivateData,
174     ) -> Result<usize, SystemError> {
175         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
176     }
177 
178     fn write_at(
179         &self,
180         _offset: usize,
181         _len: usize,
182         _buf: &[u8],
183         _data: &mut super::vfs::FilePrivateData,
184     ) -> Result<usize, SystemError> {
185         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
186     }
187 
188     fn poll(&self) -> Result<super::vfs::PollStatus, SystemError> {
189         // 加锁
190         let inode: SpinLockGuard<SysFSInode> = self.0.lock();
191 
192         // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
193         if inode.metadata.file_type == FileType::Dir {
194             return Err(SystemError::EISDIR);
195         }
196 
197         return Ok(PollStatus::READ | PollStatus::WRITE);
198     }
199 
200     fn metadata(&self) -> Result<Metadata, SystemError> {
201         return Ok(self.0.lock().metadata.clone());
202     }
203 
204     fn fs(&self) -> Arc<dyn FileSystem> {
205         return self.0.lock().fs.upgrade().unwrap();
206     }
207 
208     fn get_entry_name(&self, ino: super::vfs::InodeId) -> Result<String, SystemError> {
209         let inode: SpinLockGuard<SysFSInode> = self.0.lock();
210         if inode.metadata.file_type != FileType::Dir {
211             return Err(SystemError::ENOTDIR);
212         }
213 
214         match ino {
215             0 => {
216                 return Ok(String::from("."));
217             }
218             1 => {
219                 return Ok(String::from(".."));
220             }
221             ino => {
222                 // 暴力遍历所有的children,判断inode id是否相同
223                 // TODO: 优化这里,这个地方性能很差!
224                 let mut key: Vec<String> = inode
225                     .children
226                     .keys()
227                     .filter(|k| inode.children.get(*k).unwrap().metadata().unwrap().inode_id == ino)
228                     .cloned()
229                     .collect();
230 
231                 match key.len() {
232                     0=>{return Err(SystemError::ENOENT);}
233                     1=>{return Ok(key.remove(0));}
234                     _ => panic!("Sysfs 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)
235                 }
236             }
237         }
238     }
239 
240     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
241         let inode = self.0.lock();
242 
243         if inode.metadata.file_type != FileType::Dir {
244             return Err(SystemError::ENOTDIR);
245         }
246 
247         match name {
248             "" | "." => {
249                 return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
250             }
251             ".." => {
252                 return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?);
253             }
254             name => {
255                 // 在子目录项中查找
256                 // match inode.children.get(name) {
257                 //     Some(_) => {}
258                 //     None => kdebug!("Sysfs find {} error", name),
259                 // }
260                 return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone());
261             }
262         }
263     }
264 
265     fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, SystemError> {
266         Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
267     }
268 
269     fn list(&self) -> Result<Vec<String>, SystemError> {
270         let info = self.metadata()?;
271         if info.file_type != FileType::Dir {
272             return Err(SystemError::ENOTDIR);
273         }
274 
275         let mut keys: Vec<String> = Vec::new();
276         keys.push(String::from("."));
277         keys.push(String::from(".."));
278         keys.append(&mut self.0.lock().children.keys().cloned().collect());
279 
280         return Ok(keys);
281     }
282 }
283 
284 impl LockedSysFSInode {
285     fn do_create_with_data(
286         &self,
287         mut guard: SpinLockGuard<SysFSInode>,
288         _name: &str,
289         _file_type: FileType,
290         _mode: u32,
291         _data: usize,
292     ) -> Result<Arc<dyn IndexNode>, SystemError> {
293         if guard.metadata.file_type != FileType::Dir {
294             return Err(SystemError::ENOTDIR);
295         }
296 
297         // 如果有重名的,则返回
298         if guard.children.contains_key(_name) {
299             return Err(SystemError::EEXIST);
300         }
301 
302         // 创建inode
303         let result: Arc<LockedSysFSInode> = Arc::new(LockedSysFSInode(SpinLock::new(SysFSInode {
304             parent: guard.self_ref.clone(),
305             self_ref: Weak::default(),
306             children: BTreeMap::new(),
307             metadata: Metadata {
308                 dev_id: 0,
309                 inode_id: generate_inode_id(),
310                 size: 0,
311                 blk_size: 0,
312                 blocks: 0,
313                 atime: TimeSpec::default(),
314                 mtime: TimeSpec::default(),
315                 ctime: TimeSpec::default(),
316                 file_type: _file_type,
317                 mode: _mode,
318                 nlinks: 1,
319                 uid: 0,
320                 gid: 0,
321                 raw_dev: _data,
322             },
323             fs: guard.fs.clone(),
324         })));
325 
326         // 初始化inode的自引用的weak指针
327         result.0.lock().self_ref = Arc::downgrade(&result);
328 
329         // 将子inode插入父inode的B树中
330         guard.children.insert(String::from(_name), result.clone());
331         return Ok(result);
332     }
333 
334     /// @brief 在当前目录下,创建一个目录
335     /// @param name: 目录名
336     /// @return 成功返回目录inode, 失败返回Err(错误码)
337     #[inline]
338     #[allow(dead_code)]
339     pub fn add_dir(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
340         let guard: SpinLockGuard<SysFSInode> = self.0.lock();
341 
342         if guard.children.contains_key(name) {
343             return Err(SystemError::EEXIST);
344         }
345 
346         match self.do_create_with_data(guard, name, FileType::Dir, 0o755 as u32, 0) {
347             Ok(inode) => return Ok(inode),
348             Err(err) => {
349                 return Err(err);
350             }
351         };
352     }
353 
354     /// @brief 在当前目录下,创建一个二进制文件
355     /// @param name: 文件名
356     /// @return 成功返回Ok(()), 失败返回Err(错误码)
357     #[inline]
358     #[allow(dead_code)]
359     pub fn add_file(&self, name: &str, file: Arc<dyn IndexNode>) -> Result<(), SystemError> {
360         let mut this = self.0.lock();
361 
362         if this.children.contains_key(name) {
363             return Err(SystemError::EEXIST);
364         }
365 
366         this.children.insert(name.to_string(), file);
367         return Ok(());
368     }
369 
370     /// @brief 为该inode创建硬链接
371     /// @param None
372     /// @return 当前inode强引用
373     #[inline]
374     #[allow(dead_code)]
375     pub fn link(&self) -> Arc<dyn IndexNode> {
376         return self
377             .0
378             .lock()
379             .self_ref
380             .clone()
381             .upgrade()
382             .ok_or(SystemError::E2BIG)
383             .unwrap();
384     }
385 
386     pub fn remove(&self, name: &str) -> Result<(), SystemError> {
387         let x = self
388             .0
389             .lock()
390             .children
391             .remove(name)
392             .ok_or(SystemError::ENOENT)?;
393 
394         drop(x);
395         return Ok(());
396     }
397 }
398 
399 /// @brief sys文件i节点(无锁)
400 #[derive(Debug)]
401 pub struct SysFSInode {
402     /// 指向父Inode的弱引用
403     parent: Weak<LockedSysFSInode>,
404     /// 指向自身的弱引用
405     self_ref: Weak<LockedSysFSInode>,
406     /// 子Inode的B树
407     children: BTreeMap<String, Arc<dyn IndexNode>>,
408     /// 指向inode所在的文件系统对象的指针
409     fs: Weak<SysFS>,
410     /// INode 元数据
411     metadata: Metadata,
412 }
413 
414 impl SysFSInode {
415     pub fn new(dev_type_: FileType, mode_: u32, data_: usize) -> Self {
416         return Self::new_with_parent(Weak::default(), dev_type_, mode_, data_);
417     }
418 
419     pub fn new_with_parent(
420         parent: Weak<LockedSysFSInode>,
421         dev_type_: FileType,
422         mode_: u32,
423         data_: usize,
424     ) -> Self {
425         return SysFSInode {
426             parent: parent,
427             self_ref: Weak::default(),
428             children: BTreeMap::new(),
429             metadata: Metadata {
430                 dev_id: 1,
431                 inode_id: generate_inode_id(),
432                 size: 0,
433                 blk_size: 0,
434                 blocks: 0,
435                 atime: TimeSpec::default(),
436                 mtime: TimeSpec::default(),
437                 ctime: TimeSpec::default(),
438                 file_type: dev_type_, // 文件夹
439                 mode: mode_,
440                 nlinks: 1,
441                 uid: 0,
442                 gid: 0,
443                 raw_dev: data_,
444             },
445             fs: Weak::default(),
446         };
447     }
448 }
449