diff --git a/docs/kernel/filesystem/index.rst b/docs/kernel/filesystem/index.rst index 1442e1e7..ff0c01b0 100644 --- a/docs/kernel/filesystem/index.rst +++ b/docs/kernel/filesystem/index.rst @@ -12,4 +12,5 @@ todo: 由于文件系统模块重构,文档暂时不可用,预计在2023年4 overview vfs/index sysfs + kernfs diff --git a/docs/kernel/filesystem/kernfs.md b/docs/kernel/filesystem/kernfs.md new file mode 100644 index 00000000..d2822257 --- /dev/null +++ b/docs/kernel/filesystem/kernfs.md @@ -0,0 +1,22 @@ +# KernFS + +:::{note} + +Maintainer: +- 龙进 +::: + +## 1. 简介 +  KernFS是一个伪文件系统,它充当其它内核文件系统的容器,面向用户提供文件接口。其核心功能就是,当kernfs的文件被读/写或者触发回调点的时候,将会对预设的回调函数进行调用,触发其它内核文件系统的操作。 + +  这种设计使得SysFS和文件系统的基本操作解耦,KernFS作为SysFS的承载物,使得SysFS能更专注于KObject的管理,让代码更加优雅。 + +  在未来,DragonOS的内核子系统,或者其它的内核文件系统,可以使用KernFS作为文件系统操作的承载物,让系统管理的逻辑与具体的文件系统操作解除耦合。 + +## 2. 使用方法 + +  以SysFS为例,新创建一个KernFS实例,作为SysFS的文件系统接口,然后挂载到`/sys`目录下。接着sysfs实现上层逻辑,管理KObject,每个上层的Kobject里面都需要包含KernFSInode。并且通过设置KernFSInode的PrivateData,使得KernFS能够根据Inode获取到其指向的KObject或者sysfs的attribute。并且在创建KernFSInode的时候,为具体的Inode传入不同的callback,以此实现“不同的Inode在读写时能够触发不同的回调行为”。 + +  当发生回调时,KernFS会把回调信息、私有信息传入到回调函数中,让回调函数能够根据传入的信息,获取到对应的KObject或者sysfs的attribute,从而实现sysfs提供的高层功能。 + +  从上述描述我们能够看出:KernFS就是通过存储上层文件系统的回调函数、回调信息,来实现“把具体文件操作与高层管理逻辑进行解耦”的目的。 diff --git a/kernel/src/driver/disk/ahci/ahci_inode.rs b/kernel/src/driver/disk/ahci/ahci_inode.rs index 6c6fc138..b3f0f1fd 100644 --- a/kernel/src/driver/disk/ahci/ahci_inode.rs +++ b/kernel/src/driver/disk/ahci/ahci_inode.rs @@ -1,6 +1,7 @@ use crate::driver::base::block::block_device::BlockDevice; use crate::filesystem::devfs::{DevFS, DeviceINode}; use crate::filesystem::vfs::file::FileMode; +use crate::filesystem::vfs::syscall::ModeType; use crate::filesystem::vfs::{ core::generate_inode_id, make_rawdev, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus, @@ -49,7 +50,7 @@ impl LockedAhciInode { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::BlockDevice, // 文件夹,block设备,char设备 - mode: 0o666, + mode: ModeType::from_bits_truncate(0o666), nlinks: 1, uid: 0, gid: 0, diff --git a/kernel/src/driver/keyboard/ps2_keyboard.rs b/kernel/src/driver/keyboard/ps2_keyboard.rs index c669adca..63c38642 100644 --- a/kernel/src/driver/keyboard/ps2_keyboard.rs +++ b/kernel/src/driver/keyboard/ps2_keyboard.rs @@ -6,7 +6,10 @@ use crate::{ driver::tty::tty_device::TTY_DEVICES, filesystem::{ devfs::{devfs_register, DevFS, DeviceINode}, - vfs::{core::generate_inode_id, file::FileMode, FileType, IndexNode, Metadata, PollStatus}, + vfs::{ + core::generate_inode_id, file::FileMode, syscall::ModeType, FileType, IndexNode, + Metadata, PollStatus, + }, }, include::bindings::bindings::{vfs_file_operations_t, vfs_file_t, vfs_index_node_t}, libs::{keyboard_parser::TypeOneFSM, rwlock::RwLock, spinlock::SpinLock}, @@ -59,7 +62,7 @@ impl LockedPS2KeyBoardInode { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::CharDevice, // 文件夹,block设备,char设备 - mode: 0o666, + mode: ModeType::from_bits_truncate(0o666), nlinks: 1, uid: 0, gid: 0, diff --git a/kernel/src/driver/tty/tty_device.rs b/kernel/src/driver/tty/tty_device.rs index b200a80a..a988a07a 100644 --- a/kernel/src/driver/tty/tty_device.rs +++ b/kernel/src/driver/tty/tty_device.rs @@ -7,7 +7,10 @@ use alloc::{ use crate::{ filesystem::{ devfs::{devfs_register, DevFS, DeviceINode}, - vfs::{file::FileMode, FilePrivateData, FileType, IndexNode, Metadata, ROOT_INODE}, + vfs::{ + file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata, + ROOT_INODE, + }, }, kerror, libs::{ @@ -271,7 +274,7 @@ impl IndexNode for TtyDevice { impl TtyDevicePrivateData { pub fn new(name: &str) -> RwLock { - let mut metadata = Metadata::new(FileType::CharDevice, 0o755); + let mut metadata = Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)); metadata.size = TtyCore::STDIN_BUF_SIZE as i64; return RwLock::new(TtyDevicePrivateData { name: name.to_string(), diff --git a/kernel/src/driver/uart/uart_device.rs b/kernel/src/driver/uart/uart_device.rs index f16d5442..953871b4 100644 --- a/kernel/src/driver/uart/uart_device.rs +++ b/kernel/src/driver/uart/uart_device.rs @@ -15,7 +15,10 @@ use crate::{ filesystem::{ devfs::{devfs_register, DevFS, DeviceINode}, sysfs::bus::{bus_device_register, bus_driver_register}, - vfs::{FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus}, + vfs::{ + syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, + PollStatus, + }, }, include::bindings::bindings::{io_in8, io_out8}, kinfo, @@ -314,7 +317,7 @@ impl IndexNode for LockedUart { &self, name: &str, file_type: FileType, - mode: u32, + mode: ModeType, ) -> Result, SystemError> { // 若文件系统没有实现此方法,则默认调用其create_with_data方法。如果仍未实现,则会得到一个Err(-EOPNOTSUPP_OR_ENOTSUP)的返回值 return self.create_with_data(name, file_type, mode, 0); @@ -324,7 +327,7 @@ impl IndexNode for LockedUart { &self, _name: &str, _file_type: FileType, - _mode: u32, + _mode: ModeType, _data: usize, ) -> Result, SystemError> { // 若文件系统没有实现此方法,则返回“不支持” diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index 36edc061..dae7d6e6 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -5,6 +5,7 @@ pub mod zero_dev; use super::vfs::{ core::{generate_inode_id, ROOT_INODE}, file::FileMode, + syscall::ModeType, FileSystem, FileType, FsInfo, IndexNode, Metadata, PollStatus, }; use crate::{ @@ -55,7 +56,7 @@ impl DevFS { let root: Arc = Arc::new(LockedDevFSInode(SpinLock::new( // /dev 的权限设置为 读+执行,root 可以读写 // root 的 parent 是空指针 - DevFSInode::new(FileType::Dir, 0o755 as u32, 0), + DevFSInode::new(FileType::Dir, ModeType::from_bits_truncate(0o755), 0), ))); let devfs: Arc = Arc::new(DevFS { root_inode: root }); @@ -109,7 +110,11 @@ impl DevFS { // 字节设备挂载在 /dev/char FileType::CharDevice => { if let Err(_) = dev_root_inode.find("char") { - dev_root_inode.create("char", FileType::Dir, 0o755)?; + dev_root_inode.create( + "char", + FileType::Dir, + ModeType::from_bits_truncate(0o755), + )?; } let any_char_inode = dev_root_inode.find("char")?; @@ -128,7 +133,11 @@ impl DevFS { } FileType::BlockDevice => { if let Err(_) = dev_root_inode.find("block") { - dev_root_inode.create("block", FileType::Dir, 0o755)?; + dev_root_inode.create( + "block", + FileType::Dir, + ModeType::from_bits_truncate(0o755), + )?; } let any_block_inode = dev_root_inode.find("block")?; @@ -212,14 +221,14 @@ pub struct DevFSInode { } 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(dev_type_: FileType, mode: ModeType, data_: usize) -> Self { + return Self::new_with_parent(Weak::default(), dev_type_, mode, data_); } pub fn new_with_parent( parent: Weak, dev_type_: FileType, - mode_: u32, + mode: ModeType, data_: usize, ) -> Self { return DevFSInode { @@ -236,7 +245,7 @@ impl DevFSInode { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: dev_type_, // 文件夹 - mode: mode_, + mode, nlinks: 1, uid: 0, gid: 0, @@ -255,7 +264,13 @@ impl LockedDevFSInode { return Err(SystemError::EEXIST); } - match self.do_create_with_data(guard, name, FileType::Dir, 0o755 as u32, 0) { + match self.do_create_with_data( + guard, + name, + FileType::Dir, + ModeType::from_bits_truncate(0o755), + 0, + ) { Ok(inode) => inode, Err(err) => { return Err(err); @@ -291,17 +306,17 @@ impl LockedDevFSInode { fn do_create_with_data( &self, mut guard: SpinLockGuard, - _name: &str, - _file_type: FileType, - _mode: u32, - _data: usize, + name: &str, + file_type: FileType, + mode: ModeType, + data: usize, ) -> Result, SystemError> { if guard.metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } // 如果有重名的,则返回 - if guard.children.contains_key(_name) { + if guard.children.contains_key(name) { return Err(SystemError::EEXIST); } @@ -319,12 +334,12 @@ impl LockedDevFSInode { atime: TimeSpec::default(), mtime: TimeSpec::default(), ctime: TimeSpec::default(), - file_type: _file_type, - mode: _mode, + file_type, + mode, nlinks: 1, uid: 0, gid: 0, - raw_dev: _data, + raw_dev: data, }, fs: guard.fs.clone(), }))); @@ -333,7 +348,7 @@ impl LockedDevFSInode { result.0.lock().self_ref = Arc::downgrade(&result); // 将子inode插入父inode的B树中 - guard.children.insert(String::from(_name), result.clone()); + guard.children.insert(String::from(name), result.clone()); return Ok(result); } } @@ -359,7 +374,7 @@ impl IndexNode for LockedDevFSInode { &self, name: &str, file_type: FileType, - mode: u32, + mode: ModeType, data: usize, ) -> Result, SystemError> { // 获取当前inode @@ -399,7 +414,7 @@ impl IndexNode for LockedDevFSInode { return Err(SystemError::ENOTDIR); } - match ino { + match ino.into() { 0 => { return Ok(String::from(".")); } @@ -412,14 +427,24 @@ impl IndexNode for LockedDevFSInode { let mut key: Vec = inode .children .keys() - .filter(|k| inode.children.get(*k).unwrap().metadata().unwrap().inode_id == ino) + .filter(|k| { + inode + .children + .get(*k) + .unwrap() + .metadata() + .unwrap() + .inode_id + .into() + == ino + }) .cloned() .collect(); match key.len() { 0=>{return Err(SystemError::ENOENT);} 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) + _ => 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) } } } diff --git a/kernel/src/filesystem/devfs/null_dev.rs b/kernel/src/filesystem/devfs/null_dev.rs index b64e118c..897315dc 100644 --- a/kernel/src/filesystem/devfs/null_dev.rs +++ b/kernel/src/filesystem/devfs/null_dev.rs @@ -1,5 +1,6 @@ use crate::filesystem::vfs::file::FileMode; use crate::filesystem::vfs::make_rawdev; +use crate::filesystem::vfs::syscall::ModeType; use crate::filesystem::vfs::{ core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus, }; @@ -43,7 +44,7 @@ impl LockedNullInode { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::CharDevice, // 文件夹,block设备,char设备 - mode: 0o666, + mode: ModeType::from_bits_truncate(0o666), nlinks: 1, uid: 0, gid: 0, diff --git a/kernel/src/filesystem/devfs/zero_dev.rs b/kernel/src/filesystem/devfs/zero_dev.rs index 7385fe3c..27a854a6 100644 --- a/kernel/src/filesystem/devfs/zero_dev.rs +++ b/kernel/src/filesystem/devfs/zero_dev.rs @@ -1,5 +1,6 @@ use crate::filesystem::vfs::file::FileMode; use crate::filesystem::vfs::make_rawdev; +use crate::filesystem::vfs::syscall::ModeType; use crate::filesystem::vfs::{ core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus, }; @@ -43,7 +44,7 @@ impl LockedZeroInode { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::CharDevice, // 文件夹,block设备,char设备 - mode: 0o666, + mode: ModeType::from_bits_truncate(0o666), nlinks: 1, uid: 0, gid: 0, diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 1277afaa..2cad039c 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -13,6 +13,7 @@ use crate::{ filesystem::vfs::{ core::generate_inode_id, file::{FileMode, FilePrivateData}, + syscall::ModeType, FileSystem, FileType, IndexNode, InodeId, Metadata, PollStatus, }, kerror, @@ -189,7 +190,7 @@ impl LockedFATInode { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: file_type, - mode: 0o777, + mode: ModeType::from_bits_truncate(0o777), nlinks: 1, uid: 0, gid: 0, @@ -308,7 +309,7 @@ impl FATFileSystem { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::Dir, - mode: 0o777, + mode: ModeType::from_bits_truncate(0o777), nlinks: 1, uid: 0, gid: 0, @@ -1421,7 +1422,7 @@ impl IndexNode for LockedFATInode { &self, name: &str, file_type: FileType, - _mode: u32, + _mode: ModeType, ) -> Result, SystemError> { // 由于FAT32不支持文件权限的功能,因此忽略mode参数 let mut guard: SpinLockGuard = self.0.lock(); @@ -1627,7 +1628,7 @@ impl IndexNode for LockedFATInode { if guard.metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } - match ino { + match ino.into() { 0 => { return Ok(String::from(".")); } @@ -1640,14 +1641,24 @@ impl IndexNode for LockedFATInode { let mut key: Vec = guard .children .keys() - .filter(|k| guard.children.get(*k).unwrap().metadata().unwrap().inode_id == ino) + .filter(|k| { + guard + .children + .get(*k) + .unwrap() + .metadata() + .unwrap() + .inode_id + .into() + == ino + }) .cloned() .collect(); match key.len() { 0=>{return Err(SystemError::ENOENT);} 1=>{return Ok(key.remove(0));} - _ => panic!("FatFS get_entry_name: key.len()={key_len}>1, current inode_id={inode_id}, to find={to_find}", key_len=key.len(), inode_id = guard.metadata.inode_id, to_find=ino) + _ => panic!("FatFS get_entry_name: key.len()={key_len}>1, current inode_id={inode_id:?}, to find={to_find:?}", key_len=key.len(), inode_id = guard.metadata.inode_id, to_find=ino) } } } diff --git a/kernel/src/filesystem/kernfs/callback.rs b/kernel/src/filesystem/kernfs/callback.rs new file mode 100644 index 00000000..492ae314 --- /dev/null +++ b/kernel/src/filesystem/kernfs/callback.rs @@ -0,0 +1,73 @@ +use crate::{ + filesystem::{sysfs::SysFSKernPrivateData, vfs::PollStatus}, + libs::spinlock::SpinLockGuard, + syscall::SystemError, +}; +use alloc::sync::Arc; +use core::fmt::Debug; + +use super::KernFSInode; + +/// KernFS文件的回调接口 +/// +/// 当用户态程序打开、读取、写入、关闭文件时,kernfs会调用相应的回调函数。 +pub trait KernFSCallback: Send + Sync + Debug { + fn open(&self, data: KernCallbackData) -> Result<(), SystemError>; + + fn read( + &self, + data: KernCallbackData, + buf: &mut [u8], + offset: usize, + ) -> Result; + + fn write( + &self, + data: KernCallbackData, + buf: &[u8], + offset: usize, + ) -> Result; + + fn poll(&self, data: KernCallbackData) -> Result; +} + +/// KernFS文件的回调数据 +#[derive(Debug)] +pub struct KernCallbackData<'a> { + kern_inode: Arc, + private_data: SpinLockGuard<'a, Option>, +} + +#[allow(dead_code)] +impl<'a> KernCallbackData<'a> { + pub fn new( + kern_inode: Arc, + private_data: SpinLockGuard<'a, Option>, + ) -> Self { + Self { + kern_inode, + private_data, + } + } + + #[inline(always)] + pub fn kern_inode(&self) -> &Arc { + return &self.kern_inode; + } + + #[inline(always)] + pub fn private_data(&self) -> &Option { + return &self.private_data; + } + + #[inline(always)] + pub fn private_data_mut(&mut self) -> &mut Option { + return &mut self.private_data; + } +} + +#[allow(dead_code)] +#[derive(Debug)] +pub enum KernInodePrivateData { + SysFS(SysFSKernPrivateData), +} diff --git a/kernel/src/filesystem/kernfs/mod.rs b/kernel/src/filesystem/kernfs/mod.rs new file mode 100644 index 00000000..344c48ca --- /dev/null +++ b/kernel/src/filesystem/kernfs/mod.rs @@ -0,0 +1,486 @@ +use core::{fmt::Debug, intrinsics::unlikely}; + +use alloc::{ + string::String, + sync::{Arc, Weak}, + vec::Vec, +}; +use hashbrown::HashMap; + +use crate::{ + libs::{rwlock::RwLock, spinlock::SpinLock}, + syscall::SystemError, + time::TimeSpec, +}; + +use self::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData}; + +use super::vfs::{ + core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, + FileType, FsInfo, IndexNode, InodeId, Metadata, PollStatus, +}; + +pub mod callback; + +#[derive(Debug)] +pub struct KernFS { + root_inode: Arc, +} + +impl FileSystem for KernFS { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn info(&self) -> FsInfo { + return FsInfo { + blk_dev_id: 0, + max_name_len: KernFS::MAX_NAMELEN, + }; + } + + fn root_inode(&self) -> Arc { + return self.root_inode.clone(); + } +} + +impl KernFS { + pub const MAX_NAMELEN: usize = 4096; + + #[allow(dead_code)] + pub fn new() -> Arc { + let root_inode = Self::create_root_inode(); + let fs = Arc::new(Self { + root_inode: root_inode.clone(), + }); + + { + let ptr = root_inode.as_ref() as *const KernFSInode as *mut KernFSInode; + unsafe { + (*ptr).self_ref = Arc::downgrade(&root_inode); + } + } + root_inode.inner.lock().parent = Arc::downgrade(&root_inode); + *root_inode.fs.write() = Arc::downgrade(&fs); + return fs; + } + + fn create_root_inode() -> Arc { + let metadata = Metadata { + size: 0, + mode: ModeType::from_bits_truncate(0o755), + uid: 0, + gid: 0, + blk_size: 0, + blocks: 0, + atime: TimeSpec::new(0, 0), + mtime: TimeSpec::new(0, 0), + ctime: TimeSpec::new(0, 0), + dev_id: 0, + inode_id: generate_inode_id(), + file_type: FileType::Dir, + nlinks: 1, + raw_dev: 0, + }; + let root_inode = Arc::new(KernFSInode { + inner: SpinLock::new(InnerKernFSInode { + parent: Weak::new(), + metadata, + }), + self_ref: Weak::new(), + fs: RwLock::new(Weak::new()), + private_data: SpinLock::new(None), + callback: None, + children: SpinLock::new(HashMap::new()), + inode_type: KernInodeType::Dir, + }); + + return root_inode; + } +} + +#[derive(Debug)] +pub struct KernFSInode { + inner: SpinLock, + /// 指向当前Inode所属的文件系统的弱引用 + fs: RwLock>, + /// 指向自身的弱引用 + self_ref: Weak, + /// 私有数据 + private_data: SpinLock>, + /// 回调函数 + callback: Option<&'static dyn KernFSCallback>, + /// 子Inode + children: SpinLock>>, + /// Inode类型 + inode_type: KernInodeType, +} + +#[derive(Debug)] +pub struct InnerKernFSInode { + parent: Weak, + + /// 当前inode的元数据 + metadata: Metadata, +} + +impl IndexNode for KernFSInode { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> { + if let Some(callback) = self.callback { + let callback_data = + KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock()); + return callback.open(callback_data); + } + + return Ok(()); + } + + fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { + return Ok(()); + } + + fn metadata(&self) -> Result { + return Ok(self.inner.lock().metadata.clone()); + } + + fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> { + // 若文件系统没有实现此方法,则返回“不支持” + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn resize(&self, _len: usize) -> Result<(), SystemError> { + return Ok(()); + } + + fn create_with_data( + &self, + _name: &str, + _file_type: FileType, + _mode: ModeType, + _data: usize, + ) -> Result, SystemError> { + // 应当通过kernfs的其它方法来创建文件,而不能从用户态直接调用此方法。 + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn link(&self, _name: &str, _other: &Arc) -> Result<(), SystemError> { + // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn unlink(&self, _name: &str) -> Result<(), SystemError> { + // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn rmdir(&self, _name: &str) -> Result<(), SystemError> { + // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn move_( + &self, + _old_name: &str, + _target: &Arc, + _new_name: &str, + ) -> Result<(), SystemError> { + // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn find(&self, name: &str) -> Result, SystemError> { + if unlikely(name.len() > KernFS::MAX_NAMELEN) { + return Err(SystemError::ENAMETOOLONG); + } + if unlikely(self.inode_type != KernInodeType::Dir) { + return Err(SystemError::ENOTDIR); + } + let x: Arc = self + .children + .lock() + .get(name) + .cloned() + .ok_or(SystemError::ENOENT)?; + return Ok(x); + } + + fn get_entry_name(&self, ino: InodeId) -> Result { + if self.inode_type != KernInodeType::Dir { + return Err(SystemError::ENOTDIR); + } + + let children = self.children.lock(); + let r = children + .iter() + .find(|(_, v)| v.metadata().unwrap().inode_id == ino) + .map(|(k, _)| k.clone()); + + return r.ok_or(SystemError::ENOENT); + } + + fn get_entry_name_and_metadata(&self, ino: InodeId) -> Result<(String, Metadata), SystemError> { + // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。 + let name = self.get_entry_name(ino)?; + let entry = self.find(&name)?; + return Ok((name, entry.metadata()?)); + } + + fn ioctl(&self, _cmd: u32, _data: usize) -> Result { + // 若文件系统没有实现此方法,则返回“不支持” + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn truncate(&self, _len: usize) -> Result<(), SystemError> { + // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + fn sync(&self) -> Result<(), SystemError> { + return Ok(()); + } + + fn fs(&self) -> Arc { + return self.fs.read().upgrade().unwrap(); + } + + fn list(&self) -> Result, SystemError> { + let mut list = Vec::new(); + for (name, _) in self.children.lock().iter() { + list.push(name.clone()); + } + return Ok(list); + } + + fn poll(&self) -> Result { + // todo: 根据inode的具体attribute,返回PollStatus + return Ok(PollStatus::READ | PollStatus::WRITE); + } + + fn read_at( + &self, + offset: usize, + len: usize, + buf: &mut [u8], + _data: &mut FilePrivateData, + ) -> Result { + if self.inode_type != KernInodeType::File { + return Err(SystemError::EISDIR); + } + + if self.callback.is_none() { + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + let callback_data = + KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock()); + return self + .callback + .as_ref() + .unwrap() + .read(callback_data, &mut buf[..len], offset); + } + + fn write_at( + &self, + offset: usize, + len: usize, + buf: &[u8], + _data: &mut FilePrivateData, + ) -> Result { + if self.inode_type != KernInodeType::File { + return Err(SystemError::EISDIR); + } + + if self.callback.is_none() { + return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + } + + let callback_data = + KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock()); + return self + .callback + .as_ref() + .unwrap() + .write(callback_data, &buf[..len], offset); + } +} + +impl KernFSInode { + /// 在当前inode下增加子目录 + /// + /// ## 参数 + /// + /// - `name`:子目录名称 + /// - `mode`:子目录权限 + /// - `private_data`:子目录私有数据 + /// - `callback`:子目录回调函数 + /// + /// ## 返回值 + /// + /// - 成功:子目录inode + /// - 失败:错误码 + #[allow(dead_code)] + #[inline] + pub fn add_dir( + &self, + name: String, + mode: ModeType, + private_data: Option, + callback: Option<&'static dyn KernFSCallback>, + ) -> Result, SystemError> { + if unlikely(self.inode_type != KernInodeType::Dir) { + return Err(SystemError::ENOTDIR); + } + + return self.inner_create(name, KernInodeType::Dir, mode, private_data, callback); + } + + /// 在当前inode下增加文件 + /// + /// ## 参数 + /// + /// - `name`:文件名称 + /// - `mode`:文件权限 + /// - `private_data`:文件私有数据 + /// - `callback`:文件回调函数 + /// + /// ## 返回值 + /// + /// - 成功:文件inode + /// - 失败:错误码 + #[allow(dead_code)] + #[inline] + pub fn add_file( + &self, + name: String, + mode: ModeType, + private_data: Option, + callback: Option<&'static dyn KernFSCallback>, + ) -> Result, SystemError> { + if unlikely(self.inode_type != KernInodeType::Dir) { + return Err(SystemError::ENOTDIR); + } + + return self.inner_create(name, KernInodeType::File, mode, private_data, callback); + } + + fn inner_create( + &self, + name: String, + file_type: KernInodeType, + mode: ModeType, + private_data: Option, + callback: Option<&'static dyn KernFSCallback>, + ) -> Result, SystemError> { + let metadata = Metadata { + size: 0, + mode, + uid: 0, + gid: 0, + blk_size: 0, + blocks: 0, + atime: TimeSpec::new(0, 0), + mtime: TimeSpec::new(0, 0), + ctime: TimeSpec::new(0, 0), + dev_id: 0, + inode_id: generate_inode_id(), + file_type: file_type.into(), + nlinks: 1, + raw_dev: 0, + }; + + let new_inode: Arc = Self::new( + self.self_ref.upgrade().unwrap(), + metadata, + KernInodeType::Dir, + private_data, + callback, + ); + + self.children.lock().insert(name, new_inode.clone()); + + return Ok(new_inode); + } + + /// 在当前inode下删除子目录或者文件 + /// + /// 如果要删除的是子目录,且子目录不为空,则返回ENOTEMPTY + /// + /// ## 参数 + /// + /// - `name`:子目录或者文件名称 + /// + /// ## 返回值 + /// + /// - 成功:() + /// - 失败:错误码 + #[allow(dead_code)] + pub fn remove(&self, name: &str) -> Result<(), SystemError> { + if unlikely(self.inode_type != KernInodeType::Dir) { + return Err(SystemError::ENOTDIR); + } + + let mut children = self.children.lock(); + let inode = children.get(name).ok_or(SystemError::ENOENT)?; + if inode.children.lock().is_empty() { + children.remove(name); + return Ok(()); + } else { + return Err(SystemError::ENOTEMPTY); + } + } + + pub(self) fn new( + parent: Arc, + metadata: Metadata, + inode_type: KernInodeType, + private_data: Option, + callback: Option<&'static dyn KernFSCallback>, + ) -> Arc { + let inode = Arc::new(KernFSInode { + inner: SpinLock::new(InnerKernFSInode { + parent: Arc::downgrade(&parent), + metadata, + }), + self_ref: Weak::new(), + fs: RwLock::new(Weak::new()), + private_data: SpinLock::new(private_data), + callback, + children: SpinLock::new(HashMap::new()), + inode_type, + }); + + { + let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode; + unsafe { + (*ptr).self_ref = Arc::downgrade(&inode); + } + } + *inode.fs.write() = Arc::downgrade( + parent + .fs() + .as_any_ref() + .downcast_ref() + .expect("KernFSInode::new: parent is not a KernFS instance"), + ); + return inode; + } +} +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(self) enum KernInodeType { + Dir, + File, +} + +impl Into for KernInodeType { + fn into(self) -> FileType { + match self { + KernInodeType::Dir => FileType::Dir, + KernInodeType::File => FileType::File, + } + } +} diff --git a/kernel/src/filesystem/mod.rs b/kernel/src/filesystem/mod.rs index c848c897..107143a6 100644 --- a/kernel/src/filesystem/mod.rs +++ b/kernel/src/filesystem/mod.rs @@ -1,5 +1,6 @@ pub mod devfs; pub mod fat; +pub mod kernfs; pub mod mbr; pub mod procfs; pub mod ramfs; diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index 8880b3b8..3c7a822f 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -26,6 +26,7 @@ use crate::{ use super::vfs::{ file::{FileMode, FilePrivateData}, + syscall::ModeType, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus, }; @@ -262,7 +263,7 @@ impl ProcFS { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::Dir, - mode: 0o777, + mode: ModeType::from_bits_truncate(0o777), nlinks: 1, uid: 0, gid: 0, @@ -294,10 +295,18 @@ impl ProcFS { // 获取当前inode let proc: Arc = self.root_inode(); // 创建对应进程文件夹 - let _pf: Arc = proc.create(&pid.to_string(), FileType::Dir, 0o777)?; + let _pf: Arc = proc.create( + &pid.to_string(), + FileType::Dir, + ModeType::from_bits_truncate(0o777), + )?; // 创建相关文件 // status文件 - let binding: Arc = _pf.create("status", FileType::File, 0o777)?; + let binding: Arc = _pf.create( + "status", + FileType::File, + ModeType::from_bits_truncate(0o777), + )?; let _sf: &LockedProcFSInode = binding .as_any_ref() .downcast_ref::() @@ -482,7 +491,7 @@ impl IndexNode for LockedProcFSInode { &self, name: &str, file_type: FileType, - mode: u32, + mode: ModeType, data: usize, ) -> Result, SystemError> { // 获取当前inode @@ -623,7 +632,7 @@ impl IndexNode for LockedProcFSInode { return Err(SystemError::ENOTDIR); } - match ino { + match ino.into() { 0 => { return Ok(String::from(".")); } @@ -636,14 +645,25 @@ impl IndexNode for LockedProcFSInode { let mut key: Vec = inode .children .keys() - .filter(|k| inode.children.get(*k).unwrap().0.lock().metadata.inode_id == ino) + .filter(|k| { + inode + .children + .get(*k) + .unwrap() + .0 + .lock() + .metadata + .inode_id + .into() + == ino + }) .cloned() .collect(); match key.len() { 0=>{return Err(SystemError::ENOENT);} 1=>{return Ok(key.remove(0));} - _ => panic!("Procfs 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) + _ => panic!("Procfs 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) } } } diff --git a/kernel/src/filesystem/ramfs/mod.rs b/kernel/src/filesystem/ramfs/mod.rs index e2cef7c7..0342cf73 100644 --- a/kernel/src/filesystem/ramfs/mod.rs +++ b/kernel/src/filesystem/ramfs/mod.rs @@ -15,7 +15,8 @@ use crate::{ }; use super::vfs::{ - file::FilePrivateData, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus, + file::FilePrivateData, syscall::ModeType, FileSystem, FsInfo, IndexNode, InodeId, Metadata, + PollStatus, }; /// RamFS的inode名称的最大长度 @@ -90,7 +91,7 @@ impl RamFS { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::Dir, - mode: 0o777, + mode: ModeType::from_bits_truncate(0o777), nlinks: 1, uid: 0, gid: 0, @@ -258,7 +259,7 @@ impl IndexNode for LockedRamFSInode { &self, name: &str, file_type: FileType, - mode: u32, + mode: ModeType, data: usize, ) -> Result, SystemError> { // 获取当前inode @@ -425,7 +426,7 @@ impl IndexNode for LockedRamFSInode { return Err(SystemError::ENOTDIR); } - match ino { + match ino.into() { 0 => { return Ok(String::from(".")); } @@ -438,14 +439,25 @@ impl IndexNode for LockedRamFSInode { let mut key: Vec = inode .children .keys() - .filter(|k| inode.children.get(*k).unwrap().0.lock().metadata.inode_id == ino) + .filter(|k| { + inode + .children + .get(*k) + .unwrap() + .0 + .lock() + .metadata + .inode_id + .into() + == ino + }) .cloned() .collect(); match key.len() { 0=>{return Err(SystemError::ENOENT);} 1=>{return Ok(key.remove(0));} - _ => panic!("Ramfs 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) + _ => panic!("Ramfs 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) } } } diff --git a/kernel/src/filesystem/sysfs/dir.rs b/kernel/src/filesystem/sysfs/dir.rs new file mode 100644 index 00000000..3a03f468 --- /dev/null +++ b/kernel/src/filesystem/sysfs/dir.rs @@ -0,0 +1,32 @@ +#![allow(dead_code)] +use alloc::sync::Arc; + +use crate::driver::base::device::KObject; + +use super::AttributeGroup; + +#[derive(Debug)] +pub struct SysKernDirPriv { + kobj: Arc, + attribute_group: Option<&'static dyn AttributeGroup>, +} + +impl SysKernDirPriv { + pub fn new( + kobj: Arc, + attribute_group: Option<&'static dyn AttributeGroup>, + ) -> Self { + Self { + kobj, + attribute_group, + } + } + + pub fn kobj(&self) -> Arc { + self.kobj.clone() + } + + pub fn attribute_group(&self) -> Option<&'static dyn AttributeGroup> { + self.attribute_group + } +} diff --git a/kernel/src/filesystem/sysfs/file.rs b/kernel/src/filesystem/sysfs/file.rs new file mode 100644 index 00000000..af8c003a --- /dev/null +++ b/kernel/src/filesystem/sysfs/file.rs @@ -0,0 +1,21 @@ +#![allow(dead_code)] +use super::Attribute; + +#[derive(Debug)] +pub struct SysKernFilePriv { + attribute: Option<&'static dyn Attribute>, + // todo: 增加bin attribute,它和attribute二选一,只能有一个为Some +} + +impl SysKernFilePriv { + pub fn new(attribute: Option<&'static dyn Attribute>) -> Self { + if attribute.is_none() { + panic!("attribute can't be None"); + } + return Self { attribute }; + } + + pub fn attribute(&self) -> Option<&'static dyn Attribute> { + self.attribute + } +} diff --git a/kernel/src/filesystem/sysfs/mod.rs b/kernel/src/filesystem/sysfs/mod.rs index 7ec65af2..9d55276e 100644 --- a/kernel/src/filesystem/sysfs/mod.rs +++ b/kernel/src/filesystem/sysfs/mod.rs @@ -1,9 +1,13 @@ +use core::fmt::Debug; + +use self::{dir::SysKernDirPriv, file::SysKernFilePriv}; + use super::vfs::{ - core::generate_inode_id, file::FileMode, FileSystem, FileType, FsInfo, IndexNode, Metadata, - PollStatus, + core::generate_inode_id, file::FileMode, syscall::ModeType, FileSystem, FileType, FsInfo, + IndexNode, Metadata, PollStatus, }; use crate::{ - driver::base::platform::platform_bus_init, + driver::base::{device::KObject, platform::platform_bus_init}, filesystem::{sysfs::bus::sys_bus_init, vfs::ROOT_INODE}, kdebug, kinfo, libs::{ @@ -23,6 +27,8 @@ use alloc::{ pub mod bus; pub mod class; pub mod devices; +mod dir; +mod file; pub mod fs; const SYSFS_MAX_NAMELEN: usize = 64; @@ -98,7 +104,7 @@ impl SysFS { let root: Arc = Arc::new(LockedSysFSInode(SpinLock::new( // /sys 的权限设置为 读+执行,root 可以读写 // root 的 parent 是空指针 - SysFSInode::new(FileType::Dir, 0o755 as u32, 0), + SysFSInode::new(FileType::Dir, ModeType::from_bits_truncate(0o755), 0), ))); let sysfs: Arc = Arc::new(SysFS { root_inode: root }); @@ -220,7 +226,7 @@ impl IndexNode for LockedSysFSInode { return Err(SystemError::ENOTDIR); } - match ino { + match ino.into() { 0 => { return Ok(String::from(".")); } @@ -233,14 +239,24 @@ impl IndexNode for LockedSysFSInode { let mut key: Vec = inode .children .keys() - .filter(|k| inode.children.get(*k).unwrap().metadata().unwrap().inode_id == ino) + .filter(|k| { + inode + .children + .get(*k) + .unwrap() + .metadata() + .unwrap() + .inode_id + .into() + == ino + }) .cloned() .collect(); match key.len() { 0=>{return Err(SystemError::ENOENT);} 1=>{return Ok(key.remove(0));} - _ => 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) + _ => 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) } } } @@ -294,17 +310,17 @@ impl LockedSysFSInode { fn do_create_with_data( &self, mut guard: SpinLockGuard, - _name: &str, - _file_type: FileType, - _mode: u32, - _data: usize, + name: &str, + file_type: FileType, + mode: ModeType, + data: usize, ) -> Result, SystemError> { if guard.metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } // 如果有重名的,则返回 - if guard.children.contains_key(_name) { + if guard.children.contains_key(name) { return Err(SystemError::EEXIST); } @@ -322,12 +338,12 @@ impl LockedSysFSInode { atime: TimeSpec::default(), mtime: TimeSpec::default(), ctime: TimeSpec::default(), - file_type: _file_type, - mode: _mode, + file_type, + mode, nlinks: 1, uid: 0, gid: 0, - raw_dev: _data, + raw_dev: data, }, fs: guard.fs.clone(), }))); @@ -336,7 +352,7 @@ impl LockedSysFSInode { result.0.lock().self_ref = Arc::downgrade(&result); // 将子inode插入父inode的B树中 - guard.children.insert(String::from(_name), result.clone()); + guard.children.insert(String::from(name), result.clone()); return Ok(result); } @@ -352,7 +368,13 @@ impl LockedSysFSInode { return Err(SystemError::EEXIST); } - match self.do_create_with_data(guard, name, FileType::Dir, 0o755 as u32, 0) { + match self.do_create_with_data( + guard, + name, + FileType::Dir, + ModeType::from_bits_truncate(0o755), + 0, + ) { Ok(inode) => return Ok(inode), Err(err) => { return Err(err); @@ -421,14 +443,14 @@ pub struct SysFSInode { } impl SysFSInode { - 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(file_type: FileType, mode: ModeType, data_: usize) -> Self { + return Self::new_with_parent(Weak::default(), file_type, mode, data_); } pub fn new_with_parent( parent: Weak, - dev_type_: FileType, - mode_: u32, + file_type: FileType, + mode: ModeType, data_: usize, ) -> Self { return SysFSInode { @@ -444,8 +466,8 @@ impl SysFSInode { atime: TimeSpec::default(), mtime: TimeSpec::default(), ctime: TimeSpec::default(), - file_type: dev_type_, // 文件夹 - mode: mode_, + file_type, + mode, nlinks: 1, uid: 0, gid: 0, @@ -485,3 +507,24 @@ pub fn sysfs_init() -> Result<(), SystemError> { return result.unwrap(); } + +/// SysFS在KernFS的inode中的私有信息 +#[allow(dead_code)] +#[derive(Debug)] +pub enum SysFSKernPrivateData { + Dir(SysKernDirPriv), + File(SysKernFilePriv), +} + +/// sysfs文件目录的属性组 +pub trait AttributeGroup: Debug + Send + Sync { + fn name(&self) -> &str; + fn attrs(&self) -> &[&'static dyn Attribute]; + fn is_visible(&self, kobj: Arc, attr: &dyn Attribute) -> bool; +} + +/// sysfs文件的属性 +pub trait Attribute: Debug + Send + Sync { + fn name(&self) -> &str; + fn mode(&self) -> ModeType; +} diff --git a/kernel/src/filesystem/vfs/core.rs b/kernel/src/filesystem/vfs/core.rs index bc67d5be..904b9784 100644 --- a/kernel/src/filesystem/vfs/core.rs +++ b/kernel/src/filesystem/vfs/core.rs @@ -1,7 +1,4 @@ -use core::{ - hint::spin_loop, - sync::atomic::{AtomicUsize, Ordering}, -}; +use core::{hint::spin_loop, sync::atomic::Ordering}; use alloc::{format, string::ToString, sync::Arc}; @@ -16,7 +13,7 @@ use crate::{ procfs::procfs_init, ramfs::RamFS, sysfs::sysfs_init, - vfs::{mount::MountFS, FileSystem, FileType}, + vfs::{mount::MountFS, syscall::ModeType, AtomicInodeId, FileSystem, FileType}, }, include::bindings::bindings::PAGE_4K_SIZE, kdebug, kerror, kinfo, @@ -31,8 +28,8 @@ use super::{file::FileMode, utils::rsplit_path, IndexNode, InodeId}; /// [0]: 对应'.'目录项 /// [1]: 对应'..'目录项 pub fn generate_inode_id() -> InodeId { - static INO: AtomicUsize = AtomicUsize::new(1); - return INO.fetch_add(1, Ordering::SeqCst); + static INO: AtomicInodeId = AtomicInodeId::new(InodeId::new(1)); + return INO.fetch_add(InodeId::new(1), Ordering::SeqCst); } static mut __ROOT_INODE: Option> = None; @@ -59,13 +56,13 @@ pub extern "C" fn vfs_init() -> i32 { // 创建文件夹 root_inode - .create("proc", FileType::Dir, 0o777) + .create("proc", FileType::Dir, ModeType::from_bits_truncate(0o755)) .expect("Failed to create /proc"); root_inode - .create("dev", FileType::Dir, 0o777) + .create("dev", FileType::Dir, ModeType::from_bits_truncate(0o755)) .expect("Failed to create /dev"); root_inode - .create("sys", FileType::Dir, 0o777) + .create("sys", FileType::Dir, ModeType::from_bits_truncate(0o755)) .expect("Failed to create /sys"); kdebug!("dir in root:{:?}", root_inode.list()); @@ -94,7 +91,11 @@ fn do_migrate( let r = new_root_inode.find(mountpoint_name); let mountpoint = if r.is_err() { new_root_inode - .create(mountpoint_name, FileType::Dir, 0o777) + .create( + mountpoint_name, + FileType::Dir, + ModeType::from_bits_truncate(0o755), + ) .expect(format!("Failed to create '/{mountpoint_name}' in migrating").as_str()) } else { r.unwrap() @@ -191,8 +192,11 @@ pub fn do_mkdir(path: &str, _mode: FileMode) -> Result { let parent_inode: Arc = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; // 创建文件夹 - let _create_inode: Arc = - parent_inode.create(filename, FileType::Dir, 0o777)?; + let _create_inode: Arc = parent_inode.create( + filename, + FileType::Dir, + ModeType::from_bits_truncate(0o755), + )?; } else { // 不需要创建文件,因此返回错误码 return Err(errno); diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index c0d8ef27..21c694ee 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -14,7 +14,7 @@ use crate::{ syscall::SystemError, }; -use super::{Dirent, FileType, IndexNode, Metadata}; +use super::{Dirent, FileType, IndexNode, InodeId, Metadata}; /// 文件私有信息的枚举类型 #[derive(Debug, Clone)] @@ -185,7 +185,7 @@ impl File { } /// @brief 根据inode号获取子目录项的名字 - pub fn get_entry_name(&self, ino: usize) -> Result { + pub fn get_entry_name(&self, ino: InodeId) -> Result { return self.inode.get_entry_name(ino); } @@ -276,7 +276,7 @@ impl File { let name_bytes: &[u8] = name.as_bytes(); self.offset += 1; - dirent.d_ino = sub_inode.metadata().unwrap().inode_id as u64; + dirent.d_ino = sub_inode.metadata().unwrap().inode_id.into() as u64; dirent.d_off = 0; dirent.d_reclen = 0; dirent.d_type = sub_inode.metadata().unwrap().file_type.get_file_type_num() as u8; diff --git a/kernel/src/filesystem/vfs/mod.rs b/kernel/src/filesystem/vfs/mod.rs index d037e068..a6bbf483 100644 --- a/kernel/src/filesystem/vfs/mod.rs +++ b/kernel/src/filesystem/vfs/mod.rs @@ -7,20 +7,20 @@ pub mod mount; pub mod syscall; mod utils; -use ::core::{any::Any, fmt::Debug}; +use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize}; use alloc::{string::String, sync::Arc, vec::Vec}; use crate::{libs::casting::DowncastArc, syscall::SystemError, time::TimeSpec}; -use self::{core::generate_inode_id, file::FileMode}; +use self::{core::generate_inode_id, file::FileMode, syscall::ModeType}; pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS}; /// vfs容许的最大的路径名称长度 pub const MAX_PATHLEN: usize = 1024; -/// 定义inode号的类型为usize -pub type InodeId = usize; +// 定义inode号 +int_like!(InodeId, AtomicInodeId, usize, AtomicUsize); /// 文件的类型 #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -185,7 +185,7 @@ pub trait IndexNode: Any + Sync + Send + Debug { &self, name: &str, file_type: FileType, - mode: u32, + mode: ModeType, ) -> Result, SystemError> { // 若文件系统没有实现此方法,则默认调用其create_with_data方法。如果仍未实现,则会得到一个Err(-EOPNOTSUPP_OR_ENOTSUP)的返回值 return self.create_with_data(name, file_type, mode, 0); @@ -204,7 +204,7 @@ pub trait IndexNode: Any + Sync + Send + Debug { &self, _name: &str, _file_type: FileType, - _mode: u32, + _mode: ModeType, _data: usize, ) -> Result, SystemError> { // 若文件系统没有实现此方法,则返回“不支持” @@ -477,7 +477,7 @@ pub struct Metadata { pub file_type: FileType, /// 权限 - pub mode: u32, + pub mode: ModeType, /// 硬链接的数量 pub nlinks: usize, @@ -496,7 +496,7 @@ impl Default for Metadata { fn default() -> Self { return Self { dev_id: 0, - inode_id: 0, + inode_id: InodeId::new(0), size: 0, blk_size: 0, blocks: 0, @@ -504,7 +504,7 @@ impl Default for Metadata { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::File, - mode: 0, + mode: ModeType::empty(), nlinks: 1, uid: 0, gid: 0, @@ -551,7 +551,7 @@ pub struct Dirent { } impl Metadata { - pub fn new(file_type: FileType, mode: u32) -> Self { + pub fn new(file_type: FileType, mode: ModeType) -> Self { Metadata { dev_id: 0, inode_id: generate_inode_id(), diff --git a/kernel/src/filesystem/vfs/mount.rs b/kernel/src/filesystem/vfs/mount.rs index e34fe910..ffa84d65 100644 --- a/kernel/src/filesystem/vfs/mount.rs +++ b/kernel/src/filesystem/vfs/mount.rs @@ -10,7 +10,9 @@ use alloc::{ use crate::{libs::spinlock::SpinLock, syscall::SystemError}; -use super::{file::FileMode, FilePrivateData, FileSystem, FileType, IndexNode, InodeId}; +use super::{ + file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, InodeId, +}; /// @brief 挂载文件系统 /// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载 @@ -141,7 +143,7 @@ impl IndexNode for MountFSInode { &self, name: &str, file_type: FileType, - mode: u32, + mode: ModeType, data: usize, ) -> Result, SystemError> { return Ok(MountFSInode { @@ -213,7 +215,7 @@ impl IndexNode for MountFSInode { &self, name: &str, file_type: FileType, - mode: u32, + mode: ModeType, ) -> Result, SystemError> { return Ok(MountFSInode { inner_inode: self.inner_inode.create(name, file_type, mode)?, diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 23cabd69..985f3f4a 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -31,6 +31,7 @@ pub const SEEK_MAX: u32 = 3; bitflags! { /// 文件类型和权限 + #[repr(C)] pub struct ModeType: u32 { /// 掩码 const S_IFMT = 0o0_170_000; @@ -154,8 +155,11 @@ impl Syscall { let parent_inode: Arc = ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; // 创建文件 - let inode: Arc = - parent_inode.create(filename, FileType::File, 0o777)?; + let inode: Arc = parent_inode.create( + filename, + FileType::File, + ModeType::from_bits_truncate(0o755), + )?; inode } else { // 不需要创建文件,因此返回错误码 @@ -649,7 +653,7 @@ impl Syscall { let metadata = file.lock().metadata()?; kstat.size = metadata.size as i64; kstat.dev_id = metadata.dev_id as u64; - kstat.inode = metadata.inode_id as u64; + kstat.inode = metadata.inode_id.into() as u64; kstat.blcok_size = metadata.blk_size as i64; kstat.blocks = metadata.blocks as u64; @@ -664,7 +668,7 @@ impl Syscall { kstat.uid = metadata.uid as i32; kstat.gid = metadata.gid as i32; kstat.rdev = metadata.raw_dev as i64; - kstat.mode.bits = metadata.mode; + kstat.mode = metadata.mode; match file.lock().file_type() { FileType::File => kstat.mode.insert(ModeType::S_IFMT), FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR), diff --git a/kernel/src/ipc/pipe.rs b/kernel/src/ipc/pipe.rs index 2cbc480f..f771bf22 100644 --- a/kernel/src/ipc/pipe.rs +++ b/kernel/src/ipc/pipe.rs @@ -2,8 +2,8 @@ use crate::{ arch::{sched::sched, CurrentIrqArch}, exception::InterruptArch, filesystem::vfs::{ - core::generate_inode_id, file::FileMode, FilePrivateData, FileSystem, FileType, IndexNode, - Metadata, PollStatus, + core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, + FileType, IndexNode, Metadata, PollStatus, }, libs::{spinlock::SpinLock, wait_queue::WaitQueue}, process::ProcessState, @@ -56,7 +56,7 @@ impl LockedPipeInode { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::Pipe, - mode: 0o666, + mode: ModeType::from_bits_truncate(0o666), nlinks: 1, uid: 0, gid: 0, diff --git a/kernel/src/net/socket.rs b/kernel/src/net/socket.rs index 66bca24b..31a10fea 100644 --- a/kernel/src/net/socket.rs +++ b/kernel/src/net/socket.rs @@ -10,7 +10,7 @@ use smoltcp::{ use crate::{ arch::rand::rand, driver::net::NetDriver, - filesystem::vfs::{FileType, IndexNode, Metadata, PollStatus}, + filesystem::vfs::{syscall::ModeType, FileType, IndexNode, Metadata, PollStatus}, kerror, kwarn, libs::{ spinlock::{SpinLock, SpinLockGuard}, @@ -1215,7 +1215,7 @@ impl IndexNode for SocketInode { fn metadata(&self) -> Result { let meta = Metadata { - mode: 0o777, + mode: ModeType::from_bits_truncate(0o755), file_type: FileType::Socket, ..Default::default() };