From ea489252f409fa8bded732655cd75071c952d78a Mon Sep 17 00:00:00 2001 From: Shaowei Song Date: Thu, 10 Oct 2024 12:51:26 +0000 Subject: [PATCH] Refactor `Dentry` to optimize the vfs layer --- kernel/src/device/pty/mod.rs | 2 +- kernel/src/fs/device.rs | 2 +- kernel/src/fs/fs_resolver.rs | 36 +-- kernel/src/fs/inode_handle/dyn_cap.rs | 8 +- kernel/src/fs/inode_handle/mod.rs | 4 +- kernel/src/fs/path/dentry.rs | 251 +++++++++--------- kernel/src/fs/path/mount.rs | 17 +- kernel/src/net/socket/unix/addr.rs | 2 +- kernel/src/net/socket/unix/ns/path.rs | 4 +- .../process/program_loader/elf/load_elf.rs | 6 +- kernel/src/process/program_loader/mod.rs | 4 +- kernel/src/syscall/execve.rs | 8 +- kernel/src/syscall/mount.rs | 6 +- kernel/src/syscall/utimens.rs | 2 +- 14 files changed, 177 insertions(+), 175 deletions(-) diff --git a/kernel/src/device/pty/mod.rs b/kernel/src/device/pty/mod.rs index bbc0098eb..0faf80f84 100644 --- a/kernel/src/device/pty/mod.rs +++ b/kernel/src/device/pty/mod.rs @@ -16,7 +16,7 @@ mod pty; pub use pty::{PtyMaster, PtySlave}; use spin::Once; -static DEV_PTS: Once> = Once::new(); +static DEV_PTS: Once = Once::new(); pub fn init() -> Result<()> { let fs = FsResolver::new(); diff --git a/kernel/src/fs/device.rs b/kernel/src/fs/device.rs index 2cfafb276..8aa9e1315 100644 --- a/kernel/src/fs/device.rs +++ b/kernel/src/fs/device.rs @@ -91,7 +91,7 @@ impl From for DeviceId { /// /// If the parent path is not existing, `mkdir -p` the parent path. /// This function is used in registering device. -pub fn add_node(device: Arc, path: &str) -> Result> { +pub fn add_node(device: Arc, path: &str) -> Result { let mut dentry = { let fs_resolver = FsResolver::new(); fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())? diff --git a/kernel/src/fs/fs_resolver.rs b/kernel/src/fs/fs_resolver.rs index e4f98fe01..0ecf82e37 100644 --- a/kernel/src/fs/fs_resolver.rs +++ b/kernel/src/fs/fs_resolver.rs @@ -17,8 +17,8 @@ pub const AT_FDCWD: FileDesc = -100; /// File system resolver. #[derive(Debug, Clone)] pub struct FsResolver { - root: Arc, - cwd: Arc, + root: Dentry, + cwd: Dentry, } impl FsResolver { @@ -31,22 +31,22 @@ impl FsResolver { } /// Gets the root directory. - pub fn root(&self) -> &Arc { + pub fn root(&self) -> &Dentry { &self.root } /// Gets the current working directory. - pub fn cwd(&self) -> &Arc { + pub fn cwd(&self) -> &Dentry { &self.cwd } /// Sets the current working directory to the given `dentry`. - pub fn set_cwd(&mut self, dentry: Arc) { + pub fn set_cwd(&mut self, dentry: Dentry) { self.cwd = dentry; } /// Sets the root directory to the given `dentry`. - pub fn set_root(&mut self, dentry: Arc) { + pub fn set_root(&mut self, dentry: Dentry) { self.root = dentry; } @@ -76,7 +76,7 @@ impl FsResolver { fn open_existing_file( &self, - target_dentry: Arc, + target_dentry: Dentry, open_args: &OpenArgs, ) -> Result { let inode = target_dentry.inode(); @@ -147,19 +147,19 @@ impl FsResolver { /// Lookups the target dentry according to the `path`. /// Symlinks are always followed. - pub fn lookup(&self, path: &FsPath) -> Result> { + pub fn lookup(&self, path: &FsPath) -> Result { let (follow_tail_link, stop_on_parent) = (true, false); self.lookup_inner(path, &mut LookupCtx::new(follow_tail_link, stop_on_parent)) } /// Lookups the target dentry according to the `path`. /// If the last component is a symlink, it will not be followed. - pub fn lookup_no_follow(&self, path: &FsPath) -> Result> { + pub fn lookup_no_follow(&self, path: &FsPath) -> Result { let (follow_tail_link, stop_on_parent) = (false, false); self.lookup_inner(path, &mut LookupCtx::new(follow_tail_link, stop_on_parent)) } - fn lookup_inner(&self, path: &FsPath, lookup_ctx: &mut LookupCtx) -> Result> { + fn lookup_inner(&self, path: &FsPath, lookup_ctx: &mut LookupCtx) -> Result { let dentry = match path.inner { FsPathInner::Absolute(path) => { self.lookup_from_parent(&self.root, path.trim_start_matches('/'), lookup_ctx)? @@ -192,10 +192,10 @@ impl FsResolver { #[allow(clippy::redundant_closure)] fn lookup_from_parent( &self, - parent: &Arc, + parent: &Dentry, relative_path: &str, lookup_ctx: &mut LookupCtx, - ) -> Result> { + ) -> Result { debug_assert!(!relative_path.starts_with('/')); if relative_path.len() > PATH_MAX { @@ -285,7 +285,7 @@ impl FsResolver { } /// Lookups the target dentry according to the given `fd`. - pub fn lookup_from_fd(&self, fd: FileDesc) -> Result> { + pub fn lookup_from_fd(&self, fd: FileDesc) -> Result { let current = current!(); let file_table = current.file_table().lock(); let inode_handle = file_table @@ -299,7 +299,7 @@ impl FsResolver { /// the base file name according to the given `path`. /// /// If the last component is a symlink, do not deference it. - pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc, String)> { + pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Dentry, String)> { if matches!(path.inner, FsPathInner::Fd(_)) { return_errno!(Errno::ENOENT); } @@ -327,7 +327,7 @@ impl FsResolver { &self, path: &FsPath, is_dir: bool, - ) -> Result<(Arc, String)> { + ) -> Result<(Dentry, String)> { if matches!(path.inner, FsPathInner::Fd(_)) { return_errno!(Errno::ENOENT); } @@ -364,7 +364,7 @@ struct LookupCtx { stop_on_parent: bool, // (file_name, file_is_dir) tail_file: Option<(String, bool)>, - parent: Option>, + parent: Option, } impl LookupCtx { @@ -394,7 +394,7 @@ impl LookupCtx { .unwrap_or(false) } - pub fn parent(&self) -> Option<&Arc> { + pub fn parent(&self) -> Option<&Dentry> { self.parent.as_ref() } @@ -402,7 +402,7 @@ impl LookupCtx { let _ = self.tail_file.insert((file_name.to_string(), file_is_dir)); } - pub fn set_parent(&mut self, parent: &Arc) { + pub fn set_parent(&mut self, parent: &Dentry) { let _ = self.parent.insert(parent.clone()); } } diff --git a/kernel/src/fs/inode_handle/dyn_cap.rs b/kernel/src/fs/inode_handle/dyn_cap.rs index 002e69d8b..14b263ecb 100644 --- a/kernel/src/fs/inode_handle/dyn_cap.rs +++ b/kernel/src/fs/inode_handle/dyn_cap.rs @@ -7,11 +7,7 @@ use super::*; use crate::{prelude::*, process::signal::Pollable}; impl InodeHandle { - pub fn new( - dentry: Arc, - access_mode: AccessMode, - status_flags: StatusFlags, - ) -> Result { + pub fn new(dentry: Dentry, access_mode: AccessMode, status_flags: StatusFlags) -> Result { let inode_mode = dentry.inode().mode()?; if access_mode.is_readable() && !inode_mode.is_readable() { return_errno_with_message!(Errno::EACCES, "file is not readable"); @@ -24,7 +20,7 @@ impl InodeHandle { } pub fn new_unchecked_access( - dentry: Arc, + dentry: Dentry, access_mode: AccessMode, status_flags: StatusFlags, ) -> Result { diff --git a/kernel/src/fs/inode_handle/mod.rs b/kernel/src/fs/inode_handle/mod.rs index d06d1e844..6d759f9aa 100644 --- a/kernel/src/fs/inode_handle/mod.rs +++ b/kernel/src/fs/inode_handle/mod.rs @@ -32,7 +32,7 @@ use crate::{ pub struct InodeHandle(Arc, R); struct InodeHandle_ { - dentry: Arc, + dentry: Dentry, /// `file_io` is Similar to `file_private` field in `file` structure in linux. If /// `file_io` is Some, typical file operations including `read`, `write`, `poll`, /// `ioctl` will be provided by `file_io`, instead of `dentry`. @@ -354,7 +354,7 @@ impl Debug for InodeHandle_ { /// Methods for both dyn and static impl InodeHandle { - pub fn dentry(&self) -> &Arc { + pub fn dentry(&self) -> &Dentry { &self.0.dentry } diff --git a/kernel/src/fs/path/dentry.rs b/kernel/src/fs/path/dentry.rs index dc305069b..cbf756248 100644 --- a/kernel/src/fs/path/dentry.rs +++ b/kernel/src/fs/path/dentry.rs @@ -22,21 +22,20 @@ use crate::{ }; /// A `Dentry` is used to represent a location in the mount tree. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Dentry { mount_node: Arc, inner: Arc, - this: Weak, } /// The inner structure of `Dentry` for caching helpful nodes /// to accelerate the path lookup. pub struct Dentry_ { inode: Arc, - name_and_parent: RwMutex)>>, - this: Weak, + name_and_parent: RwLock)>>, children: RwMutex, flags: AtomicU32, + this: Weak, } impl Dentry_ { @@ -53,8 +52,8 @@ impl Dentry_ { inode, flags: AtomicU32::new(DentryFlags::empty().bits()), name_and_parent: match options { - DentryOptions::Leaf(name_and_parent) => RwMutex::new(Some(name_and_parent)), - _ => RwMutex::new(None), + DentryOptions::Leaf(name_and_parent) => RwLock::new(Some(name_and_parent)), + _ => RwLock::new(None), }, this: weak_self.clone(), children: RwMutex::new(Children::new()), @@ -139,129 +138,116 @@ impl Dentry_ { /// Creates a `Dentry_` by creating a new inode of the `type_` with the `mode`. pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { - if self.inode.type_() != InodeType::Dir { + if self.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let children = self.children.upread(); - if children.find_dentry(name).is_some() { + if children.contains(name) { return_errno!(Errno::EEXIST); } - let child = { - let inode = self.inode.create(name, type_, mode)?; - let dentry = Self::new( - inode, - DentryOptions::Leaf((String::from(name), self.this())), - ); + let new_inode = self.inode.create(name, type_, mode)?; + let name = String::from(name); + let new_child = Dentry_::new(new_inode, DentryOptions::Leaf((name.clone(), self.this()))); - let mut children = children.upgrade(); - children.insert_dentry(&dentry); - dentry - }; - Ok(child) + let mut children = children.upgrade(); + children.insert(name, new_child.clone()); + Ok(new_child) } /// Lookups a target `Dentry_` from the cache in children. pub fn lookup_via_cache(&self, name: &str) -> Option> { let children = self.children.read(); - children.find_dentry(name) + children.find(name) } /// Lookups a target `Dentry_` from the file system. pub fn lookup_via_fs(&self, name: &str) -> Result> { let children = self.children.upread(); + let inode = self.inode.lookup(name)?; - let inner = Self::new( - inode, - DentryOptions::Leaf((String::from(name), self.this())), - ); + let name = String::from(name); + let target = Self::new(inode, DentryOptions::Leaf((name.clone(), self.this()))); let mut children = children.upgrade(); - children.insert_dentry(&inner); - Ok(inner) - } - - fn insert_dentry(&self, child_dentry: &Arc) { - let mut children = self.children.write(); - children.insert_dentry(child_dentry); + children.insert(name, target.clone()); + Ok(target) } /// Creates a `Dentry_` by making an inode of the `type_` with the `mode`. pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result> { - if self.inode.type_() != InodeType::Dir { + if self.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let children = self.children.upread(); - if children.find_dentry(name).is_some() { + if children.contains(name) { return_errno!(Errno::EEXIST); } - let child = { - let inode = self.inode.mknod(name, mode, type_)?; - let dentry = Self::new( - inode, - DentryOptions::Leaf((String::from(name), self.this())), - ); + let inode = self.inode.mknod(name, mode, type_)?; + let name = String::from(name); + let new_child = Dentry_::new(inode, DentryOptions::Leaf((name.clone(), self.this()))); - let mut children = children.upgrade(); - children.insert_dentry(&dentry); - dentry - }; - Ok(child) + let mut children = children.upgrade(); + children.insert(name, new_child.clone()); + Ok(new_child) } /// Links a new name for the `Dentry_` by `link()` the inner inode. pub fn link(&self, old: &Arc, name: &str) -> Result<()> { - if self.inode.type_() != InodeType::Dir { + if self.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let children = self.children.upread(); - if children.find_dentry(name).is_some() { + if children.contains(name) { return_errno!(Errno::EEXIST); } let old_inode = old.inode(); self.inode.link(old_inode, name)?; - let dentry = Self::new( + let name = String::from(name); + let dentry = Dentry_::new( old_inode.clone(), - DentryOptions::Leaf((String::from(name), self.this())), + DentryOptions::Leaf((name.clone(), self.this())), ); let mut children = children.upgrade(); - children.insert_dentry(&dentry); + children.insert(name, dentry); Ok(()) } /// Deletes a `Dentry_` by `unlink()` the inner inode. pub fn unlink(&self, name: &str) -> Result<()> { - if self.inode.type_() != InodeType::Dir { + if self.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let children = self.children.upread(); - let _ = children.find_dentry_with_checking_mountpoint(name)?; + children.check_mountpoint(name)?; + self.inode.unlink(name)?; let mut children = children.upgrade(); - children.delete_dentry(name); + children.delete(name); Ok(()) } /// Deletes a directory `Dentry_` by `rmdir()` the inner inode. pub fn rmdir(&self, name: &str) -> Result<()> { - if self.inode.type_() != InodeType::Dir { + if self.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let children = self.children.upread(); - let _ = children.find_dentry_with_checking_mountpoint(name)?; + children.check_mountpoint(name)?; + self.inode.rmdir(name)?; let mut children = children.upgrade(); - children.delete_dentry(name); + children.delete(name); Ok(()) } @@ -270,7 +256,7 @@ impl Dentry_ { if old_name == "." || old_name == ".." || new_name == "." || new_name == ".." { return_errno_with_message!(Errno::EISDIR, "old_name or new_name is a directory"); } - if self.inode.type_() != InodeType::Dir || new_dir.inode.type_() != InodeType::Dir { + if self.type_() != InodeType::Dir || new_dir.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } @@ -281,37 +267,38 @@ impl Dentry_ { } let children = self.children.upread(); - let old_dentry = children.find_dentry_with_checking_mountpoint(old_name)?; - let _ = children.find_dentry_with_checking_mountpoint(new_name)?; + let old_dentry = children.check_mountpoint_then_find(old_name)?; + children.check_mountpoint(new_name)?; + self.inode.rename(old_name, &self.inode, new_name)?; let mut children = children.upgrade(); match old_dentry.as_ref() { Some(dentry) => { - children.delete_dentry(old_name); + children.delete(old_name); dentry.set_name_and_parent(new_name, self.this()); - children.insert_dentry(dentry); + children.insert(new_name.to_string(), dentry.clone()); } None => { - children.delete_dentry(new_name); + children.delete(new_name); } } } else { // The two are different dentries let (mut self_children, mut new_dir_children) = write_lock_children_on_two_dentries(self, new_dir); - let old_dentry = self_children.find_dentry_with_checking_mountpoint(old_name)?; - let _ = new_dir_children.find_dentry_with_checking_mountpoint(new_name)?; + let old_dentry = self_children.check_mountpoint_then_find(old_name)?; + new_dir_children.check_mountpoint(new_name)?; self.inode.rename(old_name, &new_dir.inode, new_name)?; match old_dentry.as_ref() { Some(dentry) => { - self_children.delete_dentry(old_name); + self_children.delete(old_name); dentry.set_name_and_parent(new_name, new_dir.this()); - new_dir_children.insert_dentry(dentry); + new_dir_children.insert(new_name.to_string(), dentry.clone()); } None => { - new_dir_children.delete_dentry(new_name); + new_dir_children.delete(new_name); } } } @@ -387,41 +374,60 @@ enum DentryOptions { } struct Children { - inner: HashMap>, + dentries: HashMap>, } impl Children { pub fn new() -> Self { Self { - inner: HashMap::new(), + dentries: HashMap::new(), } } - pub fn insert_dentry(&mut self, dentry: &Arc) { + pub fn len(&self) -> usize { + self.dentries.len() + } + + pub fn contains(&self, name: &str) -> bool { + self.dentries.contains_key(name) + } + + pub fn find(&self, name: &str) -> Option> { + self.dentries.get(name).cloned() + } + + pub fn insert(&mut self, name: String, dentry: Arc) { // Do not cache it in the children if is not cacheable. // When we lookup it from the parent, it will always be newly created. - if !dentry.inode().is_dentry_cacheable() { + if !dentry.inode.is_dentry_cacheable() { return; } - let _ = self.inner.insert(dentry.name(), dentry.clone()); + let _ = self.dentries.insert(name, dentry); } - pub fn delete_dentry(&mut self, name: &str) -> Option> { - self.inner.remove(name) + pub fn delete(&mut self, name: &str) -> Option> { + self.dentries.remove(name) } - pub fn find_dentry(&self, name: &str) -> Option> { - self.inner.get(name).cloned() - } - - pub fn find_dentry_with_checking_mountpoint(&self, name: &str) -> Result>> { - let dentry = self.find_dentry(name); - if let Some(dentry) = dentry.as_ref() { + pub fn check_mountpoint(&self, name: &str) -> Result<()> { + if let Some(dentry) = self.dentries.get(name) { if dentry.is_mountpoint() { return_errno_with_message!(Errno::EBUSY, "dentry is mountpint"); } } + Ok(()) + } + + pub fn check_mountpoint_then_find(&self, name: &str) -> Result>> { + let dentry = if let Some(dentry) = self.dentries.get(name) { + if dentry.is_mountpoint() { + return_errno_with_message!(Errno::EBUSY, "dentry is mountpint"); + } + Some(dentry.clone()) + } else { + None + }; Ok(dentry) } } @@ -448,52 +454,50 @@ fn write_lock_children_on_two_dentries<'a>( impl Dentry { /// Creates a new `Dentry` to represent the root directory of a file system. - pub fn new_fs_root(mount_node: Arc) -> Arc { - Self::new(mount_node.clone(), mount_node.root_dentry().clone()) + pub fn new_fs_root(mount_node: Arc) -> Self { + let inner = mount_node.root_dentry().clone(); + Self::new(mount_node, inner) } /// Creates a new `Dentry` to represent the child directory of a file system. - pub fn new_fs_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { + pub fn new_fs_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result { let new_child_dentry = self.inner.create(name, type_, mode)?; - Ok(Self::new(self.mount_node.clone(), new_child_dentry.clone())) + Ok(Self::new(self.mount_node.clone(), new_child_dentry)) } - fn new(mount_node: Arc, inner: Arc) -> Arc { - Arc::new_cyclic(|weak_self| Self { - mount_node, - inner, - this: weak_self.clone(), - }) + fn new(mount_node: Arc, inner: Arc) -> Self { + Self { mount_node, inner } } /// Lookups the target `Dentry` given the `name`. - pub fn lookup(&self, name: &str) -> Result> { - if self.inner.inode().type_() != InodeType::Dir { + pub fn lookup(&self, name: &str) -> Result { + if self.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } - if !self.inner.inode().mode()?.is_executable() { + if !self.mode()?.is_executable() { return_errno!(Errno::EACCES); } if name.len() > NAME_MAX { return_errno!(Errno::ENAMETOOLONG); } - let dentry = match name { + let target_dentry = match name { "." => self.this(), ".." => self.effective_parent().unwrap_or_else(|| self.this()), name => { - let children_inner = self.inner.lookup_via_cache(name); - match children_inner { - Some(inner) => Self::new(self.mount_node().clone(), inner.clone()), + let target_inner_opt = self.inner.lookup_via_cache(name); + match target_inner_opt { + Some(target_inner) => Self::new(self.mount_node.clone(), target_inner), None => { - let fs_inner = self.inner.lookup_via_fs(name)?; - Self::new(self.mount_node().clone(), fs_inner.clone()) + let target_inner = self.inner.lookup_via_fs(name)?; + Self::new(self.mount_node.clone(), target_inner) } } } }; - let dentry = dentry.get_top_dentry(); - Ok(dentry) + + let target_dentry = target_dentry.get_top_dentry(); + Ok(target_dentry) } /// Gets the absolute path. @@ -535,8 +539,8 @@ impl Dentry { }; let parent_inner = Self::new( - self.mount_node.parent().unwrap().upgrade().unwrap().clone(), - self.mount_node.mountpoint_dentry().unwrap().clone(), + self.mount_node.parent().unwrap().upgrade().unwrap(), + self.mount_node.mountpoint_dentry().unwrap(), ); parent_inner.effective_name() } @@ -545,18 +549,18 @@ impl Dentry { /// /// If it is the root of a mount, it will go up to the mountpoint /// to get the parent of the mountpoint recursively. - fn effective_parent(&self) -> Option> { + fn effective_parent(&self) -> Option { if !self.inner.is_root_of_mount() { return Some(Self::new( self.mount_node.clone(), - self.inner.parent().unwrap().clone(), + self.inner.parent().unwrap(), )); } let parent = self.mount_node.parent()?; let mountpoint = self.mount_node.mountpoint_dentry()?; - let parent_dentry = Self::new(parent.upgrade().unwrap(), mountpoint.clone()); + let parent_dentry = Self::new(parent.upgrade().unwrap(), mountpoint); parent_dentry.effective_parent() } @@ -567,15 +571,17 @@ impl Dentry { /// For example, first `mount /dev/sda1 /mnt` and then `mount /dev/sda2 /mnt`. /// After the second mount is completed, the content of the first mount will be overridden. /// We need to recursively obtain the top `Dentry`. - fn get_top_dentry(&self) -> Arc { + fn get_top_dentry(self) -> Self { if !self.inner.is_mountpoint() { - return self.this(); + return self; } - match self.mount_node.get(self) { + + match self.mount_node.get(&self) { Some(child_mount) => { - Self::new(child_mount.clone(), child_mount.root_dentry().clone()).get_top_dentry() + let inner = child_mount.root_dentry().clone(); + Self::new(child_mount, inner).get_top_dentry() } - None => self.this(), + None => self, } } @@ -594,14 +600,14 @@ impl Dentry { /// /// Returns the mounted child mount. pub fn mount(&self, fs: Arc) -> Result> { - if self.inner.inode().type_() != InodeType::Dir { + if self.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } if self.effective_parent().is_none() { return_errno_with_message!(Errno::EINVAL, "can not mount on root"); } - let child_mount = self.mount_node().mount(fs, &self.this())?; + let child_mount = self.mount_node.mount(fs, &self.this())?; self.set_mountpoint(child_mount.clone()); Ok(child_mount) } @@ -614,12 +620,11 @@ impl Dentry { return_errno_with_message!(Errno::EINVAL, "not mounted"); } - let mount_node = self.mount_node.clone(); - let Some(mountpoint_dentry) = mount_node.mountpoint_dentry() else { + let Some(mountpoint_dentry) = self.mount_node.mountpoint_dentry() else { return_errno_with_message!(Errno::EINVAL, "cannot umount root mount"); }; - let mountpoint_mount_node = mount_node.parent().unwrap().upgrade().unwrap(); + let mountpoint_mount_node = self.mount_node.parent().unwrap().upgrade().unwrap(); let mountpoint = Self::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone()); let child_mount = mountpoint_mount_node.unmount(&mountpoint)?; @@ -628,13 +633,13 @@ impl Dentry { } /// Creates a `Dentry` by making an inode of the `type_` with the `mode`. - pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result> { + pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result { let inner = self.inner.mknod(name, mode, type_)?; - Ok(Self::new(self.mount_node.clone(), inner.clone())) + Ok(Self::new(self.mount_node.clone(), inner)) } /// Links a new name for the `Dentry`. - pub fn link(&self, old: &Arc, name: &str) -> Result<()> { + pub fn link(&self, old: &Self, name: &str) -> Result<()> { if !Arc::ptr_eq(&old.mount_node, &self.mount_node) { return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); } @@ -652,7 +657,7 @@ impl Dentry { } /// Renames a `Dentry` to the new `Dentry` by `rename()` the inner inode. - pub fn rename(&self, old_name: &str, new_dir: &Arc, new_name: &str) -> Result<()> { + pub fn rename(&self, old_name: &str, new_dir: &Self, new_name: &str) -> Result<()> { if !Arc::ptr_eq(&self.mount_node, &new_dir.mount_node) { return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); } @@ -664,7 +669,7 @@ impl Dentry { /// If `recursive` is true, it will bind mount the whole mount tree /// to the destination `Dentry`. Otherwise, it will only bind mount /// the root mount node. - pub fn bind_mount_to(&self, dst_dentry: &Arc, recursive: bool) -> Result<()> { + pub fn bind_mount_to(&self, dst_dentry: &Self, recursive: bool) -> Result<()> { let src_mount = self .mount_node .clone_mount_node_tree(&self.inner, recursive); @@ -672,8 +677,8 @@ impl Dentry { Ok(()) } - fn this(&self) -> Arc { - self.this.upgrade().unwrap() + fn this(&self) -> Self { + self.clone() } /// Gets the mount node of current `Dentry`. diff --git a/kernel/src/fs/path/mount.rs b/kernel/src/fs/path/mount.rs index d8f83d5e7..701e7e856 100644 --- a/kernel/src/fs/path/mount.rs +++ b/kernel/src/fs/path/mount.rs @@ -69,7 +69,7 @@ impl MountNode { /// mountpoint. It is the fs's responsibility to ensure the data consistency. /// /// Return the mounted child mount. - pub fn mount(&self, fs: Arc, mountpoint: &Arc) -> Result> { + pub fn mount(&self, fs: Arc, mountpoint: &Dentry) -> Result> { if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) { return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this"); } @@ -129,13 +129,13 @@ impl MountNode { ) -> Arc { let new_root_mount = self.clone_mount_node(root_dentry); if !recursive { - return new_root_mount.clone(); + return new_root_mount; } + let mut stack = vec![self.this()]; let mut new_stack = vec![new_root_mount.clone()]; - while let Some(old_mount) = stack.pop() { - let new_parent_mount = new_stack.pop().unwrap().clone(); + let new_parent_mount = new_stack.pop().unwrap(); let old_children = old_mount.children.read(); for old_child_mount in old_children.values() { let mountpoint_dentry = old_child_mount.mountpoint_dentry().unwrap(); @@ -153,10 +153,11 @@ impl MountNode { new_child_mount .set_mountpoint_dentry(&old_child_mount.mountpoint_dentry().unwrap()); stack.push(old_child_mount.clone()); - new_stack.push(new_child_mount.clone()); + new_stack.push(new_child_mount); } } - new_root_mount.clone() + + new_root_mount } /// Detaches the mount node from the parent mount node. @@ -171,7 +172,7 @@ impl MountNode { } /// Attaches the mount node to the mountpoint. - fn attach_mount_node(&self, mountpoint: &Arc) { + fn attach_mount_node(&self, mountpoint: &Dentry) { let key = mountpoint.key(); mountpoint .mount_node() @@ -183,7 +184,7 @@ impl MountNode { } /// Grafts the mount node tree to the mountpoint. - pub fn graft_mount_node_tree(&self, mountpoint: &Arc) -> Result<()> { + pub fn graft_mount_node_tree(&self, mountpoint: &Dentry) -> Result<()> { if mountpoint.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } diff --git a/kernel/src/net/socket/unix/addr.rs b/kernel/src/net/socket/unix/addr.rs index 4a173ca6d..d2de3020b 100644 --- a/kernel/src/net/socket/unix/addr.rs +++ b/kernel/src/net/socket/unix/addr.rs @@ -72,7 +72,7 @@ impl TryFrom for UnixSocketAddr { #[derive(Clone, Debug)] pub(super) enum UnixSocketAddrBound { - Path(Arc, Arc), + Path(Arc, Dentry), Abstract(Arc), } diff --git a/kernel/src/net/socket/unix/ns/path.rs b/kernel/src/net/socket/unix/ns/path.rs index f57c329a7..86098c9c3 100644 --- a/kernel/src/net/socket/unix/ns/path.rs +++ b/kernel/src/net/socket/unix/ns/path.rs @@ -9,7 +9,7 @@ use crate::{ prelude::*, }; -pub fn lookup_socket_file(path: &str) -> Result> { +pub fn lookup_socket_file(path: &str) -> Result { let dentry = { let current = current!(); let fs = current.fs().read(); @@ -31,7 +31,7 @@ pub fn lookup_socket_file(path: &str) -> Result> { Ok(dentry) } -pub fn create_socket_file(path: &str) -> Result> { +pub fn create_socket_file(path: &str) -> Result { let (parent_pathname, file_name) = split_path(path); let parent = { diff --git a/kernel/src/process/program_loader/elf/load_elf.rs b/kernel/src/process/program_loader/elf/load_elf.rs index 3488104e3..ce8d7c8fc 100644 --- a/kernel/src/process/program_loader/elf/load_elf.rs +++ b/kernel/src/process/program_loader/elf/load_elf.rs @@ -34,7 +34,7 @@ use crate::{ pub fn load_elf_to_vm( process_vm: &ProcessVm, file_header: &[u8], - elf_file: Arc, + elf_file: Dentry, fs_resolver: &FsResolver, argv: Vec, envp: Vec, @@ -85,7 +85,7 @@ fn lookup_and_parse_ldso( elf: &Elf, file_header: &[u8], fs_resolver: &FsResolver, -) -> Result, Elf)>> { +) -> Result> { let ldso_file = { let Some(ldso_path) = elf.ldso_path(file_header)? else { return Ok(None); @@ -112,7 +112,7 @@ fn load_ldso(root_vmar: &Vmar, ldso_file: &Dentry, ldso_elf: &Elf) -> Resu fn init_and_map_vmos( process_vm: &ProcessVm, - ldso: Option<(Arc, Elf)>, + ldso: Option<(Dentry, Elf)>, parsed_elf: &Elf, elf_file: &Dentry, ) -> Result<(Vaddr, AuxVec)> { diff --git a/kernel/src/process/program_loader/mod.rs b/kernel/src/process/program_loader/mod.rs index a3592d722..b1cebdefe 100644 --- a/kernel/src/process/program_loader/mod.rs +++ b/kernel/src/process/program_loader/mod.rs @@ -25,7 +25,7 @@ use crate::{ /// because the interpreter is usually an elf binary(e.g., /bin/bash) pub fn load_program_to_vm( process_vm: &ProcessVm, - elf_file: Arc, + elf_file: Dentry, argv: Vec, envp: Vec, fs_resolver: &FsResolver, @@ -68,7 +68,7 @@ pub fn load_program_to_vm( Ok((abs_path, elf_load_info)) } -pub fn check_executable_file(dentry: &Arc) -> Result<()> { +pub fn check_executable_file(dentry: &Dentry) -> Result<()> { if dentry.type_().is_directory() { return_errno_with_message!(Errno::EISDIR, "the file is a directory"); } diff --git a/kernel/src/syscall/execve.rs b/kernel/src/syscall/execve.rs index 19926e81d..12ae26fcf 100644 --- a/kernel/src/syscall/execve.rs +++ b/kernel/src/syscall/execve.rs @@ -58,7 +58,7 @@ fn lookup_executable_file( filename: String, flags: OpenFlags, ctx: &Context, -) -> Result> { +) -> Result { let fs_resolver = ctx.process.fs().read(); let dentry = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() { fs_resolver.lookup_from_fd(dfd) @@ -79,7 +79,7 @@ fn lookup_executable_file( } fn do_execve( - elf_file: Arc, + elf_file: Dentry, argv_ptr_ptr: Vaddr, envp_ptr_ptr: Vaddr, ctx: &Context, @@ -193,7 +193,7 @@ fn read_cstring_vec( fn set_uid_from_elf( current: &Process, credentials: &Credentials, - elf_file: &Arc, + elf_file: &Dentry, ) -> Result<()> { if elf_file.mode()?.has_set_uid() { let uid = elf_file.owner()?; @@ -211,7 +211,7 @@ fn set_uid_from_elf( fn set_gid_from_elf( current: &Process, credentials: &Credentials, - elf_file: &Arc, + elf_file: &Dentry, ) -> Result<()> { if elf_file.mode()?.has_set_gid() { let gid = elf_file.group()?; diff --git a/kernel/src/syscall/mount.rs b/kernel/src/syscall/mount.rs index 606203d24..e22a3635c 100644 --- a/kernel/src/syscall/mount.rs +++ b/kernel/src/syscall/mount.rs @@ -83,7 +83,7 @@ fn do_remount() -> Result<()> { /// Such as use user command `mount --rbind src dst`. fn do_bind_mount( src_name: CString, - dst_dentry: Arc, + dst_dentry: Dentry, recursive: bool, ctx: &Context, ) -> Result<()> { @@ -109,7 +109,7 @@ fn do_change_type() -> Result<()> { } /// Move a mount from src location to dst location. -fn do_move_mount_old(src_name: CString, dst_dentry: Arc, ctx: &Context) -> Result<()> { +fn do_move_mount_old(src_name: CString, dst_dentry: Dentry, ctx: &Context) -> Result<()> { let src_dentry = { let src_name = src_name.to_string_lossy(); if src_name.is_empty() { @@ -135,7 +135,7 @@ fn do_move_mount_old(src_name: CString, dst_dentry: Arc, ctx: &Context) fn do_new_mount( devname: CString, fs_type: Vaddr, - target_dentry: Arc, + target_dentry: Dentry, ctx: &Context, ) -> Result<()> { if target_dentry.type_() != InodeType::Dir { diff --git a/kernel/src/syscall/utimens.rs b/kernel/src/syscall/utimens.rs index 07b2789eb..dce7f5ee0 100644 --- a/kernel/src/syscall/utimens.rs +++ b/kernel/src/syscall/utimens.rs @@ -109,7 +109,7 @@ struct Utimbuf { modtime: i64, } -fn vfs_utimes(dentry: &Arc, times: Option) -> Result { +fn vfs_utimes(dentry: &Dentry, times: Option) -> Result { let (atime, mtime, ctime) = match times { Some(times) => { if !times.atime.is_valid() || !times.mtime.is_valid() {