From 1074eb34e784aa2adfc5b9e0d89fa4b7e6ea03ef Mon Sep 17 00:00:00 2001 From: Samuel Dai Date: Mon, 15 Apr 2024 13:02:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(filesystem):=20=E5=BC=95=E5=85=A5Umount?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E8=B0=83=E7=94=A8=20(#719)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(filesystem): 引入Umount系统调用 * 将所有ENOSYS误用更正 * 修复了一个使同一个挂载点可以挂载2个文件系统的bug * 统一注释,增强程序稳定性,统一接口。注意:Umount时在fatfs的路径要使用大写,此受限于当前文件系统设计。 --- README.md | 2 +- README_EN.md | 2 +- docs/kernel/libs/lib_ui/scm.md | 12 +- kernel/src/arch/x86_64/kvm/mod.rs | 4 +- kernel/src/arch/x86_64/kvm/vmx/ept.rs | 2 +- kernel/src/arch/x86_64/kvm/vmx/vcpu.rs | 8 +- kernel/src/driver/acpi/sysfs.rs | 6 +- kernel/src/driver/base/device/bus.rs | 8 +- kernel/src/driver/base/device/dd.rs | 6 +- kernel/src/driver/base/device/mod.rs | 2 +- kernel/src/driver/base/kobject.rs | 4 +- kernel/src/driver/base/subsys.rs | 2 +- kernel/src/driver/disk/ahci/ahci_inode.rs | 6 +- .../driver/input/ps2_mouse/ps_mouse_device.rs | 10 +- kernel/src/driver/keyboard/ps2_keyboard.rs | 2 +- kernel/src/filesystem/devfs/mod.rs | 88 ++-- kernel/src/filesystem/devfs/null_dev.rs | 2 +- kernel/src/filesystem/devfs/zero_dev.rs | 2 +- kernel/src/filesystem/devpts/mod.rs | 10 +- kernel/src/filesystem/fat/fs.rs | 86 ++-- kernel/src/filesystem/kernfs/callback.rs | 4 +- kernel/src/filesystem/kernfs/mod.rs | 25 +- kernel/src/filesystem/procfs/mod.rs | 77 ++-- kernel/src/filesystem/ramfs/mod.rs | 131 +++--- kernel/src/filesystem/sysfs/mod.rs | 20 +- kernel/src/filesystem/vfs/core.rs | 224 ++++++---- kernel/src/filesystem/vfs/file.rs | 2 +- kernel/src/filesystem/vfs/mod.rs | 227 ++++++++-- kernel/src/filesystem/vfs/mount.rs | 419 +++++++++++++++--- kernel/src/filesystem/vfs/syscall.rs | 45 +- kernel/src/filesystem/vfs/utils.rs | 74 ++++ kernel/src/ipc/pipe.rs | 2 +- kernel/src/ipc/signal.rs | 2 +- kernel/src/ipc/syscall.rs | 2 +- kernel/src/libs/lib_ui/screen_manager.rs | 12 +- kernel/src/mm/syscall.rs | 4 +- kernel/src/mm/ucontext.rs | 2 +- kernel/src/syscall/mod.rs | 8 + kernel/src/time/clocksource.rs | 12 +- kernel/src/virt/kvm/kvm_dev.rs | 8 +- kernel/src/virt/kvm/vcpu_dev.rs | 6 +- kernel/src/virt/kvm/vm_dev.rs | 8 +- user/apps/test_ramfs/.gitignore | 1 + user/apps/test_ramfs/Makefile | 20 + user/apps/test_ramfs/main.c | 115 +++++ user/dadk/config/test_ramfs-0.1.0.dadk | 23 + 46 files changed, 1274 insertions(+), 463 deletions(-) create mode 100644 user/apps/test_ramfs/.gitignore create mode 100644 user/apps/test_ramfs/Makefile create mode 100644 user/apps/test_ramfs/main.c create mode 100644 user/dadk/config/test_ramfs-0.1.0.dadk diff --git a/README.md b/README.md index ef51f458..e4379736 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ - [谢润霖](https://github.com/xiaolin2004) - [蔡俊源](https://github.com/SMALLC04) - Kelly -- [戴吕琛](https://github.com/Samuka007) +- [Samuka007](https://github.com/Samuka007) - [杨璐玮](https://github.com/val213) - [何懿聪](https://github.com/GnoCiYeH) - [周凯韬](https://github.com/laokengwt) diff --git a/README_EN.md b/README_EN.md index 3678cfde..8e787f86 100644 --- a/README_EN.md +++ b/README_EN.md @@ -104,7 +104,7 @@ We guarantee that all sponsorship funds and items will be used for: - [谢润霖](https://github.com/xiaolin2004) - [蔡俊源](https://github.com/SMALLC04) - Kelly -- [戴吕琛](https://github.com/Samuka007) +- [Samuka007](https://github.com/Samuka007) - [杨璐玮](https://github.com/val213) - [何懿聪](https://github.com/GnoCiYeH) - [周凯韬](https://github.com/laokengwt) diff --git a/docs/kernel/libs/lib_ui/scm.md b/docs/kernel/libs/lib_ui/scm.md index 418f13fe..f2749e72 100644 --- a/docs/kernel/libs/lib_ui/scm.md +++ b/docs/kernel/libs/lib_ui/scm.md @@ -13,30 +13,30 @@ pub trait ScmUiFramework: Sync + Send + Debug { // 安装ui框架的回调函数 fn install(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 卸载ui框架的回调函数 fn uninstall(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 启用ui框架的回调函数 fn enable(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 禁用ui框架的回调函数 fn disable(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 改变ui框架的帧缓冲区的回调函数 fn change(&self, _buf: ScmBufferInfo) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 获取ScmUiFramework的元数据 /// @return 成功:Ok(ScmUiFramework的元数据) /// 失败:Err(错误码) fn metadata(&self) -> Result { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } ``` diff --git a/kernel/src/arch/x86_64/kvm/mod.rs b/kernel/src/arch/x86_64/kvm/mod.rs index 34e9ee82..c9b8b19a 100644 --- a/kernel/src/arch/x86_64/kvm/mod.rs +++ b/kernel/src/arch/x86_64/kvm/mod.rs @@ -34,14 +34,14 @@ impl X86_64KVMArch { // Check to see if CPU is Intel (“GenuineIntel”). if let Some(vi) = cpuid.get_vendor_info() { if vi.as_str() != "GenuineIntel" { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } // Check processor supports for Virtual Machine Extension (VMX) technology // CPUID.1:ECX.VMX[bit 5] = 1 (Intel Manual: 24.6 Discovering Support for VMX) if let Some(fi) = cpuid.get_feature_info() { if !fi.has_vmx() { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } Ok(()) diff --git a/kernel/src/arch/x86_64/kvm/vmx/ept.rs b/kernel/src/arch/x86_64/kvm/vmx/ept.rs index 6694448d..03223190 100644 --- a/kernel/src/arch/x86_64/kvm/vmx/ept.rs +++ b/kernel/src/arch/x86_64/kvm/vmx/ept.rs @@ -15,7 +15,7 @@ pub fn check_ept_features() -> Result<(), SystemError> { const MTRR_ENABLE_BIT: u64 = 1 << 11; let ia32_mtrr_def_type = unsafe { msr::rdmsr(msr::IA32_MTRR_DEF_TYPE) }; if (ia32_mtrr_def_type & MTRR_ENABLE_BIT) == 0 { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } Ok(()) } diff --git a/kernel/src/arch/x86_64/kvm/vmx/vcpu.rs b/kernel/src/arch/x86_64/kvm/vmx/vcpu.rs index f940069f..b718f5f6 100644 --- a/kernel/src/arch/x86_64/kvm/vmx/vcpu.rs +++ b/kernel/src/arch/x86_64/kvm/vmx/vcpu.rs @@ -419,7 +419,7 @@ impl Vcpu for VmxVcpu { } Err(e) => { kdebug!("[-] CPU does not support Intel VMX: {:?}", e); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } }; @@ -429,7 +429,7 @@ impl Vcpu for VmxVcpu { } Err(_) => { kdebug!("[-] VMX operation is not supported on this processor."); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } @@ -574,12 +574,12 @@ pub fn has_intel_vmx_support() -> Result<(), SystemError> { let cpuid = CpuId::new(); if let Some(vi) = cpuid.get_vendor_info() { if vi.as_str() != "GenuineIntel" { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } if let Some(fi) = cpuid.get_feature_info() { if !fi.has_vmx() { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } Ok(()) diff --git a/kernel/src/driver/acpi/sysfs.rs b/kernel/src/driver/acpi/sysfs.rs index de0df2fd..73e8278f 100644 --- a/kernel/src/driver/acpi/sysfs.rs +++ b/kernel/src/driver/acpi/sysfs.rs @@ -205,11 +205,11 @@ impl AttrAcpiTable { impl Attribute for AttrAcpiTable { fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn name(&self) -> &str { @@ -235,7 +235,7 @@ impl BinAttribute for AttrAcpiTable { _buf: &[u8], _offset: usize, ) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// 展示 ACPI 表的内容 diff --git a/kernel/src/driver/base/device/bus.rs b/kernel/src/driver/base/device/bus.rs index cfbe3429..3287aa9b 100644 --- a/kernel/src/driver/base/device/bus.rs +++ b/kernel/src/driver/base/device/bus.rs @@ -134,9 +134,9 @@ pub trait Bus: Debug + Send + Sync { /// /// ## 默认实现 /// - /// 如果总线不支持该操作,返回`SystemError::EOPNOTSUPP_OR_ENOTSUP` + /// 如果总线不支持该操作,返回`SystemError::ENOSYS` fn probe(&self, _device: &Arc) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn remove(&self, _device: &Arc) -> Result<(), SystemError>; fn sync_state(&self, _device: &Arc) {} @@ -750,7 +750,7 @@ impl Attribute for DriverAttrUnbind { "Intertrait casting not implemented for kobj: {}", kobj.name() ); - SystemError::EOPNOTSUPP_OR_ENOTSUP + SystemError::ENOSYS })?; let bus = driver @@ -799,7 +799,7 @@ impl Attribute for DriverAttrBind { "Intertrait casting not implemented for kobj: {}", kobj.name() ); - SystemError::EOPNOTSUPP_OR_ENOTSUP + SystemError::ENOSYS })?; let bus = driver diff --git a/kernel/src/driver/base/device/dd.rs b/kernel/src/driver/base/device/dd.rs index a5951d38..96ddb340 100644 --- a/kernel/src/driver/base/device/dd.rs +++ b/kernel/src/driver/base/device/dd.rs @@ -502,7 +502,7 @@ impl DriverManager { .and_then(|bus| bus.upgrade()) .ok_or(SystemError::EINVAL)?; let r = bus.probe(device); - if r == Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) { + if r == Err(SystemError::ENOSYS) { kerror!( "call_driver_probe: bus.probe() failed, dev: '{}', err: {:?}", device.name(), @@ -592,7 +592,7 @@ impl Attribute for DeviceAttrStateSynced { "Intertrait casting not implemented for kobj: {}", kobj.name() ); - SystemError::EOPNOTSUPP_OR_ENOTSUP + SystemError::ENOSYS })?; let val = dev.state_synced(); @@ -627,7 +627,7 @@ impl Attribute for DeviceAttrCoredump { "Intertrait casting not implemented for kobj: {}", kobj.name() ); - SystemError::EOPNOTSUPP_OR_ENOTSUP + SystemError::ENOSYS })?; let drv = dev.driver().ok_or(SystemError::EINVAL)?; diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index d4d5583c..459eb842 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -875,7 +875,7 @@ impl Attribute for DeviceAttrDev { "Intertrait casting not implemented for kobj: {}", kobj.name() ); - SystemError::EOPNOTSUPP_OR_ENOTSUP + SystemError::ENOSYS })?; let device_number = dev.id_table().device_number(); diff --git a/kernel/src/driver/base/kobject.rs b/kernel/src/driver/base/kobject.rs index de45c401..a8659c44 100644 --- a/kernel/src/driver/base/kobject.rs +++ b/kernel/src/driver/base/kobject.rs @@ -146,7 +146,7 @@ impl SysFSOps for KObjectSysFSOps { buf: &mut [u8], ) -> Result { let r = attr.show(kobj, buf).map_err(|e| { - if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { + if e == SystemError::ENOSYS { SystemError::EIO } else { e @@ -163,7 +163,7 @@ impl SysFSOps for KObjectSysFSOps { buf: &[u8], ) -> Result { let r = attr.store(kobj, buf).map_err(|e| { - if e == SystemError::EOPNOTSUPP_OR_ENOTSUP { + if e == SystemError::ENOSYS { SystemError::EIO } else { e diff --git a/kernel/src/driver/base/subsys.rs b/kernel/src/driver/base/subsys.rs index 68d4f464..34d587f4 100644 --- a/kernel/src/driver/base/subsys.rs +++ b/kernel/src/driver/base/subsys.rs @@ -201,7 +201,7 @@ pub trait SubSysInterface: Debug + Send + Sync { fn bus(&self) -> Option>; fn set_bus(&self, bus: Option>); fn add_device(&self, _device: &Arc) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn remove_device(&self, device: &Arc); } diff --git a/kernel/src/driver/disk/ahci/ahci_inode.rs b/kernel/src/driver/disk/ahci/ahci_inode.rs index 4805dc9a..ec0bed27 100644 --- a/kernel/src/driver/disk/ahci/ahci_inode.rs +++ b/kernel/src/driver/disk/ahci/ahci_inode.rs @@ -82,11 +82,11 @@ impl IndexNode for LockedAhciInode { _data: SpinLockGuard, _mode: &FileMode, ) -> Result<(), SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn close(&self, _data: SpinLockGuard) -> Result<(), SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn metadata(&self) -> Result { @@ -98,7 +98,7 @@ impl IndexNode for LockedAhciInode { } fn list(&self) -> Result, SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs index ae16bcde..e99f683d 100644 --- a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs @@ -30,8 +30,8 @@ use crate::{ devfs::{devfs_register, DevFS, DeviceINode}, kernfs::KernFSInode, vfs::{ - core::generate_inode_id, syscall::ModeType, FilePrivateData, FileSystem, FileType, - IndexNode, Metadata, + core::generate_inode_id, syscall::ModeType, utils::DName, FilePrivateData, FileSystem, + FileType, IndexNode, Metadata, }, }, libs::{ @@ -627,7 +627,7 @@ impl IndexNode for Ps2MouseDevice { _buf: &[u8], _data: SpinLockGuard, ) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn fs(&self) -> Arc { @@ -655,6 +655,10 @@ impl IndexNode for Ps2MouseDevice { fn resize(&self, _len: usize) -> Result<(), SystemError> { Ok(()) } + + fn dname(&self) -> Result { + Ok(DName::from(self.name())) + } } impl Ps2Device for Ps2MouseDevice {} diff --git a/kernel/src/driver/keyboard/ps2_keyboard.rs b/kernel/src/driver/keyboard/ps2_keyboard.rs index f7e53cd8..4133be0b 100644 --- a/kernel/src/driver/keyboard/ps2_keyboard.rs +++ b/kernel/src/driver/keyboard/ps2_keyboard.rs @@ -171,7 +171,7 @@ impl IndexNode for LockedPS2KeyBoardInode { } fn list(&self) -> Result, SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index 3b19ed97..2a3ffd2e 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -6,6 +6,7 @@ use super::vfs::{ core::{generate_inode_id, ROOT_INODE}, file::FileMode, syscall::ModeType, + utils::DName, FilePrivateData, FileSystem, FileType, FsInfo, IndexNode, Magic, Metadata, SuperBlock, }; use crate::{ @@ -182,7 +183,7 @@ impl DevFS { .expect("DevFS: Failed to register /dev/fb"); } _ => { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } @@ -225,7 +226,7 @@ impl DevFS { dev_block_inode.remove(name)?; } _ => { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } @@ -245,11 +246,13 @@ pub struct DevFSInode { /// 指向自身的弱引用 self_ref: Weak, /// 子Inode的B树 - children: BTreeMap>, + children: BTreeMap>, /// 指向inode所在的文件系统对象的指针 fs: Weak, /// INode 元数据 metadata: Metadata, + /// 目录名 + dname: DName, } impl DevFSInode { @@ -284,6 +287,7 @@ impl DevFSInode { raw_dev: DeviceNumber::from(data_ as u32), }, fs: Weak::default(), + dname: DName::default(), }; } } @@ -292,7 +296,7 @@ impl LockedDevFSInode { pub fn add_dir(&self, name: &str) -> Result<(), SystemError> { let guard: SpinLockGuard = self.0.lock(); - if guard.children.contains_key(name) { + if guard.children.contains_key(&DName::from(name)) { return Err(SystemError::EEXIST); } @@ -314,12 +318,12 @@ impl LockedDevFSInode { pub fn add_dev(&self, name: &str, dev: Arc) -> Result<(), SystemError> { let mut this = self.0.lock(); - - if this.children.contains_key(name) { + let name = DName::from(name); + if this.children.contains_key(&name) { return Err(SystemError::EEXIST); } - this.children.insert(name.to_string(), dev); + this.children.insert(name, dev); return Ok(()); } @@ -328,7 +332,7 @@ impl LockedDevFSInode { .0 .lock() .children - .remove(name) + .remove(&DName::from(name)) .ok_or(SystemError::ENOENT)?; drop(x); @@ -346,9 +350,9 @@ impl LockedDevFSInode { if guard.metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } - + let name = DName::from(name); // 如果有重名的,则返回 - if guard.children.contains_key(name) { + if guard.children.contains_key(&name) { return Err(SystemError::EEXIST); } @@ -374,13 +378,14 @@ impl LockedDevFSInode { raw_dev: DeviceNumber::from(data as u32), }, fs: guard.fs.clone(), + dname: name.clone(), }))); // 初始化inode的自引用的weak指针 result.0.lock().self_ref = Arc::downgrade(&result); // 将子inode插入父inode的B树中 - guard.children.insert(String::from(name), result.clone()); + guard.children.insert(name, result.clone()); return Ok(result); } } @@ -431,7 +436,11 @@ impl IndexNode for LockedDevFSInode { } name => { // 在子目录项中查找 - return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone()); + return Ok(inode + .children + .get(&DName::from(name)) + .ok_or(SystemError::ENOENT)? + .clone()); } } } @@ -458,19 +467,14 @@ impl IndexNode for LockedDevFSInode { // TODO: 优化这里,这个地方性能很差! let mut key: Vec = inode .children - .keys() - .filter(|k| { - inode - .children - .get(*k) - .unwrap() - .metadata() - .unwrap() - .inode_id - .into() - == ino + .iter() + .filter_map(|(k, v)| { + if v.metadata().unwrap().inode_id.into() == ino { + Some(k.to_string()) + } else { + None + } }) - .cloned() .collect(); match key.len() { @@ -488,7 +492,7 @@ impl IndexNode for LockedDevFSInode { _data: usize, _private_data: &FilePrivateData, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn list(&self) -> Result, SystemError> { @@ -500,7 +504,15 @@ impl IndexNode for LockedDevFSInode { let mut keys: Vec = Vec::new(); keys.push(String::from(".")); keys.push(String::from("..")); - keys.append(&mut self.0.lock().children.keys().cloned().collect()); + keys.append( + &mut self + .0 + .lock() + .children + .keys() + .map(ToString::to_string) + .collect(), + ); return Ok(keys); } @@ -530,7 +542,7 @@ impl IndexNode for LockedDevFSInode { _data: SpinLockGuard, ) -> Result { kerror!("DevFS: read_at is not supported!"); - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写 @@ -541,7 +553,19 @@ impl IndexNode for LockedDevFSInode { _buf: &[u8], _data: SpinLockGuard, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) + } + + fn parent(&self) -> Result, SystemError> { + let me = self.0.lock(); + Ok(me + .parent + .upgrade() + .unwrap_or(me.self_ref.upgrade().unwrap())) + } + + fn dname(&self) -> Result { + Ok(self.0.lock().dname.clone()) } } @@ -591,11 +615,11 @@ pub fn devfs_init() -> Result<(), SystemError> { // 创建 devfs 实例 let devfs: Arc = DevFS::new(); // devfs 挂载 - let _t = ROOT_INODE() - .find("dev") - .expect("Cannot find /dev") + ROOT_INODE() + .mkdir("dev", ModeType::from_bits_truncate(0o755)) + .expect("Unabled to find /dev") .mount(devfs) - .expect("Failed to mount devfs"); + .expect("Failed to mount at /dev"); kinfo!("DevFS mounted."); result = Some(Ok(())); }); diff --git a/kernel/src/filesystem/devfs/null_dev.rs b/kernel/src/filesystem/devfs/null_dev.rs index 2fad7692..0b050031 100644 --- a/kernel/src/filesystem/devfs/null_dev.rs +++ b/kernel/src/filesystem/devfs/null_dev.rs @@ -93,7 +93,7 @@ impl IndexNode for LockedNullInode { } fn list(&self) -> Result, SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { diff --git a/kernel/src/filesystem/devfs/zero_dev.rs b/kernel/src/filesystem/devfs/zero_dev.rs index c2787ac0..0a74b586 100644 --- a/kernel/src/filesystem/devfs/zero_dev.rs +++ b/kernel/src/filesystem/devfs/zero_dev.rs @@ -93,7 +93,7 @@ impl IndexNode for LockedZeroInode { } fn list(&self) -> Result, SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { diff --git a/kernel/src/filesystem/devpts/mod.rs b/kernel/src/filesystem/devpts/mod.rs index ad832dd7..1fc57f5c 100644 --- a/kernel/src/filesystem/devpts/mod.rs +++ b/kernel/src/filesystem/devpts/mod.rs @@ -21,7 +21,7 @@ use crate::{ tty_device::{PtyType, TtyDevice, TtyType}, }, }, - filesystem::vfs::{syscall::ModeType, FileType, ROOT_INODE}, + filesystem::vfs::{core::do_mount_mkdir, syscall::ModeType, FileType}, init::initcall::INITCALL_FS, libs::spinlock::{SpinLock, SpinLockGuard}, time::PosixTimeSpec, @@ -274,16 +274,10 @@ impl IndexNode for LockedDevPtsFSInode { #[unified_init(INITCALL_FS)] #[inline(never)] pub fn devpts_init() -> Result<(), SystemError> { - let dev_inode = ROOT_INODE().find("dev")?; - - let pts_inode = dev_inode.create("pts", FileType::Dir, ModeType::from_bits_truncate(0o755))?; - // 创建 devptsfs 实例 let ptsfs: Arc = DevPtsFs::new(); - // let mountfs = dev_inode.mount(ptsfs).expect("Failed to mount DevPtsFS"); - - pts_inode.mount(ptsfs).expect("Failed to mount DevPtsFS"); + do_mount_mkdir(ptsfs, "/dev/pts").expect("Failed to mount DevPtsFS"); kinfo!("DevPtsFs mounted."); Ok(()) diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 38f558ba..df6af8ce 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1,3 +1,4 @@ +use alloc::string::ToString; use core::cmp::Ordering; use core::intrinsics::unlikely; use core::{any::Any, fmt::Debug}; @@ -11,6 +12,7 @@ use alloc::{ }; use crate::driver::base::device::device_number::DeviceNumber; +use crate::filesystem::vfs::utils::DName; use crate::filesystem::vfs::{Magic, SpecialNodeData, SuperBlock}; use crate::ipc::pipe::LockedPipeInode; use crate::{ @@ -101,7 +103,7 @@ pub struct FATInode { self_ref: Weak, /// 子Inode的B树. 该数据结构用作缓存区。其中,它的key表示inode的名称。 /// 请注意,由于FAT的查询过程对大小写不敏感,因此我们选择让key全部是大写的,方便统一操作。 - children: BTreeMap>, + children: BTreeMap>, /// 当前inode的元数据 metadata: Metadata, /// 指向inode所在的文件系统对象的指针 @@ -112,6 +114,9 @@ pub struct FATInode { /// 若该节点是特殊文件节点,该字段则为真正的文件节点 special_node: Option, + + /// 目录名 + dname: DName, } impl FATInode { @@ -135,8 +140,9 @@ impl FATInode { fn find(&mut self, name: &str) -> Result, SystemError> { match &self.inode_type { FATDirEntry::Dir(d) => { + let dname = DName::from(name.to_uppercase()); // 尝试在缓存区查找 - if let Some(entry) = self.children.get(&name.to_uppercase()) { + if let Some(entry) = self.children.get(&dname) { return Ok(entry.clone()); } // 在缓存区找不到 @@ -145,13 +151,13 @@ impl FATInode { d.find_entry(name, None, None, self.fs.upgrade().unwrap())?; // 创建新的inode let entry_inode: Arc = LockedFATInode::new( + dname.clone(), self.fs.upgrade().unwrap(), self.self_ref.clone(), fat_entry, ); // 加入缓存区, 由于FAT文件系统的大小写不敏感问题,因此存入缓存区的key应当是全大写的 - self.children - .insert(name.to_uppercase(), entry_inode.clone()); + self.children.insert(dname, entry_inode.clone()); return Ok(entry_inode); } FATDirEntry::UnInit => { @@ -169,6 +175,7 @@ impl FATInode { impl LockedFATInode { pub fn new( + dname: DName, fs: Arc, parent: Weak, inode_type: FATDirEntry, @@ -206,6 +213,7 @@ impl LockedFATInode { raw_dev: DeviceNumber::default(), }, special_node: None, + dname, }))); inode.0.lock().self_ref = Arc::downgrade(&inode); @@ -338,6 +346,7 @@ impl FATFileSystem { raw_dev: DeviceNumber::default(), }, special_node: None, + dname: DName::default(), }))); let result: Arc = Arc::new(FATFileSystem { @@ -1442,7 +1451,7 @@ impl IndexNode for LockedFATInode { return Ok(guard.find(name)?); } - FileType::SymLink => return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP), + FileType::SymLink => return Err(SystemError::ENOSYS), _ => return Err(SystemError::EINVAL), }, FATDirEntry::UnInit => { @@ -1498,7 +1507,7 @@ impl IndexNode for LockedFATInode { guard.update_metadata(); return Ok(()); } - FATDirEntry::Dir(_) => return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP), + FATDirEntry::Dir(_) => return Err(SystemError::ENOSYS), FATDirEntry::UnInit => { kerror!("FATFS: param: Inode_type uninitialized."); return Err(SystemError::EROFS); @@ -1532,23 +1541,22 @@ impl IndexNode for LockedFATInode { ret.push(ent.name()); // ====== 生成inode缓存,存入B树 - let name: String = ent.name(); + let name = DName::from(ent.name().to_uppercase()); // kdebug!("name={name}"); - if !guard.children.contains_key(&name.to_uppercase()) - && name != "." - && name != ".." + if !guard.children.contains_key(&name) + && name.as_ref() != "." + && name.as_ref() != ".." { // 创建新的inode let entry_inode: Arc = LockedFATInode::new( + name.clone(), guard.fs.upgrade().unwrap(), guard.self_ref.clone(), ent, ); // 加入缓存区, 由于FAT文件系统的大小写不敏感问题,因此存入缓存区的key应当是全大写的 - guard - .children - .insert(name.to_uppercase(), entry_inode.clone()); + guard.children.insert(name, entry_inode.clone()); } } return Ok(ret); @@ -1584,7 +1592,7 @@ impl IndexNode for LockedFATInode { // 对目标inode上锁,以防更改 let target_guard: SpinLockGuard = target.0.lock(); // 先从缓存删除 - let nod = guard.children.remove(&name.to_uppercase()); + let nod = guard.children.remove(&DName::from(name.to_uppercase())); // 若删除缓存中为管道的文件,则不需要再到磁盘删除 if nod.is_some() { @@ -1619,7 +1627,7 @@ impl IndexNode for LockedFATInode { // 对目标inode上锁,以防更改 let target_guard: SpinLockGuard = target.0.lock(); // 先从缓存删除 - guard.children.remove(&name.to_uppercase()); + guard.children.remove(&DName::from(name.to_uppercase())); let dir = match &guard.inode_type { FATDirEntry::File(_) | FATDirEntry::VolId(_) => { @@ -1642,7 +1650,9 @@ impl IndexNode for LockedFATInode { Err(r) => { if r == SystemError::ENOTEMPTY { // 如果要删除的是目录,且不为空,则删除动作未发生,重新加入缓存 - guard.children.insert(name.to_uppercase(), target.clone()); + guard + .children + .insert(DName::from(name.to_uppercase()), target.clone()); drop(target_guard); } return Err(r); @@ -1666,7 +1676,7 @@ impl IndexNode for LockedFATInode { let old_inode_guard: SpinLockGuard = old_inode.0.lock(); let fs = old_inode_guard.fs.upgrade().unwrap(); // 从缓存删除 - let _nod = guard.children.remove(&old_name.to_uppercase()); + let _nod = guard.children.remove(&DName::from(old_name.to_uppercase())); let old_dir = match &guard.inode_type { FATDirEntry::File(_) | FATDirEntry::VolId(_) => { return Err(SystemError::ENOTDIR); @@ -1693,7 +1703,9 @@ impl IndexNode for LockedFATInode { let old_inode_guard: SpinLockGuard = old_inode.0.lock(); let fs = old_inode_guard.fs.upgrade().unwrap(); // 从缓存删除 - let _nod = old_guard.children.remove(&old_name.to_uppercase()); + let _nod = old_guard + .children + .remove(&DName::from(old_name.to_uppercase())); let old_dir = match &old_guard.inode_type { FATDirEntry::File(_) | FATDirEntry::VolId(_) => { return Err(SystemError::ENOTDIR); @@ -1739,19 +1751,14 @@ impl IndexNode for LockedFATInode { // TODO: 优化这里,这个地方性能很差! let mut key: Vec = guard .children - .keys() - .filter(|k| { - guard - .children - .get(*k) - .unwrap() - .metadata() - .unwrap() - .inode_id - .into() - == ino + .iter() + .filter_map(|(k, v)| { + if v.0.lock().metadata.inode_id.into() == ino { + Some(k.to_string()) + } else { + None + } }) - .cloned() .collect(); match key.len() { @@ -1780,7 +1787,9 @@ impl IndexNode for LockedFATInode { return self.create(filename, FileType::File, mode); } + let filename = DName::from(filename.to_uppercase()); let nod = LockedFATInode::new( + filename.clone(), inode.fs.upgrade().unwrap(), inode.self_ref.clone(), FATDirEntry::File(FATFile::default()), @@ -1802,15 +1811,26 @@ impl IndexNode for LockedFATInode { return Err(SystemError::EINVAL); } - inode - .children - .insert(String::from(filename).to_uppercase(), nod.clone()); + inode.children.insert(filename, nod.clone()); Ok(nod) } fn special_node(&self) -> Option { self.0.lock().special_node.clone() } + + fn dname(&self) -> Result { + Ok(self.0.lock().dname.clone()) + } + + fn parent(&self) -> Result, SystemError> { + self.0 + .lock() + .parent + .upgrade() + .map(|item| item as Arc) + .ok_or(SystemError::EINVAL) + } } impl Default for FATFsInfo { diff --git a/kernel/src/filesystem/kernfs/callback.rs b/kernel/src/filesystem/kernfs/callback.rs index 67024b70..563893c6 100644 --- a/kernel/src/filesystem/kernfs/callback.rs +++ b/kernel/src/filesystem/kernfs/callback.rs @@ -70,7 +70,7 @@ impl<'a> KernCallbackData<'a> { if let Some(private_data) = private_data { return private_data.callback_read(buf, offset); } - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result { @@ -78,7 +78,7 @@ impl<'a> KernCallbackData<'a> { if let Some(private_data) = private_data { return private_data.callback_write(buf, offset); } - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } diff --git a/kernel/src/filesystem/kernfs/mod.rs b/kernel/src/filesystem/kernfs/mod.rs index 1edfe1cc..ff29cf2a 100644 --- a/kernel/src/filesystem/kernfs/mod.rs +++ b/kernel/src/filesystem/kernfs/mod.rs @@ -178,7 +178,7 @@ impl IndexNode for KernFSInode { fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn resize(&self, _len: usize) -> Result<(), SystemError> { @@ -193,22 +193,22 @@ impl IndexNode for KernFSInode { _data: usize, ) -> Result, SystemError> { // 应当通过kernfs的其它方法来创建文件,而不能从用户态直接调用此方法。 - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn link(&self, _name: &str, _other: &Arc) -> Result<(), SystemError> { // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn unlink(&self, _name: &str) -> Result<(), SystemError> { // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn rmdir(&self, _name: &str) -> Result<(), SystemError> { // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn move_to( @@ -218,7 +218,7 @@ impl IndexNode for KernFSInode { _new_name: &str, ) -> Result<(), SystemError> { // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn find(&self, name: &str) -> Result, SystemError> { @@ -281,12 +281,12 @@ impl IndexNode for KernFSInode { _private_data: &FilePrivateData, ) -> Result { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn truncate(&self, _len: usize) -> Result<(), SystemError> { // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn sync(&self) -> Result<(), SystemError> { @@ -346,7 +346,7 @@ impl IndexNode for KernFSInode { if self.callback.is_none() { kwarn!("kernfs: callback is none"); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } let callback_data = @@ -370,7 +370,7 @@ impl IndexNode for KernFSInode { } if self.callback.is_none() { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } let callback_data = @@ -381,11 +381,6 @@ impl IndexNode for KernFSInode { .unwrap() .write(callback_data, &buf[..len], offset); } - - fn rename(&self, _old_name: &str, _new_name: &str) -> Result<(), SystemError> { - // 待实现 - Err(SystemError::ENOSYS) - } } impl KernFSInode { diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index ef69cce1..07dcd179 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -31,6 +31,7 @@ use crate::{ use super::vfs::{ file::{FileMode, FilePrivateData}, syscall::ModeType, + utils::DName, FileSystem, FsInfo, IndexNode, InodeId, Magic, Metadata, SuperBlock, }; @@ -115,7 +116,7 @@ pub struct ProcFSInode { /// 指向自身的弱引用 self_ref: Weak, /// 子Inode的B树 - children: BTreeMap>, + children: BTreeMap>, /// 当前inode的数据部分 data: Vec, /// 当前inode的元数据 @@ -124,6 +125,8 @@ pub struct ProcFSInode { fs: Weak, /// 储存私有信息 fdata: InodeInfo, + /// 目录项 + dname: DName, } /// 对ProcFSInode实现获取各类文件信息的函数 @@ -329,6 +332,7 @@ impl ProcFS { pid: Pid::new(0), ftype: ProcFileType::Default, }, + dname: DName::default(), }))); let result: Arc = Arc::new(ProcFS { @@ -529,7 +533,7 @@ impl IndexNode for LockedProcFSInode { _buf: &[u8], _data: SpinLockGuard, ) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn fs(&self) -> Arc { @@ -582,8 +586,9 @@ impl IndexNode for LockedProcFSInode { if inode.metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } + let name = DName::from(name); // 如果有重名的,则返回 - if inode.children.contains_key(name) { + if inode.children.contains_key(&name) { return Err(SystemError::EEXIST); } @@ -615,13 +620,14 @@ impl IndexNode for LockedProcFSInode { pid: Pid::new(0), ftype: ProcFileType::Default, }, + dname: name.clone(), }))); // 初始化inode的自引用的weak指针 result.0.lock().self_ref = Arc::downgrade(&result); // 将子inode插入父inode的B树中 - inode.children.insert(String::from(name), result.clone()); + inode.children.insert(name, result.clone()); return Ok(result); } @@ -642,15 +648,15 @@ impl IndexNode for LockedProcFSInode { if other_locked.metadata.file_type == FileType::Dir { return Err(SystemError::EISDIR); } - + let name = DName::from(name); // 如果当前文件夹下已经有同名文件,也报错。 - if inode.children.contains_key(name) { + if inode.children.contains_key(&name) { return Err(SystemError::EEXIST); } inode .children - .insert(String::from(name), other_locked.self_ref.upgrade().unwrap()); + .insert(name, other_locked.self_ref.upgrade().unwrap()); // 增加硬链接计数 other_locked.metadata.nlinks += 1; @@ -668,15 +674,15 @@ impl IndexNode for LockedProcFSInode { if name == "." || name == ".." { return Err(SystemError::ENOTEMPTY); } - + let name = DName::from(name); // 获得要删除的文件的inode - let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?; + let to_delete = inode.children.get(&name).ok_or(SystemError::ENOENT)?; // 减少硬链接计数 to_delete.0.lock().metadata.nlinks -= 1; // 在当前目录中删除这个子目录项 - inode.children.remove(name); + inode.children.remove(&name); return Ok(()); } @@ -687,7 +693,7 @@ impl IndexNode for LockedProcFSInode { _target: &Arc, _new_name: &str, ) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn find(&self, name: &str) -> Result, SystemError> { @@ -707,7 +713,11 @@ impl IndexNode for LockedProcFSInode { } name => { // 在子目录项中查找 - return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone()); + return Ok(inode + .children + .get(&DName::from(name)) + .ok_or(SystemError::ENOENT)? + .clone()); } } } @@ -730,20 +740,14 @@ impl IndexNode for LockedProcFSInode { // TODO: 优化这里,这个地方性能很差! let mut key: Vec = inode .children - .keys() - .filter(|k| { - inode - .children - .get(*k) - .unwrap() - .0 - .lock() - .metadata - .inode_id - .into() - == ino + .iter() + .filter_map(|(k, v)| { + if v.0.lock().metadata.inode_id.into() == ino { + Some(k.to_string()) + } else { + None + } }) - .cloned() .collect(); match key.len() { @@ -764,10 +768,22 @@ impl IndexNode for LockedProcFSInode { let mut keys: Vec = Vec::new(); keys.push(String::from(".")); keys.push(String::from("..")); - keys.append(&mut self.0.lock().children.keys().cloned().collect()); + keys.append( + &mut self + .0 + .lock() + .children + .keys() + .map(ToString::to_string) + .collect(), + ); return Ok(keys); } + + fn dname(&self) -> Result { + Ok(self.0.lock().dname.clone()) + } } /// @brief 向procfs注册进程 @@ -808,13 +824,12 @@ pub fn procfs_init() -> Result<(), SystemError> { kinfo!("Initializing ProcFS..."); // 创建 procfs 实例 let procfs: Arc = ProcFS::new(); - // procfs 挂载 - let _t = ROOT_INODE() - .find("proc") - .expect("Cannot find /proc") + ROOT_INODE() + .mkdir("proc", ModeType::from_bits_truncate(0o755)) + .expect("Unabled to find /proc") .mount(procfs) - .expect("Failed to mount proc"); + .expect("Failed to mount at /proc"); kinfo!("ProcFS mounted."); result = Some(Ok(())); }); diff --git a/kernel/src/filesystem/ramfs/mod.rs b/kernel/src/filesystem/ramfs/mod.rs index 8c76ae32..c2435ff3 100644 --- a/kernel/src/filesystem/ramfs/mod.rs +++ b/kernel/src/filesystem/ramfs/mod.rs @@ -12,6 +12,7 @@ use crate::{ time::PosixTimeSpec, }; +use alloc::string::ToString; use alloc::{ collections::BTreeMap, string::String, @@ -21,8 +22,8 @@ use alloc::{ use system_error::SystemError; use super::vfs::{ - file::FilePrivateData, syscall::ModeType, FileSystem, FileSystemMaker, FsInfo, IndexNode, - InodeId, Metadata, SpecialNodeData, + file::FilePrivateData, syscall::ModeType, utils::DName, FileSystem, FileSystemMaker, FsInfo, + IndexNode, InodeId, Metadata, SpecialNodeData, }; use super::vfs::{Magic, SuperBlock}; @@ -53,7 +54,7 @@ pub struct RamFSInode { /// 指向自身的弱引用 self_ref: Weak, /// 子Inode的B树 - children: BTreeMap>, + children: BTreeMap>, /// 当前inode的数据部分 data: Vec, /// 当前inode的元数据 @@ -62,6 +63,8 @@ pub struct RamFSInode { fs: Weak, /// 指向特殊节点 special_node: Option, + + name: DName, } impl FileSystem for RamFS { @@ -122,6 +125,7 @@ impl RamFS { }, fs: Weak::default(), special_node: None, + name: Default::default(), }))); let result: Arc = Arc::new(RamFS { @@ -287,6 +291,7 @@ impl IndexNode for LockedRamFSInode { mode: ModeType, data: usize, ) -> Result, SystemError> { + let name = DName::from(name); // 获取当前inode let mut inode = self.0.lock(); // 如果当前inode不是文件夹,则返回 @@ -294,7 +299,7 @@ impl IndexNode for LockedRamFSInode { return Err(SystemError::ENOTDIR); } // 如果有重名的,则返回 - if inode.children.contains_key(name) { + if inode.children.contains_key(&name) { return Err(SystemError::EEXIST); } @@ -322,13 +327,14 @@ impl IndexNode for LockedRamFSInode { }, fs: inode.fs.clone(), special_node: None, + name: name.clone(), }))); // 初始化inode的自引用的weak指针 result.0.lock().self_ref = Arc::downgrade(&result); // 将子inode插入父inode的B树中 - inode.children.insert(String::from(name), result.clone()); + inode.children.insert(name, result.clone()); return Ok(result); } @@ -337,6 +343,7 @@ impl IndexNode for LockedRamFSInode { let other: &LockedRamFSInode = other .downcast_ref::() .ok_or(SystemError::EPERM)?; + let name = DName::from(name); let mut inode: SpinLockGuard = self.0.lock(); let mut other_locked: SpinLockGuard = other.0.lock(); @@ -351,13 +358,13 @@ impl IndexNode for LockedRamFSInode { } // 如果当前文件夹下已经有同名文件,也报错。 - if inode.children.contains_key(name) { + if inode.children.contains_key(&name) { return Err(SystemError::EEXIST); } inode .children - .insert(String::from(name), other_locked.self_ref.upgrade().unwrap()); + .insert(name, other_locked.self_ref.upgrade().unwrap()); // 增加硬链接计数 other_locked.metadata.nlinks += 1; @@ -375,33 +382,35 @@ impl IndexNode for LockedRamFSInode { return Err(SystemError::ENOTEMPTY); } + let name = DName::from(name); // 获得要删除的文件的inode - let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?; + let to_delete = inode.children.get(&name).ok_or(SystemError::ENOENT)?; if to_delete.0.lock().metadata.file_type == FileType::Dir { return Err(SystemError::EPERM); } // 减少硬链接计数 to_delete.0.lock().metadata.nlinks -= 1; // 在当前目录中删除这个子目录项 - inode.children.remove(name); + inode.children.remove(&name); return Ok(()); } fn rmdir(&self, name: &str) -> Result<(), SystemError> { + let name = DName::from(name); let mut inode: SpinLockGuard = self.0.lock(); // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录 if inode.metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } // 获得要删除的文件夹的inode - let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?; + let to_delete = inode.children.get(&name).ok_or(SystemError::ENOENT)?; if to_delete.0.lock().metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } to_delete.0.lock().metadata.nlinks -= 1; // 在当前目录中删除这个子目录项 - inode.children.remove(name); + inode.children.remove(&name); return Ok(()); } @@ -411,27 +420,41 @@ impl IndexNode for LockedRamFSInode { target: &Arc, new_name: &str, ) -> Result<(), SystemError> { - let inode: Arc = self.find(old_name)?; + let inode_to_move = self + .find(old_name)? + .downcast_arc::() + .ok_or(SystemError::EINVAL)?; + + let new_name = DName::from(new_name); + + inode_to_move.0.lock().name = new_name.clone(); + + let target_id = target.metadata()?.inode_id; + + let mut self_inode = self.0.lock(); + // 判断是否在同一目录下, 是则进行重命名 + if target_id == self_inode.metadata.inode_id { + self_inode.children.remove(&DName::from(old_name)); + self_inode.children.insert(new_name, inode_to_move); + return Ok(()); + } + drop(self_inode); + // 修改其对父节点的引用 - inode - .downcast_ref::() - .ok_or(SystemError::EPERM)? - .0 - .lock() - .parent = Arc::downgrade( + inode_to_move.0.lock().parent = Arc::downgrade( &target .clone() .downcast_arc::() - .ok_or(SystemError::EPERM)?, + .ok_or(SystemError::EINVAL)?, ); // 在新的目录下创建一个硬链接 - target.link(new_name, &inode)?; + target.link(new_name.as_ref(), &(inode_to_move as Arc))?; // 取消现有的目录下的这个硬链接 if let Err(e) = self.unlink(old_name) { // 当操作失败时回退操作 - target.unlink(new_name)?; + target.unlink(new_name.as_ref())?; return Err(e); } @@ -455,7 +478,12 @@ impl IndexNode for LockedRamFSInode { } name => { // 在子目录项中查找 - return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone()); + let name = DName::from(name); + return Ok(inode + .children + .get(&name) + .ok_or(SystemError::ENOENT)? + .clone()); } } } @@ -478,20 +506,14 @@ impl IndexNode for LockedRamFSInode { // TODO: 优化这里,这个地方性能很差! let mut key: Vec = inode .children - .keys() - .filter(|k| { - inode - .children - .get(*k) - .unwrap() - .0 - .lock() - .metadata - .inode_id - .into() - == ino + .iter() + .filter_map(|(k, v)| { + if v.0.lock().metadata.inode_id.into() == ino { + Some(k.to_string()) + } else { + None + } }) - .cloned() .collect(); match key.len() { @@ -512,7 +534,15 @@ impl IndexNode for LockedRamFSInode { let mut keys: Vec = Vec::new(); keys.push(String::from(".")); keys.push(String::from("..")); - keys.append(&mut self.0.lock().children.keys().cloned().collect()); + keys.append( + &mut self + .0 + .lock() + .children + .keys() + .map(|k| k.to_string()) + .collect(), + ); return Ok(keys); } @@ -534,6 +564,8 @@ impl IndexNode for LockedRamFSInode { return self.create(filename, FileType::File, mode); } + let filename = DName::from(filename); + let nod = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { parent: inode.self_ref.clone(), self_ref: Weak::default(), @@ -557,6 +589,7 @@ impl IndexNode for LockedRamFSInode { }, fs: inode.fs.clone(), special_node: None, + name: filename.clone(), }))); nod.0.lock().self_ref = Arc::downgrade(&nod); @@ -575,28 +608,24 @@ impl IndexNode for LockedRamFSInode { unimplemented!() } - inode - .children - .insert(String::from(filename).to_uppercase(), nod.clone()); + inode.children.insert(filename, nod.clone()); Ok(nod) } fn special_node(&self) -> Option { return self.0.lock().special_node.clone(); } - /// # 用于重命名内存中的文件或目录 - fn rename(&self, _old_name: &str, _new_name: &str) -> Result<(), SystemError> { - let old_inode: Arc = self.find(_old_name)?; - // 在新的目录下创建一个硬链接 - self.link(_new_name, &old_inode)?; - // 取消现有的目录下的这个硬链接 - if let Err(err) = self.unlink(_old_name) { - // 如果取消失败,那就取消新的目录下的硬链接 - self.unlink(_new_name)?; - return Err(err); - } + fn dname(&self) -> Result { + Ok(self.0.lock().name.clone()) + } - return Ok(()); + fn parent(&self) -> Result, SystemError> { + self.0 + .lock() + .parent + .upgrade() + .map(|item| item as Arc) + .ok_or(SystemError::EINVAL) } } diff --git a/kernel/src/filesystem/sysfs/mod.rs b/kernel/src/filesystem/sysfs/mod.rs index 43179dc5..a1567a46 100644 --- a/kernel/src/filesystem/sysfs/mod.rs +++ b/kernel/src/filesystem/sysfs/mod.rs @@ -42,11 +42,11 @@ pub fn sysfs_init() -> Result<(), SystemError> { unsafe { SYSFS_INSTANCE = Some(sysfs) }; // sysfs 挂载 - let _t = ROOT_INODE() - .find("sys") - .expect("Cannot find /sys") + ROOT_INODE() + .mkdir("sys", ModeType::from_bits_truncate(0o755)) + .expect("Unabled to find /sys") .mount(sysfs_instance().fs().clone()) - .expect("Failed to mount sysfs"); + .expect("Failed to mount at /sys"); kinfo!("SysFS mounted."); // kdebug!("sys_bus_init result: {:?}", SYS_BUS_INODE().list()); @@ -74,7 +74,7 @@ impl SysFSKernPrivateData { return Ok(len); } _ => { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } } @@ -86,7 +86,7 @@ impl SysFSKernPrivateData { return file.callback_write(buf, offset); } _ => { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } } @@ -125,11 +125,11 @@ pub trait Attribute: Debug + Send + Sync { fn support(&self) -> SysFSOpsSupport; fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } @@ -142,7 +142,7 @@ pub trait BinAttribute: Attribute { _buf: &[u8], _offset: usize, ) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn read( @@ -151,7 +151,7 @@ pub trait BinAttribute: Attribute { _buf: &mut [u8], _offset: usize, ) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn size(&self) -> usize; diff --git a/kernel/src/filesystem/vfs/core.rs b/kernel/src/filesystem/vfs/core.rs index 7115e991..ed6badcf 100644 --- a/kernel/src/filesystem/vfs/core.rs +++ b/kernel/src/filesystem/vfs/core.rs @@ -13,13 +13,15 @@ use crate::{ sysfs::sysfs_init, vfs::{mount::MountFS, syscall::ModeType, AtomicInodeId, FileSystem, FileType}, }, - kdebug, kerror, kinfo, + kerror, kinfo, process::ProcessManager, }; use super::{ + fcntl::AtFlags, file::FileMode, - mount::MountFSInode, + mount::{init_mountlist, MOUNT_LIST}, + syscall::UmountFlag, utils::{rsplit_path, user_path_at}, IndexNode, InodeId, VFS_MAX_FOLLOW_SYMLINK_TIMES, }; @@ -52,24 +54,11 @@ pub fn vfs_init() -> Result<(), SystemError> { let ramfs = RamFS::new(); let mount_fs = MountFS::new(ramfs, None); let root_inode = mount_fs.root_inode(); - + init_mountlist(); unsafe { __ROOT_INODE = Some(root_inode.clone()); } - // 创建文件夹 - root_inode - .create("proc", FileType::Dir, ModeType::from_bits_truncate(0o755)) - .expect("Failed to create /proc"); - root_inode - .create("dev", FileType::Dir, ModeType::from_bits_truncate(0o755)) - .expect("Failed to create /dev"); - root_inode - .create("sys", FileType::Dir, ModeType::from_bits_truncate(0o755)) - .expect("Failed to create /sys"); - - kdebug!("dir in root:{:?}", root_inode.list()); - procfs_init().expect("Failed to initialize procfs"); devfs_init().expect("Failed to initialize devfs"); @@ -83,63 +72,40 @@ pub fn vfs_init() -> Result<(), SystemError> { return Ok(()); } -/// @brief 真正执行伪文件系统迁移的过程 -/// -/// @param mountpoint_name 在根目录下的挂载点的名称 -/// @param inode 原本的挂载点的inode -fn do_migrate( - new_root_inode: Arc, - mountpoint_name: &str, - fs: &MountFS, -) -> Result<(), SystemError> { - let r = new_root_inode.find(mountpoint_name); - let mountpoint = if let Ok(r) = r { - r - } else { - new_root_inode - .create( - mountpoint_name, - FileType::Dir, - ModeType::from_bits_truncate(0o755), - ) - .unwrap_or_else(|_| panic!("Failed to create '/{mountpoint_name}' in migrating")) - }; - // 迁移挂载点 - let inode = mountpoint.arc_any().downcast::().unwrap(); - inode.do_mount(inode.inode_id(), fs.self_ref())?; - - return Ok(()); -} - /// @brief 迁移伪文件系统的inode /// 请注意,为了避免删掉了伪文件系统内的信息,因此没有在原root inode那里调用unlink. fn migrate_virtual_filesystem(new_fs: Arc) -> Result<(), SystemError> { kinfo!("VFS: Migrating filesystems..."); - // ==== 在这里获取要被迁移的文件系统的inode === - let binding = ROOT_INODE().find("proc").expect("ProcFS not mounted!").fs(); - let proc: &MountFS = binding.as_any_ref().downcast_ref::().unwrap(); - let binding = ROOT_INODE().find("dev").expect("DevFS not mounted!").fs(); - let dev: &MountFS = binding.as_any_ref().downcast_ref::().unwrap(); - let binding = ROOT_INODE().find("sys").expect("SysFs not mounted!").fs(); - let sys: &MountFS = binding.as_any_ref().downcast_ref::().unwrap(); - let new_fs = MountFS::new(new_fs, None); // 获取新的根文件系统的根节点的引用 let new_root_inode = new_fs.root_inode(); - // 把上述文件系统,迁移到新的文件系统下 - do_migrate(new_root_inode.clone(), "proc", proc)?; - do_migrate(new_root_inode.clone(), "dev", dev)?; - do_migrate(new_root_inode.clone(), "sys", sys)?; + // ==== 在这里获取要被迁移的文件系统的inode并迁移 === + // 因为是换根所以路径没有变化 + // 不需要重新注册挂载目录 + new_root_inode + .mkdir("proc", ModeType::from_bits_truncate(0o755)) + .expect("Unable to create /proc") + .mount_from(ROOT_INODE().find("proc").expect("proc not mounted!")) + .expect("Failed to migrate filesystem of proc"); + new_root_inode + .mkdir("dev", ModeType::from_bits_truncate(0o755)) + .expect("Unable to create /dev") + .mount_from(ROOT_INODE().find("dev").expect("dev not mounted!")) + .expect("Failed to migrate filesystem of dev"); + new_root_inode + .mkdir("sys", ModeType::from_bits_truncate(0o755)) + .expect("Unable to create /sys") + .mount_from(ROOT_INODE().find("sys").expect("sys not mounted!")) + .expect("Failed to migrate filesystem of sys"); unsafe { // drop旧的Root inode let old_root_inode = __ROOT_INODE.take().unwrap(); - drop(old_root_inode); - // 设置全局的新的ROOT Inode - __ROOT_INODE = Some(new_root_inode); + __ROOT_INODE = Some(new_root_inode.clone()); + drop(old_root_inode); } kinfo!("VFS: Migrate filesystems done!"); @@ -180,31 +146,20 @@ pub fn mount_root_fs() -> Result<(), SystemError> { } /// @brief 创建文件/文件夹 -pub fn do_mkdir(path: &str, _mode: FileMode) -> Result { - let path = path.trim(); - - let inode: Result, SystemError> = ROOT_INODE().lookup(path); - - if let Err(errno) = inode { - // 文件不存在,且需要创建 - if errno == SystemError::ENOENT { - let (filename, parent_path) = rsplit_path(path); - // 查找父目录 - let parent_inode: Arc = - ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; - // 创建文件夹 - let _create_inode: Arc = parent_inode.create( - filename, - FileType::Dir, - ModeType::from_bits_truncate(0o755), - )?; - } else { - // 不需要创建文件,因此返回错误码 - return Err(errno); - } +pub fn do_mkdir_at( + dirfd: i32, + path: &str, + mode: FileMode, +) -> Result, SystemError> { + // kdebug!("Call do mkdir at"); + let (mut current_inode, path) = + user_path_at(&ProcessManager::current_pcb(), dirfd, path.trim())?; + let (name, parent) = rsplit_path(&path); + if let Some(parent) = parent { + current_inode = current_inode.lookup(parent)?; } - - return Ok(0); + // kdebug!("mkdir at {:?}", current_inode.metadata()?.inode_id); + return current_inode.mkdir(name, ModeType::from_bits_truncate(mode.bits())); } /// @brief 删除文件夹 @@ -276,10 +231,101 @@ pub fn do_unlink_at(dirfd: i32, path: &str) -> Result { return Ok(0); } -// @brief mount filesystem -pub fn do_mount(fs: Arc, mount_point: &str) -> Result { - ROOT_INODE() - .lookup_follow_symlink(mount_point, VFS_MAX_FOLLOW_SYMLINK_TIMES)? - .mount(fs)?; - Ok(0) +/// # do_mount - 挂载文件系统 +/// +/// 将给定的文件系统挂载到指定的挂载点。 +/// +/// 此函数会检查是否已经挂载了相同的文件系统,如果已经挂载,则返回错误。 +/// 它还会处理符号链接,并确保挂载点是有效的。 +/// +/// ## 参数 +/// +/// - `fs`: Arc,要挂载的文件系统。 +/// - `mount_point`: &str,挂载点路径。 +/// +/// ## 返回值 +/// +/// - `Ok(Arc)`: 挂载成功后返回挂载的文件系统。 +/// - `Err(SystemError)`: 挂载失败时返回错误。 +pub fn do_mount(fs: Arc, mount_point: &str) -> Result, SystemError> { + let (current_node, rest_path) = user_path_at( + &ProcessManager::current_pcb(), + AtFlags::AT_FDCWD.bits(), + mount_point, + )?; + let inode = current_node.lookup_follow_symlink(&rest_path, VFS_MAX_FOLLOW_SYMLINK_TIMES)?; + if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { + if rest.is_empty() { + return Err(SystemError::EBUSY); + } + } + // 移至IndexNode.mount()来记录 + return inode.mount(fs); +} + +/// # do_mount_mkdir - 在指定挂载点创建目录并挂载文件系统 +/// +/// 在指定的挂载点创建一个目录,并将其挂载到文件系统中。如果挂载点已经存在,并且不是空的, +/// 则会返回错误。成功时,会返回一个新的挂载文件系统的引用。 +/// +/// ## 参数 +/// +/// - `fs`: FileSystem - 文件系统的引用,用于创建和挂载目录。 +/// - `mount_point`: &str - 挂载点路径,用于创建和挂载目录。 +/// +/// ## 返回值 +/// +/// - `Ok(Arc)`: 成功挂载文件系统后,返回挂载文件系统的共享引用。 +/// - `Err(SystemError)`: 挂载失败时,返回系统错误。 +pub fn do_mount_mkdir( + fs: Arc, + mount_point: &str, +) -> Result, SystemError> { + let inode = do_mkdir_at( + AtFlags::AT_FDCWD.bits(), + mount_point, + FileMode::from_bits_truncate(0o755), + )?; + if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { + if rest.is_empty() { + return Err(SystemError::EBUSY); + } + } + return inode.mount(fs); +} + +/// # do_umount2 - 执行卸载文件系统的函数 +/// +/// 这个函数用于卸载指定的文件系统。 +/// +/// ## 参数 +/// +/// - dirfd: i32 - 目录文件描述符,用于指定要卸载的文件系统的根目录。 +/// - target: &str - 要卸载的文件系统的目标路径。 +/// - _flag: UmountFlag - 卸载标志,目前未使用。 +/// +/// ## 返回值 +/// +/// - Ok(Arc): 成功时返回文件系统的 Arc 引用。 +/// - Err(SystemError): 出错时返回系统错误。 +/// +/// ## 错误处理 +/// +/// 如果指定的路径没有对应的文件系统,或者在尝试卸载时发生错误,将返回错误。 +pub fn do_umount2( + dirfd: i32, + target: &str, + _flag: UmountFlag, +) -> Result, SystemError> { + let (work, rest) = user_path_at(&ProcessManager::current_pcb(), dirfd, target)?; + let path = work.absolute_path()? + &rest; + let do_umount = || -> Result, SystemError> { + if let Some(fs) = MOUNT_LIST().remove(path) { + // Todo: 占用检测 + fs.umount()?; + return Ok(fs); + } + return Err(SystemError::EINVAL); + }; + return do_umount(); } diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 2436027d..c867d4ca 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -515,7 +515,7 @@ impl File { return socket.remove_epoll(epoll); } - _ => return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP), + _ => return Err(SystemError::ENOSYS), } } diff --git a/kernel/src/filesystem/vfs/mod.rs b/kernel/src/filesystem/vfs/mod.rs index 6a6a805a..482d4a88 100644 --- a/kernel/src/filesystem/vfs/mod.rs +++ b/kernel/src/filesystem/vfs/mod.rs @@ -4,7 +4,7 @@ pub mod file; pub mod mount; pub mod open; pub mod syscall; -mod utils; +pub mod utils; use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize}; use alloc::{string::String, sync::Arc, vec::Vec}; @@ -23,7 +23,7 @@ use crate::{ time::PosixTimeSpec, }; -use self::{core::generate_inode_id, file::FileMode, syscall::ModeType}; +use self::{core::generate_inode_id, file::FileMode, syscall::ModeType, utils::DName}; pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS}; /// vfs容许的最大的路径名称长度 @@ -129,7 +129,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { _mode: &FileMode, ) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 关闭文件 @@ -138,7 +138,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn close(&self, _data: SpinLockGuard) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 在inode的指定偏移量开始,读取指定大小的数据 @@ -180,7 +180,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// @return PollStatus结构体 fn poll(&self, _private_data: &FilePrivateData) -> Result { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 获取inode的元数据 @@ -189,7 +189,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn metadata(&self) -> Result { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 设置inode的元数据 @@ -198,7 +198,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 重新设置文件的大小 @@ -210,7 +210,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn resize(&self, _len: usize) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 在当前目录下创建一个新的inode @@ -227,7 +227,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { file_type: FileType, mode: ModeType, ) -> Result, SystemError> { - // 若文件系统没有实现此方法,则默认调用其create_with_data方法。如果仍未实现,则会得到一个Err(-EOPNOTSUPP_OR_ENOTSUP)的返回值 + // 若文件系统没有实现此方法,则默认调用其create_with_data方法。如果仍未实现,则会得到一个Err(-ENOSYS)的返回值 return self.create_with_data(name, file_type, mode, 0); } @@ -248,7 +248,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { _data: usize, ) -> Result, SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 在当前目录下,创建一个名为Name的硬链接,指向另一个IndexNode @@ -260,7 +260,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn link(&self, _name: &str, _other: &Arc) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 在当前目录下,删除一个名为Name的硬链接 @@ -271,7 +271,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn unlink(&self, _name: &str) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 删除文件夹 @@ -281,19 +281,13 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// @return 成功 Ok(()) /// @return 失败 Err(错误码) fn rmdir(&self, _name: &str) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } - /// @brief 将指定名称的子目录项的文件内容,移动到target这个目录下。如果_old_name所指向的inode与_target的相同,那么则直接执行重命名的操作。 + /// 将指定的`old_name`子目录项移动到target目录下, 并予以`new_name`。 /// - /// @param old_name 旧的名字 - /// - /// @param target 移动到指定的inode - /// - /// @param new_name 新的文件名 - /// - /// @return 成功: Ok() - /// 失败: Err(错误码) + /// # Behavior + /// 如果old_name所指向的inode与target的相同,那么则直接**执行重命名的操作**。 fn move_to( &self, _old_name: &str, @@ -301,24 +295,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { _new_name: &str, ) -> Result<(), SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - /// # 修改文件名 - /// - /// - /// ## 参数 - /// - /// - _old_name: 源文件路径 - /// - _new_name: 目标文件路径 - /// - /// ## 返回值 - /// - Ok(返回值类型): 返回值的说明 - /// - Err(错误值类型): 错误的说明 - /// - fn rename(&self, _old_name: &str, _new_name: &str) -> Result<(), SystemError> { - // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 寻找一个名为Name的inode @@ -329,7 +306,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn find(&self, _name: &str) -> Result, SystemError> { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 根据inode号,获取子目录项的名字 @@ -340,7 +317,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// 失败:Err(错误码) fn get_entry_name(&self, _ino: InodeId) -> Result { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 根据inode号,获取子目录项的名字和元数据 @@ -370,7 +347,7 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { _private_data: &FilePrivateData, ) -> Result { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 获取inode所在的文件系统的指针 @@ -383,17 +360,111 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { /// @brief 列出当前inode下的所有目录项的名字 fn list(&self) -> Result, SystemError>; - /// @brief 在当前Inode下,挂载一个新的文件系统 - /// 请注意!该函数只能被MountFS实现,其他文件系统不应实现这个函数 + /// # mount - 挂载文件系统 + /// + /// 将给定的文件系统挂载到当前的文件系统节点上。 + /// + /// 该函数是`MountFS`结构体的实例方法,用于将一个新的文件系统挂载到调用它的`MountFS`实例上。 + /// + /// ## 参数 + /// + /// - `fs`: `Arc` - 要挂载的文件系统的共享引用。 + /// + /// ## 返回值 + /// + /// - `Ok(Arc)`: 新的挂载文件系统的共享引用。 + /// - `Err(SystemError)`: 挂载过程中出现的错误。 + /// + /// ## 错误处理 + /// + /// - 如果文件系统不是目录类型,则返回`SystemError::ENOTDIR`错误。 + /// - 如果当前路径已经是挂载点,则返回`SystemError::EBUSY`错误。 + /// + /// ## 副作用 + /// + /// - 该函数会在`MountFS`实例上创建一个新的挂载点。 + /// - 该函数会在全局的挂载列表中记录新的挂载关系。 fn mount(&self, _fs: Arc) -> Result, SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); + } + + /// # mount_from - 从给定的目录挂载已有挂载信息的文件系统 + /// + /// 这个函数将一个已有挂载信息的文件系统从给定的目录挂载到当前目录。 + /// + /// ## 参数 + /// + /// - `from`: Arc - 要挂载的目录的引用。 + /// + /// ## 返回值 + /// + /// - Ok(Arc): 挂载的新文件系统的引用。 + /// - Err(SystemError): 如果发生错误,返回系统错误。 + /// + /// ## 错误处理 + /// + /// - 如果给定的目录不是目录类型,返回`SystemError::ENOTDIR`。 + /// - 如果当前目录已经是挂载点的根目录,返回`SystemError::EBUSY`。 + /// + /// ## 副作用 + /// + /// - 系统初始化用,其他情况不应调用此函数 + fn mount_from(&self, _des: Arc) -> Result, SystemError> { + return Err(SystemError::ENOSYS); + } + + /// # umount - 卸载当前Inode下的文件系统 + /// + /// 该函数是特定于`MountFS`实现的,其他文件系统不应实现此函数。 + /// + /// ## 参数 + /// + /// 无 + /// + /// ## 返回值 + /// + /// - Ok(Arc): 卸载的文件系统的引用。 + /// - Err(SystemError): 如果发生错误,返回系统错误。 + /// + /// ## 行为 + /// + /// - 查找路径 + /// - 定位到父文件系统的挂载点 + /// - 将挂载点与子文件系统的根进行叠加 + /// - 判断是否为子文件系统的根 + /// - 调用父文件系统挂载点的`_umount`方法进行卸载 + fn umount(&self) -> Result, SystemError> { + return Err(SystemError::ENOSYS); + } + + /// # absolute_path 获取目录项绝对路径 + /// + /// ## 参数 + /// + /// 无 + /// + /// ## 返回值 + /// + /// - Ok(String): 路径 + /// - Err(SystemError): 文件系统不支持dname parent api + /// + /// ## Behavior + /// + /// 该函数只能被MountFS实现,其他文件系统不应实现这个函数 + /// + /// # Performance + /// + /// 这是一个O(n)的路径查询,并且在未实现DName缓存的文件系统中,性能极差; + /// 即使实现了DName也尽量不要用。 + fn absolute_path(&self) -> Result { + return Err(SystemError::ENOSYS); } /// @brief 截断当前inode到指定的长度。如果当前文件长度小于len,则不操作。 /// /// @param len 要被截断到的目标长度 fn truncate(&self, _len: usize) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 将当前inode的内容同步到具体设备上 @@ -410,13 +481,73 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { _mode: ModeType, _dev_t: DeviceNumber, ) -> Result, SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); + } + + /// # mkdir - 新建名称为`name`的目录项 + /// + /// 当目录下已有名称为`name`的文件夹时,返回该目录项的引用;否则新建`name`文件夹,并返回该引用。 + /// + /// 该函数会检查`name`目录是否已存在,如果存在但类型不为文件夹,则会返回`EEXIST`错误。 + /// + /// # 参数 + /// + /// - `name`: &str - 要新建的目录项的名称。 + /// - `mode`: ModeType - 设置目录项的权限模式。 + /// + /// # 返回值 + /// + /// - `Ok(Arc)`: 成功时返回`name`目录项的共享引用。 + /// - `Err(SystemError)`: 出错时返回错误信息。 + fn mkdir(&self, name: &str, mode: ModeType) -> Result, SystemError> { + match self.find(name) { + Ok(inode) => { + if inode.metadata()?.file_type == FileType::Dir { + Ok(inode) + } else { + Err(SystemError::EEXIST) + } + } + Err(SystemError::ENOENT) => self.create(name, FileType::Dir, mode), + Err(err) => Err(err), + } } /// ## 返回特殊文件的inode fn special_node(&self) -> Option { None } + + /// # dname - 返回目录名 + /// + /// 此函数用于返回一个目录名。 + /// + /// ## 参数 + /// + /// 无 + /// + /// ## 返回值 + /// - Ok(DName): 成功时返回一个目录名。 + /// - Err(SystemError): 如果系统不支持此操作,则返回一个系统错误。 + fn dname(&self) -> Result { + return Err(SystemError::ENOSYS); + } + + /// # parent - 返回父目录的引用 + /// + /// 当该目录是当前文件系统的根目录时,返回自身的引用。 + /// + /// ## 参数 + /// + /// 无 + /// + /// ## 返回值 + /// + /// - Ok(Arc): A reference to the parent directory + /// - Err(SystemError): If there is an error in finding the parent directory + fn parent(&self) -> Result, SystemError> { + return self.find(".."); + } } impl DowncastArc for dyn IndexNode { diff --git a/kernel/src/filesystem/vfs/mount.rs b/kernel/src/filesystem/vfs/mount.rs index 24ed20dc..7d751583 100644 --- a/kernel/src/filesystem/vfs/mount.rs +++ b/kernel/src/filesystem/vfs/mount.rs @@ -1,22 +1,29 @@ use core::{ any::Any, + fmt::Debug, sync::atomic::{compiler_fence, Ordering}, }; use alloc::{ collections::BTreeMap, + string::{String, ToString}, sync::{Arc, Weak}, }; use system_error::SystemError; use crate::{ driver::base::device::device_number::DeviceNumber, - libs::spinlock::{SpinLock, SpinLockGuard}, + filesystem::vfs::ROOT_INODE, + libs::{ + casting::DowncastArc, + rwlock::RwLock, + spinlock::{SpinLock, SpinLockGuard}, + }, }; use super::{ - file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, InodeId, - Magic, SuperBlock, + file::FileMode, syscall::ModeType, utils::DName, FilePrivateData, FileSystem, FileType, + IndexNode, InodeId, Magic, SuperBlock, }; const MOUNTFS_BLOCK_SIZE: u64 = 512; @@ -49,21 +56,22 @@ pub struct MountFSInode { impl MountFS { pub fn new( - inner_fs: Arc, + inner_filesystem: Arc, self_mountpoint: Option>, ) -> Arc { - return MountFS { - inner_filesystem: inner_fs, + return Arc::new_cyclic(|self_ref| MountFS { + inner_filesystem, mountpoints: SpinLock::new(BTreeMap::new()), self_mountpoint, - self_ref: Weak::default(), - } - .wrap(); + self_ref: self_ref.clone(), + }); } /// @brief 用Arc指针包裹MountFS对象。 /// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针 /// 本函数只应在构造器中被调用 + #[allow(dead_code)] + #[deprecated] fn wrap(self) -> Arc { // 创建Arc指针 let mount_fs: Arc = Arc::new(self); @@ -81,12 +89,11 @@ impl MountFS { /// @brief 获取挂载点的文件系统的root inode pub fn mountpoint_root_inode(&self) -> Arc { - return MountFSInode { + return Arc::new_cyclic(|self_ref| MountFSInode { inner_inode: self.inner_filesystem.root_inode(), mount_fs: self.self_ref.upgrade().unwrap(), - self_ref: Weak::default(), - } - .wrap(); + self_ref: self_ref.clone(), + }); } pub fn inner_filesystem(&self) -> Arc { @@ -96,12 +103,24 @@ impl MountFS { pub fn self_ref(&self) -> Arc { self.self_ref.upgrade().unwrap() } + + /// 卸载文件系统 + /// # Errors + /// 如果当前文件系统是根文件系统,那么将会返回`EINVAL` + pub fn umount(&self) -> Result, SystemError> { + self.self_mountpoint + .as_ref() + .ok_or(SystemError::EINVAL)? + .do_umount() + } } impl MountFSInode { /// @brief 用Arc指针包裹MountFSInode对象。 /// 本函数的主要功能为,初始化MountFSInode对象中的自引用Weak指针 /// 本函数只应在构造器中被调用 + #[allow(dead_code)] + #[deprecated] fn wrap(self) -> Arc { // 创建Arc指针 let inode: Arc = Arc::new(self); @@ -159,6 +178,66 @@ impl MountFSInode { pub(super) fn inode_id(&self) -> InodeId { self.metadata().map(|x| x.inode_id).unwrap() } + + fn do_find(&self, name: &str) -> Result, SystemError> { + // 直接调用当前inode所在的文件系统的find方法进行查找 + // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode + let inner_inode = self.inner_inode.find(name)?; + return Ok(Arc::new_cyclic(|self_ref| MountFSInode { + inner_inode, + mount_fs: self.mount_fs.clone(), + self_ref: self_ref.clone(), + }) + .overlaid_inode()); + } + + pub(super) fn do_parent(&self) -> Result, SystemError> { + if self.is_mountpoint_root()? { + // 当前inode是它所在的文件系统的root inode + match &self.mount_fs.self_mountpoint { + Some(inode) => { + let inner_inode = inode.parent()?; + return Ok(Arc::new_cyclic(|self_ref| MountFSInode { + inner_inode, + mount_fs: self.mount_fs.clone(), + self_ref: self_ref.clone(), + })); + } + None => { + return Ok(self.self_ref.upgrade().unwrap()); + } + } + } else { + let inner_inode = self.inner_inode.parent()?; + // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找 + return Ok(Arc::new_cyclic(|self_ref| MountFSInode { + inner_inode, + mount_fs: self.mount_fs.clone(), + self_ref: self_ref.clone(), + })); + } + } + + /// 移除挂载点下的文件系统 + fn do_umount(&self) -> Result, SystemError> { + if self.metadata()?.file_type != FileType::Dir { + return Err(SystemError::ENOTDIR); + } + return self + .mount_fs + .mountpoints + .lock() + .remove(&self.inner_inode.metadata()?.inode_id) + .ok_or(SystemError::ENOENT); + } + + fn do_absolute_path(&self, len: usize) -> Result { + if self.metadata()?.inode_id == ROOT_INODE().metadata()?.inode_id { + return Ok(String::with_capacity(len)); + } + let name = self.dname()?; + return Ok(self.do_parent()?.do_absolute_path(len + name.0.len() + 1)? + "/" + &name.0); + } } impl IndexNode for MountFSInode { @@ -181,14 +260,14 @@ impl IndexNode for MountFSInode { mode: ModeType, data: usize, ) -> Result, SystemError> { - return Ok(MountFSInode { - inner_inode: self - .inner_inode - .create_with_data(name, file_type, mode, data)?, + let inner_inode = self + .inner_inode + .create_with_data(name, file_type, mode, data)?; + return Ok(Arc::new_cyclic(|self_ref| MountFSInode { + inner_inode, mount_fs: self.mount_fs.clone(), - self_ref: Weak::default(), - } - .wrap()); + self_ref: self_ref.clone(), + })); } fn truncate(&self, len: usize) -> Result<(), SystemError> { @@ -247,12 +326,12 @@ impl IndexNode for MountFSInode { file_type: FileType, mode: ModeType, ) -> Result, SystemError> { - return Ok(MountFSInode { - inner_inode: self.inner_inode.create(name, file_type, mode)?, + let inner_inode = self.inner_inode.create(name, file_type, mode)?; + return Ok(Arc::new_cyclic(|self_ref| MountFSInode { + inner_inode, mount_fs: self.mount_fs.clone(), - self_ref: Weak::default(), - } - .wrap()); + self_ref: self_ref.clone(), + })); } fn link(&self, name: &str, other: &Arc) -> Result<(), SystemError> { @@ -299,41 +378,17 @@ impl IndexNode for MountFSInode { fn find(&self, name: &str) -> Result, SystemError> { match name { // 查找的是当前目录 - "" | "." => return Ok(self.self_ref.upgrade().unwrap()), + "" | "." => self + .self_ref + .upgrade() + .map(|inode| inode as Arc) + .ok_or(SystemError::ENOENT), // 往父级查找 - ".." => { - if self.is_mountpoint_root()? { - // 当前inode是它所在的文件系统的root inode - match &self.mount_fs.self_mountpoint { - Some(inode) => { - return inode.find(name); - } - None => { - return Ok(self.self_ref.upgrade().unwrap()); - } - } - } else { - // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找 - return Ok(MountFSInode { - inner_inode: self.inner_inode.find(name)?, - mount_fs: self.mount_fs.clone(), - self_ref: Weak::default(), - } - .wrap()); - } - } + ".." => self.parent(), // 在当前目录下查找 - _ => { - // 直接调用当前inode所在的文件系统的find方法进行查找 - // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode - return Ok(MountFSInode { - inner_inode: self.inner_inode.find(name)?, - mount_fs: self.mount_fs.clone(), - self_ref: Weak::default(), - } - .wrap() - .overlaid_inode()); - } + // 直接调用当前inode所在的文件系统的find方法进行查找 + // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode + _ => self.do_find(name).map(|inode| inode as Arc), } } @@ -365,21 +420,65 @@ impl IndexNode for MountFSInode { return self.inner_inode.list(); } - /// @brief 在当前inode下,挂载一个文件系统 - /// - /// @return Ok(Arc) 挂载成功,返回指向MountFS的指针 fn mount(&self, fs: Arc) -> Result, SystemError> { let metadata = self.inner_inode.metadata()?; if metadata.file_type != FileType::Dir { return Err(SystemError::ENOTDIR); } - // 为新的挂载点创建挂载文件系统 - let new_mount_fs: Arc = MountFS::new(fs, Some(self.self_ref.upgrade().unwrap())); - self.do_mount(metadata.inode_id, new_mount_fs.clone())?; + if self.is_mountpoint_root()? { + return Err(SystemError::EBUSY); + } + + // 若已有挂载系统,保证MountFS只包一层 + let to_mount_fs = fs + .clone() + .downcast_arc::() + .map(|it| it.inner_filesystem()) + .unwrap_or(fs); + let new_mount_fs = MountFS::new(to_mount_fs, Some(self.self_ref.upgrade().unwrap())); + self.mount_fs + .mountpoints + .lock() + .insert(metadata.inode_id, new_mount_fs.clone()); + + let mount_path = self.absolute_path(); + + MOUNT_LIST().insert(mount_path?, new_mount_fs.clone()); return Ok(new_mount_fs); } + fn mount_from(&self, from: Arc) -> Result, SystemError> { + let metadata = self.metadata()?; + if from.metadata()?.file_type != FileType::Dir || metadata.file_type != FileType::Dir { + return Err(SystemError::ENOTDIR); + } + if self.is_mountpoint_root()? { + return Err(SystemError::EBUSY); + } + // kdebug!("from {:?}, to {:?}", from, self); + let new_mount_fs = from.umount()?; + self.mount_fs + .mountpoints + .lock() + .insert(metadata.inode_id, new_mount_fs.clone()); + + // MOUNT_LIST().remove(from.absolute_path()?); + // MOUNT_LIST().insert(self.absolute_path()?, new_mount_fs.clone()); + return Ok(new_mount_fs); + } + + fn umount(&self) -> Result, SystemError> { + if !self.is_mountpoint_root()? { + return Err(SystemError::EINVAL); + } + return self.mount_fs.umount(); + } + + fn absolute_path(&self) -> Result { + self.do_absolute_path(0) + } + #[inline] fn mknod( &self, @@ -387,12 +486,12 @@ impl IndexNode for MountFSInode { mode: ModeType, dev_t: DeviceNumber, ) -> Result, SystemError> { - return Ok(MountFSInode { - inner_inode: self.inner_inode.mknod(filename, mode, dev_t)?, + let inner_inode = self.inner_inode.mknod(filename, mode, dev_t)?; + return Ok(Arc::new_cyclic(|self_ref| MountFSInode { + inner_inode, mount_fs: self.mount_fs.clone(), - self_ref: Weak::default(), - } - .wrap()); + self_ref: self_ref.clone(), + })); } #[inline] @@ -404,6 +503,23 @@ impl IndexNode for MountFSInode { fn poll(&self, private_data: &FilePrivateData) -> Result { self.inner_inode.poll(private_data) } + + /// 若不支持,则调用第二种情况来从父目录获取文件名 + /// # Performance + /// 应尽可能引入DName, + /// 在默认情况下,性能非常差!!! + fn dname(&self) -> Result { + if self.is_mountpoint_root()? { + if let Some(inode) = &self.mount_fs.self_mountpoint { + return inode.inner_inode.dname(); + } + } + return self.inner_inode.dname(); + } + + fn parent(&self) -> Result, SystemError> { + return self.do_parent().map(|inode| inode as Arc); + } } impl FileSystem for MountFS { @@ -432,3 +548,168 @@ impl FileSystem for MountFS { SuperBlock::new(Magic::MOUNT_MAGIC, MOUNTFS_BLOCK_SIZE, MOUNTFS_MAX_NAMELEN) } } + +/// MountList +/// ```rust +/// use alloc::collection::BTreeSet; +/// let map = BTreeSet::from([ +/// "/sys", "/dev", "/", "/bin", "/proc" +/// ]); +/// assert_eq!(format!("{:?}", map), "{\"/\", \"/bin\", \"/dev\", \"/proc\", \"/sys\"}"); +/// // {"/", "/bin", "/dev", "/proc", "/sys"} +/// ``` +#[derive(PartialEq, Eq, Debug)] +pub struct MountPath(String); + +impl From<&str> for MountPath { + fn from(value: &str) -> Self { + Self(String::from(value)) + } +} + +impl From for MountPath { + fn from(value: String) -> Self { + Self(value) + } +} + +impl AsRef for MountPath { + fn as_ref(&self) -> &str { + &self.0 + } +} + +impl PartialOrd for MountPath { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for MountPath { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + let self_dep = self.0.chars().filter(|c| *c == '/').count(); + let othe_dep = other.0.chars().filter(|c| *c == '/').count(); + if self_dep == othe_dep { + // 深度一样时反序来排 + // 根目录和根目录下的文件的绝对路径都只有一个'/' + other.0.cmp(&self.0) + } else { + // 根据深度,深度 + othe_dep.cmp(&self_dep) + } + } +} + +// 维护一个挂载点的记录,以支持特定于文件系统的索引 +pub struct MountList(RwLock>>); +// pub struct MountList(Option>); +static mut __MOUNTS_LIST: Option> = None; + +/// # init_mountlist - 初始化挂载列表 +/// +/// 此函数用于初始化系统的挂载列表。挂载列表记录了系统中所有的文件系统挂载点及其属性。 +/// +/// ## 参数 +/// +/// - 无 +/// +/// ## 返回值 +/// +/// - 无 +#[inline(always)] +pub fn init_mountlist() { + unsafe { + __MOUNTS_LIST = Some(Arc::new(MountList(RwLock::new(BTreeMap::new())))); + } +} + +/// # MOUNT_LIST - 获取全局挂载列表 +/// +/// 该函数用于获取一个对全局挂载列表的引用。全局挂载列表是系统中所有挂载点的集合。 +/// +/// ## 返回值 +/// - &'static Arc: 返回全局挂载列表的引用。 +#[inline(always)] +#[allow(non_snake_case)] +pub fn MOUNT_LIST() -> &'static Arc { + unsafe { + return __MOUNTS_LIST.as_ref().unwrap(); + } +} + +impl MountList { + /// # insert - 将文件系统挂载点插入到挂载表中 + /// + /// 将一个新的文件系统挂载点插入到挂载表中。如果挂载点已经存在,则会更新对应的文件系统。 + /// + /// 此函数是线程安全的,因为它使用了RwLock来保证并发访问。 + /// + /// ## 参数 + /// + /// - `path`: &str, 挂载点的路径。这个路径会被转换成`MountPath`类型。 + /// - `fs`: Arc, 共享的文件系统实例。 + /// + /// ## 返回值 + /// + /// - 无 + #[inline] + pub fn insert>(&self, path: T, fs: Arc) { + self.0.write().insert(MountPath::from(path.as_ref()), fs); + } + + /// # get_mount_point - 获取挂载点的路径 + /// + /// 这个函数用于查找给定路径的挂载点。它搜索一个内部映射,找到与路径匹配的挂载点。 + /// + /// ## 参数 + /// + /// - `path: T`: 这是一个可转换为字符串的引用,表示要查找其挂载点的路径。 + /// + /// ## 返回值 + /// + /// - `Option<(String, String, Arc)>`: + /// - `Some((mount_point, rest_path, fs))`: 如果找到了匹配的挂载点,返回一个包含挂载点路径、剩余路径和挂载文件系统的元组。 + /// - `None`: 如果没有找到匹配的挂载点,返回 None。 + #[inline] + #[allow(dead_code)] + pub fn get_mount_point>( + &self, + path: T, + ) -> Option<(String, String, Arc)> { + self.0 + .upgradeable_read() + .iter() + .filter_map(|(key, fs)| { + let strkey = key.as_ref(); + if let Some(rest) = path.as_ref().strip_prefix(strkey) { + return Some((strkey.to_string(), rest.to_string(), fs.clone())); + } + None + }) + .next() + } + + /// # remove - 移除挂载点 + /// + /// 从挂载点管理器中移除一个挂载点。 + /// + /// 此函数用于从挂载点管理器中移除一个已经存在的挂载点。如果挂载点不存在,则不进行任何操作。 + /// + /// ## 参数 + /// + /// - `path: T`: `T` 实现了 `Into` trait,代表要移除的挂载点的路径。 + /// + /// ## 返回值 + /// + /// - `Option>`: 返回一个 `Arc` 类型的可选值,表示被移除的挂载点,如果挂载点不存在则返回 `None`。 + #[inline] + pub fn remove>(&self, path: T) -> Option> { + self.0.write().remove(&path.into()) + } +} + +impl Debug for MountList { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_map().entries(MOUNT_LIST().0.read().iter()).finish() + } +} diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 86954d48..c7a24033 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -20,14 +20,14 @@ use crate::{ time::PosixTimeSpec, }; -use super::SuperBlock; use super::{ - core::{do_mkdir, do_remove_dir, do_unlink_at}, + core::{do_mkdir_at, do_remove_dir, do_unlink_at}, fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC}, file::{File, FileMode}, open::{do_faccessat, do_fchmodat, do_sys_open}, utils::{rsplit_path, user_path_at}, - Dirent, FileType, IndexNode, FSMAKER, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES, + Dirent, FileType, IndexNode, SuperBlock, FSMAKER, MAX_PATHLEN, ROOT_INODE, + VFS_MAX_FOLLOW_SYMLINK_TIMES, }; // use crate::kdebug; @@ -452,6 +452,17 @@ bitflags! { const RESOLVE_CACHED = 0x20; } } + +bitflags! { + pub struct UmountFlag: i32 { + const DEFAULT = 0; /* Default call to umount. */ + const MNT_FORCE = 1; /* Force unmounting. */ + const MNT_DETACH = 2; /* Just detach from the tree. */ + const MNT_EXPIRE = 4; /* Mark for expiry. */ + const UMOUNT_NOFOLLOW = 8; /* Don't follow symlink on umount. */ + } +} + impl Syscall { /// @brief 为当前进程打开一个文件 /// @@ -768,7 +779,12 @@ impl Syscall { /// @return uint64_t 负数错误码 / 0表示成功 pub fn mkdir(path: *const u8, mode: usize) -> Result { let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; - return do_mkdir(&path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize); + do_mkdir_at( + AtFlags::AT_FDCWD.bits(), + &path, + FileMode::from_bits_truncate(mode as u32), + )?; + return Ok(0); } /// **创建硬连接的系统调用** @@ -928,9 +944,9 @@ impl Syscall { /// /// ## 参数 /// - /// - oldfd: 源文件描述符 + /// - oldfd: 源文件夹文件描述符 /// - filename_from: 源文件路径 - /// - newfd: 目标文件描述符 + /// - newfd: 目标文件夹文件描述符 /// - filename_to: 目标文件路径 /// - flags: 标志位 /// @@ -1542,13 +1558,28 @@ impl Syscall { let filesystemtype = producefs!(FSMAKER, filesystemtype)?; - return Vcore::do_mount(filesystemtype, target.to_string().as_str()); + Vcore::do_mount(filesystemtype, target.to_string().as_str())?; + + return Ok(0); } // 想法:可以在VFS中实现一个文件系统分发器,流程如下: // 1. 接受从上方传来的文件类型字符串 // 2. 将传入值与启动时准备好的字符串数组逐个比较(probe) // 3. 直接在函数内调用构造方法并直接返回文件系统对象 + + /// src/linux/mount.c `umount` & `umount2` + /// + /// [umount(2) — Linux manual page](https://www.man7.org/linux/man-pages/man2/umount.2.html) + pub fn umount2(target: *const u8, flags: i32) -> Result<(), SystemError> { + let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))?; + Vcore::do_umount2( + AtFlags::AT_FDCWD.bits(), + &target, + UmountFlag::from_bits(flags).ok_or(SystemError::EINVAL)?, + )?; + return Ok(()); + } } #[repr(C)] diff --git a/kernel/src/filesystem/vfs/utils.rs b/kernel/src/filesystem/vfs/utils.rs index cd9077c0..7e9ce6c7 100644 --- a/kernel/src/filesystem/vfs/utils.rs +++ b/kernel/src/filesystem/vfs/utils.rs @@ -1,3 +1,8 @@ +use core::cmp::Ordering; +use core::fmt::Debug; +use core::hash::Hash; + +use alloc::string::ToString; use alloc::{string::String, sync::Arc}; use system_error::SystemError; @@ -72,3 +77,72 @@ pub fn user_path_at( return Ok((inode, ret_path)); } + +/// Directory Name +/// 可以用来作为原地提取目录名及比较的 +/// Dentry的对标(x +/// +/// 简单的生成一个新的DName,以实现简单的RCU +#[derive(Debug)] +pub struct DName(pub Arc); + +impl PartialEq for DName { + fn eq(&self, other: &Self) -> bool { + return *self.0 == *other.0; + } +} +impl Eq for DName {} + +impl Hash for DName { + fn hash(&self, state: &mut H) { + self.0.hash(state) + } +} + +impl PartialOrd for DName { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for DName { + fn cmp(&self, other: &Self) -> Ordering { + return self.0.cmp(&other.0); + } +} + +impl Default for DName { + fn default() -> Self { + Self(Arc::new(String::new())) + } +} + +impl From for DName { + fn from(value: String) -> Self { + Self(Arc::from(value)) + } +} + +impl From<&str> for DName { + fn from(value: &str) -> Self { + Self(Arc::from(String::from(value))) + } +} + +impl Clone for DName { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl ToString for DName { + fn to_string(&self) -> String { + (*self.0).clone() + } +} + +impl AsRef for DName { + fn as_ref(&self) -> &str { + self.0.as_str() + } +} diff --git a/kernel/src/ipc/pipe.rs b/kernel/src/ipc/pipe.rs index a38427fb..a0349a4e 100644 --- a/kernel/src/ipc/pipe.rs +++ b/kernel/src/ipc/pipe.rs @@ -413,7 +413,7 @@ impl IndexNode for LockedPipeInode { } fn list(&self) -> Result, SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn poll(&self, private_data: &FilePrivateData) -> Result { diff --git a/kernel/src/ipc/signal.rs b/kernel/src/ipc/signal.rs index 873b3fcf..df4f0f46 100644 --- a/kernel/src/ipc/signal.rs +++ b/kernel/src/ipc/signal.rs @@ -36,7 +36,7 @@ impl Signal { // 如果并无进程与指定的 pid 相匹配,那么 kill() 调用失败,同时将 errno 置为 ESRCH(“查无此进程”) if pid.lt(&Pid::from(0)) { kwarn!("Kill operation not support: pid={:?}", pid); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } compiler_fence(core::sync::atomic::Ordering::SeqCst); // 检查sig是否符合要求,如果不符合要求,则退出。 diff --git a/kernel/src/ipc/syscall.rs b/kernel/src/ipc/syscall.rs index b196ec1a..995dcfbd 100644 --- a/kernel/src/ipc/syscall.rs +++ b/kernel/src/ipc/syscall.rs @@ -262,7 +262,7 @@ impl Syscall { // 暂不支持巨页 if shmflg.contains(ShmFlags::SHM_HUGETLB) { kerror!("shmget: not support huge page"); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } let mut shm_manager_guard = shm_manager_lock(); diff --git a/kernel/src/libs/lib_ui/screen_manager.rs b/kernel/src/libs/lib_ui/screen_manager.rs index 13516f66..5ed9d49a 100644 --- a/kernel/src/libs/lib_ui/screen_manager.rs +++ b/kernel/src/libs/lib_ui/screen_manager.rs @@ -237,30 +237,30 @@ impl ScmUiFrameworkMetadata { pub trait ScmUiFramework: Sync + Send + Debug { // 安装ui框架的回调函数 fn install(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 卸载ui框架的回调函数 fn uninstall(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 启用ui框架的回调函数 fn enable(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 禁用ui框架的回调函数 fn disable(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 改变ui框架的帧缓冲区的回调函数 fn change(&self, _buf: ScmBufferInfo) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// @brief 获取ScmUiFramework的元数据 /// @return 成功:Ok(ScmUiFramework的元数据) /// 失败:Err(错误码) fn metadata(&self) -> Result { // 若文件系统没有实现此方法,则返回“不支持” - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } } diff --git a/kernel/src/mm/syscall.rs b/kernel/src/mm/syscall.rs index 8d3aa037..743db840 100644 --- a/kernel/src/mm/syscall.rs +++ b/kernel/src/mm/syscall.rs @@ -250,13 +250,13 @@ impl Syscall { // 暂时不支持除匿名页以外的映射 if !map_flags.contains(MapFlags::MAP_ANONYMOUS) { kerror!("mmap: not support file mapping"); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 暂时不支持巨页映射 if map_flags.contains(MapFlags::MAP_HUGETLB) { kerror!("mmap: not support huge page mapping"); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } let current_address_space = AddressSpace::current()?; let start_page = current_address_space.write().map_anonymous( diff --git a/kernel/src/mm/ucontext.rs b/kernel/src/mm/ucontext.rs index a04867c3..a26beee6 100644 --- a/kernel/src/mm/ucontext.rs +++ b/kernel/src/mm/ucontext.rs @@ -779,7 +779,7 @@ impl UserMappings { if flags.contains(MapFlags::MAP_FIXED) { // todo: 支持MAP_FIXED标志对已有的VMA进行覆盖 - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 如果没有指定MAP_FIXED标志,那么就对地址做修正 diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index e207e637..c8cb7648 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -1030,6 +1030,14 @@ impl Syscall { let filesystemtype = args[2] as *const u8; return Self::mount(source, target, filesystemtype, 0, null()); } + + SYS_UMOUNT2 => { + let target = args[0] as *const u8; + let flags = args[1] as i32; + Self::umount2(target, flags)?; + return Ok(0); + } + SYS_NEWFSTATAT => { // todo: 这个系统调用还没有实现 diff --git a/kernel/src/time/clocksource.rs b/kernel/src/time/clocksource.rs index 19bf57ab..d67d81c9 100644 --- a/kernel/src/time/clocksource.rs +++ b/kernel/src/time/clocksource.rs @@ -196,29 +196,29 @@ pub trait Clocksource: Send + Sync + Debug { fn read(&self) -> CycleNum; /// optional function to enable the clocksource fn enable(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// optional function to disable the clocksource fn disable(&self) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// vsyscall based read fn vread(&self) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// suspend function for the clocksource, if necessary fn suspend(&self) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } /// resume function for the clocksource, if necessary fn resume(&self) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 获取时钟源数据 fn clocksource_data(&self) -> ClocksourceData; fn update_clocksource_data(&self, _data: ClocksourceData) -> Result<(), SystemError> { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } // 获取时钟源 fn clocksource(&self) -> Arc; diff --git a/kernel/src/virt/kvm/kvm_dev.rs b/kernel/src/virt/kvm/kvm_dev.rs index d5243941..3a900f6a 100644 --- a/kernel/src/virt/kvm/kvm_dev.rs +++ b/kernel/src/virt/kvm/kvm_dev.rs @@ -111,7 +111,7 @@ impl IndexNode for LockedKvmInode { } fn list(&self) -> Result, SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { @@ -153,7 +153,7 @@ impl IndexNode for LockedKvmInode { | KVM_GET_VCPU_MMAP_SIZE | KVM_TRACE_ENABLE | KVM_TRACE_PAUSE - | KVM_TRACE_DISABLE => Err(SystemError::EOPNOTSUPP_OR_ENOTSUP), + | KVM_TRACE_DISABLE => Err(SystemError::ENOSYS), _ => KVMArch::kvm_arch_dev_ioctl(cmd, data), } } @@ -165,7 +165,7 @@ impl IndexNode for LockedKvmInode { _buf: &mut [u8], _data: SpinLockGuard, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写 @@ -176,7 +176,7 @@ impl IndexNode for LockedKvmInode { _buf: &[u8], _data: SpinLockGuard, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } } diff --git a/kernel/src/virt/kvm/vcpu_dev.rs b/kernel/src/virt/kvm/vcpu_dev.rs index 31d1bbe8..53e56e8c 100644 --- a/kernel/src/virt/kvm/vcpu_dev.rs +++ b/kernel/src/virt/kvm/vcpu_dev.rs @@ -119,7 +119,7 @@ impl IndexNode for LockedVcpuInode { } fn list(&self) -> Result, SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { @@ -204,7 +204,7 @@ impl IndexNode for LockedVcpuInode { _buf: &mut [u8], _data: SpinLockGuard, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写 @@ -215,6 +215,6 @@ impl IndexNode for LockedVcpuInode { _buf: &[u8], _data: SpinLockGuard, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } } diff --git a/kernel/src/virt/kvm/vm_dev.rs b/kernel/src/virt/kvm/vm_dev.rs index f860da62..4b2f1fac 100644 --- a/kernel/src/virt/kvm/vm_dev.rs +++ b/kernel/src/virt/kvm/vm_dev.rs @@ -117,7 +117,7 @@ impl IndexNode for LockedVmInode { } fn list(&self) -> Result, SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { @@ -181,7 +181,7 @@ impl IndexNode for LockedVmInode { Ok(0) } KVM_GET_DIRTY_LOG | KVM_IRQFD | KVM_IOEVENTFD | KVM_IRQ_LINE_STATUS => { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } _ => { kdebug!("kvm_vm ioctl"); @@ -197,7 +197,7 @@ impl IndexNode for LockedVmInode { _buf: &mut [u8], _data: SpinLockGuard, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } /// 写设备 - 应该调用设备的函数读写,而不是通过文件系统读写 @@ -208,7 +208,7 @@ impl IndexNode for LockedVmInode { _buf: &[u8], _data: SpinLockGuard, ) -> Result { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } } diff --git a/user/apps/test_ramfs/.gitignore b/user/apps/test_ramfs/.gitignore new file mode 100644 index 00000000..3d1060bb --- /dev/null +++ b/user/apps/test_ramfs/.gitignore @@ -0,0 +1 @@ +test_ramfs diff --git a/user/apps/test_ramfs/Makefile b/user/apps/test_ramfs/Makefile new file mode 100644 index 00000000..fa1e746d --- /dev/null +++ b/user/apps/test_ramfs/Makefile @@ -0,0 +1,20 @@ +ifeq ($(ARCH), x86_64) + CROSS_COMPILE=x86_64-linux-musl- +else ifeq ($(ARCH), riscv64) + CROSS_COMPILE=riscv64-linux-musl- +endif + +CC=$(CROSS_COMPILE)gcc + +.PHONY: all +all: main.c + $(CC) -static -o test_ramfs main.c + +.PHONY: install clean +install: all + mv test_ramfs $(DADK_CURRENT_BUILD_DIR)/test_ramfs + +clean: + rm test_ramfs *.o + +fmt: diff --git a/user/apps/test_ramfs/main.c b/user/apps/test_ramfs/main.c new file mode 100644 index 00000000..5915159d --- /dev/null +++ b/user/apps/test_ramfs/main.c @@ -0,0 +1,115 @@ +// #include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PATH_LENGTH 100 +#define MAX_DIR_DEPTH 4 + + +int main(int argc, char const* argv[]) { + + if (mkdir("/SOME", 0777) == -1) { + perror("Failed to create directory under /some"); + return 1; + } + + // Create a directory under /SOME/RAMFS + if (mkdir("/SOME/RAMFS", 0777) == -1) { + perror("Failed to create directory under /SOME/RAMFS"); + return 1; + } + + // Mount the first ramfs at /SOME/RAMFS + if (mount("", "/SOME/RAMFS", "ramfs", 0, NULL) == -1) { + perror("Failed to mount ramfs at /SOME/RAMFS"); + return 1; + } + + if (mkdir("/SOME/RAMFS/some", 0777) == -1) { + perror("Failed to create directory under /SOME/RAMFS/some"); + return 1; + } + + puts("Success mkdir /SOME/RAMFS/some"); + + // Create a directory under /SOME/RAMFS/some/another + if (mkdir("/SOME/RAMFS/some/another", 0777) == -1) { + perror("Failed to create directory under /SOME/RAMFS/some/another"); + return 1; + } + + puts("Success mkdir /SOME/RAMFS/some/another"); + + if (mount("", "/SOME/RAMFS/some/another", "ramfs", 0, NULL) == -1) { + perror("Failed to mount ramfs at /SOME/RAMFS/some/another"); + return 1; + } + + puts("Success mount on /SOME/RAMFS/some/another"); + + if (mkdir("/SOME/RAMFS/some/another/just_another", 0777) == -1) { + perror("Failed to create directory under /SOME/RAMFS/some/another"); + return 1; + } + + puts("Success mkdir /SOME/RAMFS/some/another/just_another"); + + if (mount("", "/SOME/RAMFS/some/another/just_another", "ramfs", 0, NULL) == -1) { + perror("Failed to mount ramfs at /SOME/RAMFS/some/another"); + return 1; + } + + puts("Success mount on /SOME/RAMFS/some/another/just_another"); + + // Write files under /SOME/RAMFS and /SOME/RAMFS/some/another + FILE* file1 = fopen("/SOME/RAMFS/file1.txt", "w"); + if (file1 == NULL) { + perror("Failed to open /SOME/RAMFS/file1.txt"); + return 1; + } + fprintf(file1, "This is file1.txt\n"); + fclose(file1); + + FILE* file2 = fopen("/SOME/RAMFS/some/another/file2.txt", "w"); + if (file2 == NULL) { + perror("Failed to open /SOME/RAMFS/some/another/file2.txt"); + return 1; + } + fprintf(file2, "This is file2.txt\n"); + fclose(file2); + + FILE* file3 = fopen("/SOME/RAMFS/some/another/just_another/file3.txt", "w+"); + if (file3 == NULL) { + perror("Failed to open /SOME/RAMFS/some/another/just_another/file3.txt"); + return 1; + } + fprintf(file3, "Multi mount behave well.\n"); + // print file3.txt + char buffer[100]; + fseek(file3, 0, SEEK_SET); + fread(buffer, 1, 100, file3); + printf("file3.txt content: %s\n", buffer); + fclose(file3); + + // test umount with flags ( use umount2 ) + if (umount("/SOME/RAMFS/some/another/just_another") == -1) { + perror("Failed to umount ramfs at /SOME/RAMFS/some/another/just_another"); + return 1; + } + + puts("Successful umount /SOME/RAMFS/some/another/just_another"); + + // delete just_another + if (rmdir("/SOME/RAMFS/some/another/just_another") == -1) { + perror("Failed to delete /SOME/RAMFS/some/another/just_another"); + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/user/dadk/config/test_ramfs-0.1.0.dadk b/user/dadk/config/test_ramfs-0.1.0.dadk new file mode 100644 index 00000000..8eca983e --- /dev/null +++ b/user/dadk/config/test_ramfs-0.1.0.dadk @@ -0,0 +1,23 @@ +{ + "name": "test_ramfs", + "version": "0.1.0", + "description": "ramfs test bench", + "task_type": { + "BuildFromSource": { + "Local": { + "path": "apps/test_ramfs" + } + } + }, + "depends": [], + "build": { + "build_command": "make install" + }, + "install": { + "in_dragonos_path": "/bin" + }, + "clean": { + "clean_command": "make clean" + }, + "envs": [] +}