diff --git a/kernel/src/fs/inode_handle/dyn_cap.rs b/kernel/src/fs/inode_handle/dyn_cap.rs index 5c4bbce1c..584c10b77 100644 --- a/kernel/src/fs/inode_handle/dyn_cap.rs +++ b/kernel/src/fs/inode_handle/dyn_cap.rs @@ -204,7 +204,7 @@ impl FileLike for InodeHandle { } fn inode(&self) -> &Arc { - self.0.inode() + self.0.path.inode() } } diff --git a/kernel/src/fs/inode_handle/mod.rs b/kernel/src/fs/inode_handle/mod.rs index f7e73bdac..882361c3b 100644 --- a/kernel/src/fs/inode_handle/mod.rs +++ b/kernel/src/fs/inode_handle/mod.rs @@ -7,7 +7,6 @@ mod dyn_cap; use core::sync::atomic::{AtomicU32, Ordering}; pub use dyn_cap::InodeHandle; -use inherit_methods_macro::inherit_methods; use crate::{ events::IoEvents, @@ -252,12 +251,6 @@ impl HandleInner { } } -#[inherit_methods(from = "self.path")] -impl HandleInner { - pub(self) fn size(&self) -> usize; - pub(self) fn inode(&self) -> &Arc; -} - impl Debug for HandleInner { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("HandleInner") diff --git a/kernel/src/fs/path/dentry.rs b/kernel/src/fs/path/dentry.rs index d556a33a2..7615c8827 100644 --- a/kernel/src/fs/path/dentry.rs +++ b/kernel/src/fs/path/dentry.rs @@ -1,24 +1,14 @@ // SPDX-License-Identifier: MPL-2.0 -#![expect(dead_code)] - -use core::{ - sync::atomic::{AtomicU32, Ordering}, - time::Duration, -}; +use core::sync::atomic::{AtomicU32, Ordering}; use hashbrown::HashMap; -use inherit_methods_macro::inherit_methods; use ostd::sync::RwMutexWriteGuard; use super::is_dot_or_dotdot; use crate::{ - fs::utils::{ - FileSystem, Inode, InodeMode, InodeType, Metadata, MknodType, XattrName, XattrNamespace, - XattrSetFlags, - }, + fs::utils::{Inode, InodeMode, InodeType, MknodType}, prelude::*, - process::{Gid, Uid}, }; /// A `Dentry` represents a cached filesystem node in the VFS tree. @@ -100,6 +90,12 @@ impl Dentry { &self.inode } + /// Returns whether the dentry can be cached. + fn is_dentry_cacheable(&self) -> bool { + // Should we store it as a dentry flag? + self.inode.is_dentry_cacheable() + } + fn flags(&self) -> DentryFlags { let flags = self.flags.load(Ordering::Relaxed); DentryFlags::from_bits(flags).unwrap() @@ -355,48 +351,14 @@ impl Dentry { } } -#[inherit_methods(from = "self.inode")] -impl Dentry { - pub(super) fn fs(&self) -> Arc; - pub(super) fn sync_all(&self) -> Result<()>; - pub(super) fn sync_data(&self) -> Result<()>; - pub(super) fn metadata(&self) -> Metadata; - pub(super) fn mode(&self) -> Result; - pub(super) fn set_mode(&self, mode: InodeMode) -> Result<()>; - pub(super) fn size(&self) -> usize; - pub(super) fn resize(&self, size: usize) -> Result<()>; - pub(super) fn owner(&self) -> Result; - pub(super) fn set_owner(&self, uid: Uid) -> Result<()>; - pub(super) fn group(&self) -> Result; - pub(super) fn set_group(&self, gid: Gid) -> Result<()>; - pub(super) fn atime(&self) -> Duration; - pub(super) fn set_atime(&self, time: Duration); - pub(super) fn mtime(&self) -> Duration; - pub(super) fn set_mtime(&self, time: Duration); - pub(super) fn ctime(&self) -> Duration; - pub(super) fn set_ctime(&self, time: Duration); - pub(super) fn is_dentry_cacheable(&self) -> bool; - pub(super) fn set_xattr( - &self, - name: XattrName, - value_reader: &mut VmReader, - flags: XattrSetFlags, - ) -> Result<()>; - pub(super) fn get_xattr(&self, name: XattrName, value_writer: &mut VmWriter) -> Result; - pub(super) fn list_xattr( - &self, - namespace: XattrNamespace, - list_writer: &mut VmWriter, - ) -> Result; - pub(super) fn remove_xattr(&self, name: XattrName) -> Result<()>; -} - impl Debug for Dentry { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("Dentry") .field("inode", &self.inode) - .field("flags", &self.flags()) - .finish() + .field("type_", &self.type_) + .field("flags", &self.flags) + .field("mount_count", &self.mount_count) + .finish_non_exhaustive() } } @@ -459,6 +421,7 @@ impl DentryChildren { } /// Checks if a negative dentry with the given name exists. + #[expect(dead_code)] fn contains_negative(&self, name: &str) -> bool { self.dentries.get(name).is_some_and(|child| child.is_none()) } diff --git a/kernel/src/fs/path/mod.rs b/kernel/src/fs/path/mod.rs index f9a670007..d5ccaaaae 100644 --- a/kernel/src/fs/path/mod.rs +++ b/kernel/src/fs/path/mod.rs @@ -11,7 +11,7 @@ pub use mount_namespace::MountNamespace; use crate::{ fs::{ inode_handle::InodeHandle, - path::dentry::{Dentry, DentryKey}, + path::dentry::Dentry, utils::{ CreationFlags, FileSystem, FsFlags, Inode, InodeMode, InodeType, Metadata, MknodType, OpenArgs, Permission, StatusFlags, XattrName, XattrNamespace, XattrSetFlags, NAME_MAX, @@ -99,6 +99,23 @@ impl Path { Ok(target_path.get_top_path()) } + /// Opens the `Path` with the given `OpenArgs`. + /// + /// Returns an `InodeHandle` on success. + pub fn open(&self, open_args: OpenArgs) -> Result { + let inode = self.inode(); + check_open_util(inode.as_ref(), &open_args)?; + + if inode.type_().is_regular_file() + && open_args.creation_flags.contains(CreationFlags::O_TRUNC) + && !open_args.status_flags.contains(StatusFlags::O_PATH) + { + self.resize(0)?; + } + + InodeHandle::new(self.clone(), open_args.access_mode, open_args.status_flags) + } + /// Gets the absolute path. /// /// It will resolve the mountpoint automatically. @@ -195,6 +212,33 @@ impl Path { } } +/// Checks if the given `Inode` can be opened with the given `OpenArgs`. +pub(super) fn check_open_util(inode: &dyn Inode, open_args: &OpenArgs) -> Result<()> { + let inode_type = inode.type_(); + let creation_flags = &open_args.creation_flags; + + if inode_type == InodeType::SymLink + && creation_flags.contains(CreationFlags::O_NOFOLLOW) + && !open_args.status_flags.contains(StatusFlags::O_PATH) + { + return_errno_with_message!(Errno::ELOOP, "the file is a symlink"); + } + + if creation_flags.contains(CreationFlags::O_CREAT) + && creation_flags.contains(CreationFlags::O_EXCL) + { + return_errno_with_message!(Errno::EEXIST, "the file already exists"); + } + if creation_flags.contains(CreationFlags::O_DIRECTORY) && inode_type != InodeType::Dir { + return_errno_with_message!( + Errno::ENOTDIR, + "O_DIRECTORY is specified but the file is not a directory" + ); + } + + Ok(()) +} + impl Path { /// Mounts a filesystem at the current path. /// @@ -394,6 +438,15 @@ impl Path { Ok(()) } +} + +// Methods inherited from `Dentry`. +#[inherit_methods(from = "self.dentry")] +impl Path { + pub fn inode(&self) -> &Arc; + pub fn type_(&self) -> InodeType; + pub fn unlink(&self, name: &str) -> Result<()>; + pub fn rmdir(&self, name: &str) -> Result<()>; /// Creates a `Path` by making an inode of the `type_` with the `mode`. pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result { @@ -418,61 +471,15 @@ impl Path { self.dentry.rename(old_name, &new_dir.dentry, new_name) } - - /// Opens the `Path` with the given `OpenArgs`. - /// - /// Returns an `InodeHandle` on success. - pub fn open(&self, open_args: OpenArgs) -> Result { - let inode = self.inode(); - check_open_util(inode.as_ref(), &open_args)?; - - if inode.type_().is_regular_file() - && open_args.creation_flags.contains(CreationFlags::O_TRUNC) - && !open_args.status_flags.contains(StatusFlags::O_PATH) - { - self.resize(0)?; - } - - InodeHandle::new(self.clone(), open_args.access_mode, open_args.status_flags) - } } -/// Checks if the given `Inode` can be opened with the given `OpenArgs`. -pub fn check_open_util(inode: &dyn Inode, open_args: &OpenArgs) -> Result<()> { - let inode_type = inode.type_(); - let creation_flags = &open_args.creation_flags; - - if inode_type == InodeType::SymLink - && creation_flags.contains(CreationFlags::O_NOFOLLOW) - && !open_args.status_flags.contains(StatusFlags::O_PATH) - { - return_errno_with_message!(Errno::ELOOP, "the file is a symlink"); - } - - if creation_flags.contains(CreationFlags::O_CREAT) - && creation_flags.contains(CreationFlags::O_EXCL) - { - return_errno_with_message!(Errno::EEXIST, "the file already exists"); - } - if creation_flags.contains(CreationFlags::O_DIRECTORY) && inode_type != InodeType::Dir { - return_errno_with_message!( - Errno::ENOTDIR, - "O_DIRECTORY is specified but the file is not a directory" - ); - } - - Ok(()) -} - -#[inherit_methods(from = "self.dentry")] +// Methods inherited from `Inode`. +#[inherit_methods(from = "self.inode()")] impl Path { - pub fn unlink(&self, name: &str) -> Result<()>; - pub fn rmdir(&self, name: &str) -> Result<()>; pub fn fs(&self) -> Arc; pub fn sync_all(&self) -> Result<()>; pub fn sync_data(&self) -> Result<()>; pub fn metadata(&self) -> Metadata; - pub fn type_(&self) -> InodeType; pub fn mode(&self) -> Result; pub fn set_mode(&self, mode: InodeMode) -> Result<()>; pub fn size(&self) -> usize; @@ -487,9 +494,6 @@ impl Path { pub fn set_mtime(&self, time: Duration); pub fn ctime(&self) -> Duration; pub fn set_ctime(&self, time: Duration); - pub fn key(&self) -> DentryKey; - pub fn inode(&self) -> &Arc; - pub fn is_mountpoint(&self) -> bool; pub fn set_xattr( &self, name: XattrName, diff --git a/kernel/src/fs/path/mount.rs b/kernel/src/fs/path/mount.rs index b8b98449a..1be511a56 100644 --- a/kernel/src/fs/path/mount.rs +++ b/kernel/src/fs/path/mount.rs @@ -371,7 +371,7 @@ impl Mount { /// Attaches the mount node to the mountpoint. fn attach_to_path(&self, target_path: &Path) { - let key = target_path.key(); + let key = target_path.dentry.key(); target_path .mount_node() .children