123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- /// 导出devfs的模块
- pub mod null_dev;
- pub mod zero_dev;
- use super::vfs::{
- core::{generate_inode_id, ROOT_INODE},
- FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus, file::FileMode,
- };
- use crate::{
- include::bindings::bindings::{EEXIST, EISDIR, ENOENT, ENOTDIR, ENOTSUP},
- kdebug, kerror,
- libs::spinlock::{SpinLock, SpinLockGuard},
- time::TimeSpec,
- };
- use alloc::{
- collections::BTreeMap,
- string::{String, ToString},
- sync::{Arc, Weak},
- vec::Vec,
- };
- const DEVFS_MAX_NAMELEN: usize = 64;
- /// @brief dev文件系统
- #[derive(Debug)]
- pub struct DevFS {
- // 文件系统根节点
- root_inode: Arc<LockedDevFSInode>,
- }
- impl FileSystem for DevFS {
- fn as_any_ref(&self) -> &dyn core::any::Any {
- self
- }
- fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> {
- return self.root_inode.clone();
- }
- fn info(&self) -> super::vfs::FsInfo {
- return FsInfo {
- blk_dev_id: 0,
- max_name_len: DEVFS_MAX_NAMELEN,
- };
- }
- }
- impl DevFS {
- pub fn new() -> Arc<Self> {
- // 初始化root inode
- let root: Arc<LockedDevFSInode> = Arc::new(LockedDevFSInode(SpinLock::new(
- // /dev 的权限设置为 读+执行,root 可以读写
- // root 的 parent 是空指针
- DevFSInode::new(FileType::Dir, 0o755 as u32, 0),
- )));
- let devfs: Arc<DevFS> = Arc::new(DevFS { root_inode: root });
- // 对root inode加锁,并继续完成初始化工作
- let mut root_guard: SpinLockGuard<DevFSInode> = devfs.root_inode.0.lock();
- root_guard.parent = Arc::downgrade(&devfs.root_inode);
- root_guard.self_ref = Arc::downgrade(&devfs.root_inode);
- root_guard.fs = Arc::downgrade(&devfs);
- // 释放锁
- drop(root_guard);
- // 创建文件夹
- let root: &Arc<LockedDevFSInode> = &devfs.root_inode;
- root.add_dir("char")
- .expect("DevFS: Failed to create /dev/char");
- root.add_dir("block")
- .expect("DevFS: Failed to create /dev/block");
- devfs.register_bultinin_device();
- // kdebug!("ls /dev: {:?}", root.list());
- return devfs;
- }
- /// @brief 注册系统内部自带的设备
- fn register_bultinin_device(&self) {
- use null_dev::LockedNullInode;
- use zero_dev::LockedZeroInode;
- let dev_root: Arc<LockedDevFSInode> = self.root_inode.clone();
- dev_root
- .add_dev("null", LockedNullInode::new())
- .expect("DevFS: Failed to register /dev/null");
- dev_root
- .add_dev("zero", LockedZeroInode::new())
- .expect("DevFS: Failed to register /dev/zero");
- }
- /// @brief 在devfs内注册设备
- ///
- /// @param name 设备名称
- /// @param device 设备节点的结构体
- pub fn register_device<T: DeviceINode>(&self, name: &str, device: Arc<T>) -> Result<(), i32> {
- let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
- match device.metadata().unwrap().file_type {
- // 字节设备挂载在 /dev/char
- FileType::CharDevice => {
- if let Err(_) = dev_root_inode.find("char") {
- dev_root_inode.create("char", FileType::Dir, 0o755)?;
- }
- let any_char_inode = dev_root_inode.find("char")?;
- let dev_char_inode: &LockedDevFSInode = any_char_inode
- .as_any_ref()
- .downcast_ref::<LockedDevFSInode>()
- .unwrap();
- dev_char_inode.add_dev(name, device.clone())?;
- device.set_fs(dev_char_inode.0.lock().fs.clone());
- }
- FileType::BlockDevice => {
- if let Err(_) = dev_root_inode.find("block") {
- dev_root_inode.create("block", FileType::Dir, 0o755)?;
- }
- let any_block_inode = dev_root_inode.find("block")?;
- let dev_block_inode: &LockedDevFSInode = any_block_inode
- .as_any_ref()
- .downcast_ref::<LockedDevFSInode>()
- .unwrap();
- dev_block_inode.add_dev(name, device.clone())?;
- device.set_fs(dev_block_inode.0.lock().fs.clone());
- }
- _ => {
- return Err(-(ENOTSUP as i32));
- }
- }
- return Ok(());
- }
- /// @brief 卸载设备
- pub fn unregister_device<T: DeviceINode>(&self, name: &str, device: Arc<T>) -> Result<(), i32> {
- let dev_root_inode: Arc<LockedDevFSInode> = self.root_inode.clone();
- match device.metadata().unwrap().file_type {
- // 字节设备挂载在 /dev/char
- FileType::CharDevice => {
- if let Err(_) = dev_root_inode.find("char") {
- return Err(-(ENOENT as i32));
- }
- let any_char_inode = dev_root_inode.find("char")?;
- let dev_char_inode = any_char_inode
- .as_any_ref()
- .downcast_ref::<LockedDevFSInode>()
- .unwrap();
- // TODO: 调用设备的卸载接口(当引入卸载接口之后)
- dev_char_inode.remove(name)?;
- }
- FileType::BlockDevice => {
- if let Err(_) = dev_root_inode.find("block") {
- return Err(-(ENOENT as i32));
- }
- let any_block_inode = dev_root_inode.find("block")?;
- let dev_block_inode = any_block_inode
- .as_any_ref()
- .downcast_ref::<LockedDevFSInode>()
- .unwrap();
- dev_block_inode.remove(name)?;
- }
- _ => {
- return Err(-(ENOTSUP as i32));
- }
- }
- return Ok(());
- }
- }
- /// @brief dev文件i节点(锁)
- #[derive(Debug)]
- pub struct LockedDevFSInode(SpinLock<DevFSInode>);
- /// @brief dev文件i节点(无锁)
- #[derive(Debug)]
- pub struct DevFSInode {
- /// 指向父Inode的弱引用
- parent: Weak<LockedDevFSInode>,
- /// 指向自身的弱引用
- self_ref: Weak<LockedDevFSInode>,
- /// 子Inode的B树
- children: BTreeMap<String, Arc<dyn IndexNode>>,
- /// 指向inode所在的文件系统对象的指针
- fs: Weak<DevFS>,
- /// INode 元数据
- metadata: Metadata,
- }
- impl DevFSInode {
- pub fn new(dev_type_: FileType, mode_: u32, data_: usize) -> Self {
- return Self::new_with_parent(Weak::default(), dev_type_, mode_, data_);
- }
- pub fn new_with_parent(
- parent: Weak<LockedDevFSInode>,
- dev_type_: FileType,
- mode_: u32,
- data_: usize,
- ) -> Self {
- return DevFSInode {
- parent: parent,
- self_ref: Weak::default(),
- children: BTreeMap::new(),
- metadata: Metadata {
- dev_id: 1,
- inode_id: generate_inode_id(),
- size: 0,
- blk_size: 0,
- blocks: 0,
- atime: TimeSpec::default(),
- mtime: TimeSpec::default(),
- ctime: TimeSpec::default(),
- file_type: dev_type_, // 文件夹
- mode: mode_,
- nlinks: 1,
- uid: 0,
- gid: 0,
- raw_dev: data_,
- },
- fs: Weak::default(),
- };
- }
- }
- impl LockedDevFSInode {
- pub fn add_dir(&self, name: &str) -> Result<(), i32> {
- let guard:SpinLockGuard<DevFSInode> = self.0.lock();
- if guard.children.contains_key(name) {
- return Err(-(EEXIST as i32));
- }
- match self.do_create_with_data(guard, name, FileType::Dir, 0o755 as u32, 0) {
- Ok(inode) => inode,
- Err(err) => {
- return Err(err);
- }
- };
- return Ok(());
- }
- pub fn add_dev(&self, name: &str, dev: Arc<dyn IndexNode>) -> Result<(), i32> {
- let mut this = self.0.lock();
- if this.children.contains_key(name) {
- return Err(-(EEXIST as i32));
- }
- this.children.insert(name.to_string(), dev);
- return Ok(());
- }
- pub fn remove(&self, name: &str) -> Result<(), i32> {
- let x = self
- .0
- .lock()
- .children
- .remove(name)
- .ok_or(-(ENOENT as i32))?;
- drop(x);
- return Ok(());
- }
- fn do_create_with_data(&self, mut guard: SpinLockGuard<DevFSInode>,_name: &str,
- _file_type: FileType,
- _mode: u32,
- _data: usize,) -> Result<Arc<dyn IndexNode>, i32>{
- if guard.metadata.file_type != FileType::Dir {
- return Err(-(ENOTDIR as i32));
- }
- // 如果有重名的,则返回
- if guard.children.contains_key(_name) {
- return Err(-(EEXIST as i32));
- }
- // 创建inode
- let result: Arc<LockedDevFSInode> = Arc::new(LockedDevFSInode(SpinLock::new(DevFSInode {
- parent: guard.self_ref.clone(),
- self_ref: Weak::default(),
- children: BTreeMap::new(),
- metadata: Metadata {
- dev_id: 0,
- inode_id: generate_inode_id(),
- size: 0,
- blk_size: 0,
- blocks: 0,
- atime: TimeSpec::default(),
- mtime: TimeSpec::default(),
- ctime: TimeSpec::default(),
- file_type: _file_type,
- mode: _mode,
- nlinks: 1,
- uid: 0,
- gid: 0,
- raw_dev: _data,
- },
- fs: guard.fs.clone(),
- })));
- // 初始化inode的自引用的weak指针
- result.0.lock().self_ref = Arc::downgrade(&result);
- // 将子inode插入父inode的B树中
- guard.children.insert(String::from(_name), result.clone());
- return Ok(result);
- }
- }
- impl IndexNode for LockedDevFSInode {
- fn as_any_ref(&self) -> &dyn core::any::Any {
- self
- }
- fn open(&self, _data: &mut super::vfs::FilePrivateData, _mode: &FileMode) -> Result<(), i32> {
- return Ok(());
- }
- fn close(&self, _data: &mut super::vfs::FilePrivateData) -> Result<(), i32> {
- return Ok(());
- }
-
- fn create_with_data(
- &self,
- name: &str,
- file_type: FileType,
- mode: u32,
- data: usize,
- ) -> Result<Arc<dyn IndexNode>, i32> {
- // 获取当前inode
- let guard:SpinLockGuard<DevFSInode> = self.0.lock();
- // 如果当前inode不是文件夹,则返回
- return self.do_create_with_data(guard, name, file_type, mode, data);
- }
- fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, i32> {
- let inode = self.0.lock();
- if inode.metadata.file_type != FileType::Dir {
- return Err(-(ENOTDIR as i32));
- }
- match name {
- "" | "." => {
- return Ok(inode.self_ref.upgrade().ok_or(-(ENOENT as i32))?);
- }
- ".." => {
- return Ok(inode.parent.upgrade().ok_or(-(ENOENT as i32))?);
- }
- name => {
- // 在子目录项中查找
- return Ok(inode.children.get(name).ok_or(-(ENOENT as i32))?.clone());
- }
- }
- }
- fn fs(&self) -> Arc<dyn FileSystem> {
- return self.0.lock().fs.upgrade().unwrap();
- }
- fn get_entry_name(&self, ino: super::vfs::InodeId) -> Result<String, i32> {
- let inode: SpinLockGuard<DevFSInode> = self.0.lock();
- if inode.metadata.file_type != FileType::Dir {
- return Err(-(ENOTDIR as i32));
- }
- match ino {
- 0 => {
- return Ok(String::from("."));
- }
- 1 => {
- return Ok(String::from(".."));
- }
- ino => {
- // 暴力遍历所有的children,判断inode id是否相同
- // TODO: 优化这里,这个地方性能很差!
- let mut key: Vec<String> = inode
- .children
- .keys()
- .filter(|k| inode.children.get(*k).unwrap().metadata().unwrap().inode_id == ino)
- .cloned()
- .collect();
- match key.len() {
- 0=>{return Err(-(ENOENT as i32));}
- 1=>{return Ok(key.remove(0));}
- _ => 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)
- }
- }
- }
- }
- fn ioctl(&self, _cmd: u32, _data: usize) -> Result<usize, i32> {
- Err(-(ENOTSUP as i32))
- }
- fn list(&self) -> Result<Vec<String>, i32> {
- let info = self.metadata()?;
- if info.file_type != FileType::Dir {
- return Err(-(ENOTDIR as i32));
- }
- let mut keys: Vec<String> = Vec::new();
- keys.push(String::from("."));
- keys.push(String::from(".."));
- keys.append(&mut self.0.lock().children.keys().cloned().collect());
- return Ok(keys);
- }
- fn metadata(&self) -> Result<Metadata, i32> {
- return Ok(self.0.lock().metadata.clone());
- }
- fn set_metadata(&self, metadata: &Metadata) -> Result<(), i32> {
- let mut inode = self.0.lock();
- inode.metadata.atime = metadata.atime;
- inode.metadata.mtime = metadata.mtime;
- inode.metadata.ctime = metadata.ctime;
- inode.metadata.mode = metadata.mode;
- inode.metadata.uid = metadata.uid;
- inode.metadata.gid = metadata.gid;
- return Ok(());
- }
- fn poll(&self) -> Result<super::vfs::PollStatus, i32> {
- // 加锁
- let inode: SpinLockGuard<DevFSInode> = self.0.lock();
- // 检查当前inode是否为一个文件夹,如果是的话,就返回错误
- if inode.metadata.file_type == FileType::Dir {
- return Err(-(EISDIR as i32));
- }
- return Ok(PollStatus {
- flags: PollStatus::READ_MASK | PollStatus::WRITE_MASK,
- });
- }
- /// 读设备 - 应该调用设备的函数读写,而不是通过文件系统读写
- fn read_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &mut [u8],
- _data: &mut super::vfs::file::FilePrivateData,
- ) -> Result<usize, i32> {
- Err(-(ENOTSUP as i32))
- }
- /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写
- fn write_at(
- &self,
- _offset: usize,
- _len: usize,
- _buf: &[u8],
- _data: &mut super::vfs::file::FilePrivateData,
- ) -> Result<usize, i32> {
- Err(-(ENOTSUP as i32))
- }
- }
- /// @brief 所有的设备INode都需要额外实现这个trait
- pub trait DeviceINode: IndexNode {
- fn set_fs(&self, fs: Weak<DevFS>);
- // TODO: 增加 unregister 方法
- }
- /// @brief 获取devfs实例的强类型不可变引用
- macro_rules! devfs_exact_ref {
- () => {{
- let devfs_inode: Result<Arc<dyn IndexNode>, i32> = ROOT_INODE().find("dev");
- if let Err(e) = devfs_inode {
- kerror!("failed to get DevFS ref. errcode = {e}");
- return Err(-(ENOENT as i32));
- }
- let binding = devfs_inode.unwrap();
- let devfs_inode: &LockedDevFSInode = binding
- .as_any_ref()
- .downcast_ref::<LockedDevFSInode>()
- .unwrap();
- let binding = devfs_inode.fs();
- binding
- }
- .as_any_ref()
- .downcast_ref::<DevFS>()
- .unwrap()};
- }
- /// @brief devfs的设备注册函数
- pub fn devfs_register<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), i32> {
- return devfs_exact_ref!().register_device(name, device);
- }
- /// @brief devfs的设备卸载函数
- #[allow(dead_code)]
- pub fn devfs_unregister<T: DeviceINode>(name: &str, device: Arc<T>) -> Result<(), i32> {
- return devfs_exact_ref!().unregister_device(name, device);
- }
|