diff --git a/kernel/aster-nix/src/device/pty/mod.rs b/kernel/aster-nix/src/device/pty/mod.rs index 22135e4a..74573a9e 100644 --- a/kernel/aster-nix/src/device/pty/mod.rs +++ b/kernel/aster-nix/src/device/pty/mod.rs @@ -22,22 +22,15 @@ pub fn init() -> Result<()> { let dev = fs.lookup(&FsPath::try_from("/dev")?)?; // Create the "pts" directory and mount devpts on it. - let devpts_dentry = - dev.dentry() - .create("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?; - let devpts_mount_node = - DentryMnt::new(dev.mount_node().clone(), devpts_dentry.clone()).mount(DevPts::new())?; - let devpts = DentryMnt::new( - devpts_mount_node.clone(), - devpts_mount_node.root_dentry().clone(), - ); - - devpts.mount(DevPts::new())?; + let devpts_dentrymnt = + dev.new_fs_child("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?; + let devpts_mount_node = devpts_dentrymnt.mount(DevPts::new())?; + let devpts = DentryMnt::new_fs_root(devpts_mount_node.clone()); DEV_PTS.call_once(|| devpts); // Create the "ptmx" symlink. - let ptmx = dev.dentry().create( + let ptmx = dev.new_fs_child( "ptmx", InodeType::SymLink, InodeMode::from_bits_truncate(0o777), diff --git a/kernel/aster-nix/src/fs/device.rs b/kernel/aster-nix/src/fs/device.rs index de3d7924..f6b8b3e4 100644 --- a/kernel/aster-nix/src/fs/device.rs +++ b/kernel/aster-nix/src/fs/device.rs @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MPL-2.0 -use super::inode_handle::FileIo; +use super::{inode_handle::FileIo, utils::DentryMnt}; use crate::{ fs::{ fs_resolver::{FsPath, FsResolver}, - utils::{Dentry, InodeMode, InodeType}, + utils::{InodeMode, InodeType}, }, prelude::*, }; @@ -84,15 +84,14 @@ impl From for u64 { /// /// 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, pathname: &str) -> Result> { +pub fn add_node(device: Arc, path: &str) -> Result> { let mut dentrymnt = { let fs_resolver = FsResolver::new(); fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())? }; - let mut dentry = dentrymnt.dentry().clone(); let mut relative_path = { - let relative_path = pathname.trim_start_matches('/'); + let relative_path = path.trim_start_matches('/'); if relative_path.is_empty() { return_errno_with_message!(Errno::EINVAL, "invalid device path"); } @@ -117,14 +116,14 @@ pub fn add_node(device: Arc, pathname: &str) -> Result> Err(_) => { if path_remain.is_empty() { // Create the device node - dentry = dentrymnt.dentry().mknod( + dentrymnt = dentrymnt.mknod( next_name, InodeMode::from_bits_truncate(0o666), device.clone(), )?; } else { // Mkdir parent path - dentry = dentrymnt.dentry().create( + dentrymnt = dentrymnt.new_fs_child( next_name, InodeType::Dir, InodeMode::from_bits_truncate(0o755), @@ -135,15 +134,15 @@ pub fn add_node(device: Arc, pathname: &str) -> Result> relative_path = path_remain; } - Ok(dentry) + Ok(dentrymnt) } /// Delete the device node from FS for the device. /// /// This function is used in unregistering device. -pub fn delete_node(pathname: &str) -> Result<()> { +pub fn delete_node(path: &str) -> Result<()> { let abs_path = { - let device_path = pathname.trim_start_matches('/'); + let device_path = path.trim_start_matches('/'); if device_path.is_empty() { return_errno_with_message!(Errno::EINVAL, "invalid device path"); } @@ -155,6 +154,6 @@ pub fn delete_node(pathname: &str) -> Result<()> { fs_resolver.lookup_dir_and_base_name(&FsPath::try_from(abs_path.as_str()).unwrap())? }; - parent_dentrymnt.dentry().unlink(&name)?; + parent_dentrymnt.unlink(&name)?; Ok(()) } diff --git a/kernel/aster-nix/src/fs/fs_resolver.rs b/kernel/aster-nix/src/fs/fs_resolver.rs index af46b02a..89a94cc8 100644 --- a/kernel/aster-nix/src/fs/fs_resolver.rs +++ b/kernel/aster-nix/src/fs/fs_resolver.rs @@ -37,8 +37,8 @@ impl Default for FsResolver { impl FsResolver { pub fn new() -> Self { Self { - root: DentryMnt::new(root_mount().clone(), root_mount().root_dentry().clone()), - cwd: DentryMnt::new(root_mount().clone(), root_mount().root_dentry().clone()), + root: DentryMnt::new_fs_root(root_mount().clone()), + cwd: DentryMnt::new_fs_root(root_mount().clone()), } } @@ -63,7 +63,7 @@ impl FsResolver { } /// Open or create a file inode handler. - pub fn open(&self, pathname: &FsPath, flags: u32, mode: u16) -> Result { + pub fn open(&self, path: &FsPath, flags: u32, mode: u16) -> Result { let creation_flags = CreationFlags::from_bits_truncate(flags); let status_flags = StatusFlags::from_bits_truncate(flags); let access_mode = AccessMode::from_u32(flags)?; @@ -72,9 +72,9 @@ impl FsResolver { let follow_tail_link = !(creation_flags.contains(CreationFlags::O_NOFOLLOW) || creation_flags.contains(CreationFlags::O_CREAT) && creation_flags.contains(CreationFlags::O_EXCL)); - let dentrymnt = match self.lookup_inner(pathname, follow_tail_link) { + let dentrymnt = match self.lookup_inner(path, follow_tail_link) { Ok(dentrymnt) => { - let inode = dentrymnt.dentry().inode(); + let inode = dentrymnt.inode(); if inode.type_() == InodeType::SymLink && creation_flags.contains(CreationFlags::O_NOFOLLOW) && !status_flags.contains(StatusFlags::O_PATH) @@ -104,18 +104,14 @@ impl FsResolver { return_errno_with_message!(Errno::ENOTDIR, "cannot create directory"); } let (dir_dentrymnt, file_name) = - self.lookup_dir_and_base_name_inner(pathname, follow_tail_link)?; + self.lookup_dir_and_base_name_inner(path, follow_tail_link)?; if file_name.ends_with('/') { return_errno_with_message!(Errno::EISDIR, "path refers to a directory"); } - if !dir_dentrymnt.dentry().mode()?.is_writable() { + if !dir_dentrymnt.mode()?.is_writable() { return_errno_with_message!(Errno::EACCES, "file cannot be created"); } - let dir_dentry = - dir_dentrymnt - .dentry() - .create(&file_name, InodeType::File, inode_mode)?; - DentryMnt::new(dir_dentrymnt.mount_node().clone(), dir_dentry.clone()) + dir_dentrymnt.new_fs_child(&file_name, InodeType::File, inode_mode)? } Err(e) => return Err(e), }; @@ -125,29 +121,27 @@ impl FsResolver { } /// Lookup dentrymnt according to FsPath, always follow symlinks - pub fn lookup(&self, pathname: &FsPath) -> Result> { - self.lookup_inner(pathname, true) + pub fn lookup(&self, path: &FsPath) -> Result> { + self.lookup_inner(path, true) } /// Lookup dentrymnt according to FsPath, do not follow it if last component is a symlink - pub fn lookup_no_follow(&self, pathname: &FsPath) -> Result> { - self.lookup_inner(pathname, false) + pub fn lookup_no_follow(&self, path: &FsPath) -> Result> { + self.lookup_inner(path, false) } - fn lookup_inner(&self, pathname: &FsPath, follow_tail_link: bool) -> Result> { - let dentrymnt = match pathname.inner { - FsPathInner::Absolute(pathname) => self.lookup_from_parent( - &self.root, - pathname.trim_start_matches('/'), - follow_tail_link, - )?, - FsPathInner::CwdRelative(pathname) => { - self.lookup_from_parent(&self.cwd, pathname, follow_tail_link)? + fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result> { + let dentrymnt = match path.inner { + FsPathInner::Absolute(path) => { + self.lookup_from_parent(&self.root, path.trim_start_matches('/'), follow_tail_link)? + } + FsPathInner::CwdRelative(path) => { + self.lookup_from_parent(&self.cwd, path, follow_tail_link)? } FsPathInner::Cwd => self.cwd.clone(), - FsPathInner::FdRelative(fd, pathname) => { + FsPathInner::FdRelative(fd, path) => { let parent = self.lookup_from_fd(fd)?; - self.lookup_from_parent(&parent, pathname, follow_tail_link)? + self.lookup_from_parent(&parent, path, follow_tail_link)? } FsPathInner::Fd(fd) => self.lookup_from_fd(fd)?, }; @@ -196,8 +190,7 @@ impl FsResolver { // Iterate next dentry let next_dentrymnt = dentrymnt.lookup(next_name)?; - let next_dentry = next_dentrymnt.dentry(); - let next_type = next_dentry.type_(); + let next_type = next_dentrymnt.type_(); let next_is_tail = path_remain.is_empty(); // If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times. @@ -206,7 +199,7 @@ impl FsResolver { return_errno_with_message!(Errno::ELOOP, "too many symlinks"); } let link_path_remain = { - let mut tmp_link_path = next_dentry.inode().read_link()?; + let mut tmp_link_path = next_dentrymnt.inode().read_link()?; if tmp_link_path.is_empty() { return_errno_with_message!(Errno::ENOENT, "empty symlink"); } @@ -241,7 +234,7 @@ impl FsResolver { } /// Lookup dentry from the giving 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 @@ -251,35 +244,35 @@ impl FsResolver { Ok(inode_handle.dentrymnt().clone()) } - /// Lookup the dir dentrymnt and base file name of the giving pathname. + /// Lookup the dir dentrymnt and base file name of the giving path. /// /// If the last component is a symlink, do not deference it - pub fn lookup_dir_and_base_name(&self, pathname: &FsPath) -> Result<(Arc, String)> { - self.lookup_dir_and_base_name_inner(pathname, false) + pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc, String)> { + self.lookup_dir_and_base_name_inner(path, false) } fn lookup_dir_and_base_name_inner( &self, - pathname: &FsPath, + path: &FsPath, follow_tail_link: bool, ) -> Result<(Arc, String)> { - let (mut dir_dentrymnt, mut base_name) = match pathname.inner { - FsPathInner::Absolute(pathname) => { - let (dir, file_name) = split_path(pathname); + let (mut dir_dentrymnt, mut base_name) = match path.inner { + FsPathInner::Absolute(path) => { + let (dir, file_name) = split_path(path); ( self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?, String::from(file_name), ) } - FsPathInner::CwdRelative(pathname) => { - let (dir, file_name) = split_path(pathname); + FsPathInner::CwdRelative(path) => { + let (dir, file_name) = split_path(path); ( self.lookup_from_parent(&self.cwd, dir, true)?, String::from(file_name), ) } - FsPathInner::FdRelative(fd, pathname) => { - let (dir, file_name) = split_path(pathname); + FsPathInner::FdRelative(fd, path) => { + let (dir, file_name) = split_path(path); let parent = self.lookup_from_fd(fd)?; ( self.lookup_from_parent(&parent, dir, true)?, @@ -295,9 +288,9 @@ impl FsResolver { // Dereference the tail symlinks if needed loop { match dir_dentrymnt.lookup(base_name.trim_end_matches('/')) { - Ok(dentrymnt) if dentrymnt.dentry().type_() == InodeType::SymLink => { + Ok(dentrymnt) if dentrymnt.type_() == InodeType::SymLink => { let link = { - let mut link = dentrymnt.dentry().inode().read_link()?; + let mut link = dentrymnt.inode().read_link()?; if link.is_empty() { return_errno_with_message!(Errno::ENOENT, "invalid symlink"); } diff --git a/kernel/aster-nix/src/fs/inode_handle/dyn_cap.rs b/kernel/aster-nix/src/fs/inode_handle/dyn_cap.rs index 15c4cc01..60d5af94 100644 --- a/kernel/aster-nix/src/fs/inode_handle/dyn_cap.rs +++ b/kernel/aster-nix/src/fs/inode_handle/dyn_cap.rs @@ -12,7 +12,7 @@ impl InodeHandle { access_mode: AccessMode, status_flags: StatusFlags, ) -> Result { - let inode = dentrymnt.dentry().inode(); + let inode = dentrymnt.inode(); if access_mode.is_readable() && !inode.mode()?.is_readable() { return_errno_with_message!(Errno::EACCES, "File is not readable"); } @@ -116,6 +116,6 @@ impl FileLike for InodeHandle { } fn as_device(&self) -> Option> { - self.0.dentrymnt.dentry().inode().as_device() + self.0.dentrymnt.inode().as_device() } } diff --git a/kernel/aster-nix/src/fs/inode_handle/mod.rs b/kernel/aster-nix/src/fs/inode_handle/mod.rs index 6ce50561..9a893cfb 100644 --- a/kernel/aster-nix/src/fs/inode_handle/mod.rs +++ b/kernel/aster-nix/src/fs/inode_handle/mod.rs @@ -47,12 +47,9 @@ impl InodeHandle_ { } let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentrymnt - .dentry() - .inode() - .read_direct_at(*offset, buf)? + self.dentrymnt.inode().read_direct_at(*offset, buf)? } else { - self.dentrymnt.dentry().inode().read_at(*offset, buf)? + self.dentrymnt.inode().read_at(*offset, buf)? }; *offset += len; @@ -67,15 +64,12 @@ impl InodeHandle_ { } if self.status_flags().contains(StatusFlags::O_APPEND) { - *offset = self.dentrymnt.dentry().size(); + *offset = self.dentrymnt.size(); } let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentrymnt - .dentry() - .inode() - .write_direct_at(*offset, buf)? + self.dentrymnt.inode().write_direct_at(*offset, buf)? } else { - self.dentrymnt.dentry().inode().write_at(*offset, buf)? + self.dentrymnt.inode().write_at(*offset, buf)? }; *offset += len; @@ -88,9 +82,9 @@ impl InodeHandle_ { } let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentrymnt.dentry().inode().read_direct_all(buf)? + self.dentrymnt.inode().read_direct_all(buf)? } else { - self.dentrymnt.dentry().inode().read_all(buf)? + self.dentrymnt.inode().read_all(buf)? }; Ok(len) } @@ -105,7 +99,7 @@ impl InodeHandle_ { off as isize } SeekFrom::End(off /* as isize */) => { - let file_size = self.dentrymnt.dentry().size() as isize; + let file_size = self.dentrymnt.size() as isize; assert!(file_size >= 0); file_size .checked_add(off) @@ -133,7 +127,7 @@ impl InodeHandle_ { if self.status_flags().contains(StatusFlags::O_APPEND) { return_errno_with_message!(Errno::EPERM, "can not resize append-only file"); } - self.dentrymnt.dentry().resize(new_size) + self.dentrymnt.resize(new_size) } pub fn access_mode(&self) -> AccessMode { @@ -152,11 +146,7 @@ impl InodeHandle_ { pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result { let mut offset = self.offset.lock(); - let read_cnt = self - .dentrymnt - .dentry() - .inode() - .readdir_at(*offset, visitor)?; + let read_cnt = self.dentrymnt.inode().readdir_at(*offset, visitor)?; *offset += read_cnt; Ok(read_cnt) } @@ -166,7 +156,7 @@ impl InodeHandle_ { return file_io.poll(mask, poller); } - self.dentrymnt.dentry().inode().poll(mask, poller) + self.dentrymnt.inode().poll(mask, poller) } fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { @@ -174,11 +164,11 @@ impl InodeHandle_ { return file_io.ioctl(cmd, arg); } - self.dentrymnt.dentry().inode().ioctl(cmd, arg) + self.dentrymnt.inode().ioctl(cmd, arg) } } -#[inherit_methods(from = "self.dentrymnt.dentry()")] +#[inherit_methods(from = "self.dentrymnt")] impl InodeHandle_ { pub fn size(&self) -> usize; pub fn metadata(&self) -> Metadata; diff --git a/kernel/aster-nix/src/fs/procfs/pid/fd.rs b/kernel/aster-nix/src/fs/procfs/pid/fd.rs index c3bbcc81..579c80a0 100644 --- a/kernel/aster-nix/src/fs/procfs/pid/fd.rs +++ b/kernel/aster-nix/src/fs/procfs/pid/fd.rs @@ -76,12 +76,12 @@ impl FileSymOps { impl SymOps for FileSymOps { fn read_link(&self) -> Result { - let pathname = if let Some(inode_handle) = self.0.downcast_ref::() { + let path = if let Some(inode_handle) = self.0.downcast_ref::() { inode_handle.dentrymnt().abs_path() } else { // TODO: get the real path for other FileLike object String::from("/dev/tty") }; - Ok(pathname) + Ok(path) } } diff --git a/kernel/aster-nix/src/fs/rootfs.rs b/kernel/aster-nix/src/fs/rootfs.rs index 27d67677..358b48f0 100644 --- a/kernel/aster-nix/src/fs/rootfs.rs +++ b/kernel/aster-nix/src/fs/rootfs.rs @@ -54,20 +54,20 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> { let mode = InodeMode::from_bits_truncate(metadata.permission_mode()); match metadata.file_type() { FileType::File => { - let dentry = parent.dentry().create(name, InodeType::File, mode)?; - entry.read_all(dentry.inode().writer(0))?; + let dentrymnt = parent.new_fs_child(name, InodeType::File, mode)?; + entry.read_all(dentrymnt.inode().writer(0))?; } FileType::Dir => { - let _ = parent.dentry().create(name, InodeType::Dir, mode)?; + let _ = parent.new_fs_child(name, InodeType::Dir, mode)?; } FileType::Link => { - let dentry = parent.dentry().create(name, InodeType::SymLink, mode)?; + let dentrymnt = parent.new_fs_child(name, InodeType::SymLink, mode)?; let link_content = { let mut link_data: Vec = Vec::new(); entry.read_all(&mut link_data)?; core::str::from_utf8(&link_data)?.to_string() }; - dentry.inode().write_link(&link_content)?; + dentrymnt.inode().write_link(&link_content)?; } type_ => { panic!("unsupported file type = {:?} in initramfs", type_); diff --git a/kernel/aster-nix/src/fs/utils/dentry.rs b/kernel/aster-nix/src/fs/utils/dentry.rs index 211b9ca6..53907163 100644 --- a/kernel/aster-nix/src/fs/utils/dentry.rs +++ b/kernel/aster-nix/src/fs/utils/dentry.rs @@ -9,7 +9,10 @@ use inherit_methods_macro::inherit_methods; use super::{FileSystem, Inode, InodeMode, InodeType, Metadata}; use crate::{ - fs::device::Device, + fs::{ + device::Device, + utils::{MountNode, NAME_MAX}, + }, prelude::*, process::{Gid, Uid}, }; @@ -28,24 +31,16 @@ pub struct Dentry { } impl Dentry { - /// Create a new root dentry with the giving inode and mount node. + /// Create a new root dentry with the giving inode. /// /// It is been created during the construction of MountNode struct. The MountNode - /// struct holds an arc reference to this root dentry, while this dentry holds a - /// weak reference to the MountNode struct. + /// struct holds an arc reference to this root dentry. pub(super) fn new_root(inode: Arc) -> Arc { let root = Self::new(inode, DentryOptions::Root); DCACHE.lock().insert(root.key(), root.clone()); root } - pub fn new_child(&self, inode: Arc, name: &str) -> Arc { - Dentry::new( - inode, - DentryOptions::Leaf((String::from(name), self.this())), - ) - } - /// Internal constructor. fn new(inode: Arc, options: DentryOptions) -> Arc { Arc::new_cyclic(|weak_self| Self { @@ -63,7 +58,7 @@ impl Dentry { /// Get the name of dentry. /// /// Returns "/" if it is a root dentry. - pub fn name(&self) -> String { + fn name(&self) -> String { match self.name_and_parent.read().as_ref() { Some(name_and_parent) => name_and_parent.0.clone(), None => String::from("/"), @@ -73,7 +68,7 @@ impl Dentry { /// Get the parent. /// /// Returns None if it is root dentry. - pub fn parent(&self) -> Option> { + fn parent(&self) -> Option> { self.name_and_parent .read() .as_ref() @@ -91,7 +86,7 @@ impl Dentry { } /// Get the DentryKey. - pub fn key(&self) -> DentryKey { + fn key(&self) -> DentryKey { DentryKey::new(self) } @@ -106,27 +101,27 @@ impl Dentry { DentryFlags::from_bits(flags).unwrap() } - pub fn is_mountpoint(&self) -> bool { + fn is_mountpoint(&self) -> bool { self.flags().contains(DentryFlags::MOUNTED) } - pub fn set_mountpoint(&self) { + fn set_mountpoint(&self) { self.flags .fetch_or(DentryFlags::MOUNTED.bits(), Ordering::Release); } - pub fn clear_mountpoint(&self) { + fn clear_mountpoint(&self) { self.flags .fetch_and(!(DentryFlags::MOUNTED.bits()), Ordering::Release); } /// Currently, the root dentry of a fs is the root of a mount. - pub fn is_root_of_mount(&self) -> bool { + fn is_root_of_mount(&self) -> bool { self.name_and_parent.read().as_ref().is_none() } /// Create a dentry by making inode. - pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { + fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } @@ -148,13 +143,13 @@ impl Dentry { } /// Lookup a dentry from DCACHE. - pub fn lookup_fast(&self, name: &str) -> Option> { + fn lookup_via_cache(&self, name: &str) -> Option> { let mut children = self.children.lock(); children.find_dentry(name) } /// Lookup a dentry from filesystem. - pub fn lookup_slow(&self, name: &str) -> Result> { + fn lookuop_via_fs(&self, name: &str) -> Result> { let mut children = self.children.lock(); let inode = self.inode.lookup(name)?; let dentry = Self::new( @@ -165,13 +160,13 @@ impl Dentry { Ok(dentry) } - pub fn insert_dentry(&self, child_dentry: &Arc) { + fn insert_dentry(&self, child_dentry: &Arc) { let mut children = self.children.lock(); children.insert_dentry(child_dentry); } /// Create a dentry by making a device inode. - pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc) -> Result> { + fn mknod(&self, name: &str, mode: InodeMode, device: Arc) -> Result> { if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } @@ -192,8 +187,27 @@ impl Dentry { Ok(child) } + /// Link a new name for the dentry by linking inode. + fn link(&self, old: &Arc, name: &str) -> Result<()> { + if self.inode.type_() != InodeType::Dir { + return_errno!(Errno::ENOTDIR); + } + let mut children = self.children.lock(); + if children.find_dentry(name).is_some() { + return_errno!(Errno::EEXIST); + } + let old_inode = old.inode(); + self.inode.link(old_inode, name)?; + let dentry = Self::new( + old_inode.clone(), + DentryOptions::Leaf((String::from(name), self.this())), + ); + children.insert_dentry(&dentry); + Ok(()) + } + /// Delete a dentry by unlinking inode. - pub fn unlink(&self, name: &str) -> Result<()> { + fn unlink(&self, name: &str) -> Result<()> { if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } @@ -205,7 +219,7 @@ impl Dentry { } /// Delete a directory dentry by rmdiring inode. - pub fn rmdir(&self, name: &str) -> Result<()> { + fn rmdir(&self, name: &str) -> Result<()> { if self.inode.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } @@ -217,7 +231,7 @@ impl Dentry { } /// Rename a dentry to the new dentry by renaming inode. - pub fn rename(&self, old_name: &str, new_dir: &Arc, new_name: &str) -> Result<()> { + fn rename(&self, old_name: &str, new_dir: &Arc, new_name: &str) -> Result<()> { if old_name == "." || old_name == ".." || new_name == "." || new_name == ".." { return_errno_with_message!(Errno::EISDIR, "old_name or new_name is a directory"); } @@ -268,22 +282,22 @@ impl Dentry { #[inherit_methods(from = "self.inode")] impl Dentry { - pub fn fs(&self) -> Arc; - pub fn sync(&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; - pub fn resize(&self, size: usize) -> Result<()>; - pub fn owner(&self) -> Result; - pub fn set_owner(&self, uid: Uid) -> Result<()>; - pub fn group(&self) -> Result; - pub fn set_group(&self, gid: Gid) -> Result<()>; - pub fn atime(&self) -> Duration; - pub fn set_atime(&self, time: Duration); - pub fn mtime(&self) -> Duration; - pub fn set_mtime(&self, time: Duration); + fn fs(&self) -> Arc; + fn sync(&self) -> Result<()>; + fn metadata(&self) -> Metadata; + fn type_(&self) -> InodeType; + fn mode(&self) -> Result; + fn set_mode(&self, mode: InodeMode) -> Result<()>; + fn size(&self) -> usize; + fn resize(&self, size: usize) -> Result<()>; + fn owner(&self) -> Result; + fn set_owner(&self, uid: Uid) -> Result<()>; + fn group(&self) -> Result; + fn set_group(&self, gid: Gid) -> Result<()>; + fn atime(&self) -> Duration; + fn set_atime(&self, time: Duration); + fn mtime(&self) -> Duration; + fn set_mtime(&self, time: Duration); } impl Debug for Dentry { @@ -307,7 +321,7 @@ pub struct DentryKey { impl DentryKey { /// Form the DentryKey for the dentry. - pub fn new(dentry: &Dentry) -> Self { + fn new(dentry: &Dentry) -> Self { let (name, parent) = match dentry.name_and_parent.read().as_ref() { Some(name_and_parent) => name_and_parent.clone(), None => (String::from("/"), dentry.this()), @@ -335,13 +349,13 @@ struct Children { } impl Children { - pub fn new() -> Self { + fn new() -> Self { Self { inner: BTreeMap::new(), } } - pub fn insert_dentry(&mut self, dentry: &Arc) { + fn insert_dentry(&mut self, dentry: &Arc) { // Do not cache it in DCACHE and children if is not cacheable. // When we look up it from the parent, it will always be newly created. if !dentry.inode().is_dentry_cacheable() { @@ -352,14 +366,14 @@ impl Children { self.inner.insert(dentry.name(), Arc::downgrade(dentry)); } - pub fn delete_dentry(&mut self, name: &str) -> Option> { + fn delete_dentry(&mut self, name: &str) -> Option> { self.inner .remove(name) .and_then(|d| d.upgrade()) .and_then(|d| DCACHE.lock().remove(&d.key())) } - pub fn find_dentry(&mut self, name: &str) -> Option> { + fn find_dentry(&mut self, name: &str) -> Option> { if let Some(dentry) = self.inner.get(name) { dentry.upgrade().or_else(|| { self.inner.remove(name); @@ -370,10 +384,7 @@ impl Children { } } - pub fn find_dentry_with_checking_mountpoint( - &mut self, - name: &str, - ) -> Result>> { + fn find_dentry_with_checking_mountpoint(&mut self, name: &str) -> Result>> { let dentry = self.find_dentry(name); if let Some(dentry) = dentry.as_ref() { if dentry.is_mountpoint() { @@ -400,3 +411,256 @@ fn write_lock_children_on_two_dentries<'a>( (this, other) } } + +/// The DentryMnt can represent a location in the mount tree. +#[derive(Debug)] +pub struct DentryMnt { + mount_node: Arc, + dentry: Arc, + this: Weak, +} + +impl DentryMnt { + /// Create a new DentryMnt 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()) + } + + /// Crete a new DentryMnt to represent the child directory of a file system. + pub fn new_fs_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { + let new_child_dentry = self.dentry.create(name, type_, mode)?; + Ok(Self::new(self.mount_node.clone(), new_child_dentry.clone())) + } + + /// Internal constructor. + fn new(mount_node: Arc, dentry: Arc) -> Arc { + Arc::new_cyclic(|weak_self| Self { + mount_node, + dentry, + this: weak_self.clone(), + }) + } + + /// Lookup a dentrymnt. + pub fn lookup(&self, name: &str) -> Result> { + if self.dentry.inode().type_() != InodeType::Dir { + return_errno!(Errno::ENOTDIR); + } + if !self.dentry.inode().mode()?.is_executable() { + return_errno!(Errno::EACCES); + } + if name.len() > NAME_MAX { + return_errno!(Errno::ENAMETOOLONG); + } + + let dentrymnt = match name { + "." => self.this(), + ".." => self.effective_parent().unwrap_or_else(|| self.this()), + name => { + let children_dentry = self.dentry.lookup_via_cache(name); + match children_dentry { + Some(dentry) => Self::new(self.mount_node().clone(), dentry.clone()), + None => { + let slow_dentry = self.dentry.lookuop_via_fs(name)?; + Self::new(self.mount_node().clone(), slow_dentry.clone()) + } + } + } + }; + let dentrymnt = dentrymnt.get_top_dentrymnt(); + Ok(dentrymnt) + } + + /// Get the absolute path. + /// + /// It will resolve the mountpoint automatically. + pub fn abs_path(&self) -> String { + let mut path = self.effective_name(); + let mut dir_dentrymnt = self.this(); + + while let Some(parent_dir_dentrymnt) = dir_dentrymnt.effective_parent() { + path = { + let parent_name = parent_dir_dentrymnt.effective_name(); + if parent_name != "/" { + parent_name + "/" + &path + } else { + parent_name + &path + } + }; + dir_dentrymnt = parent_dir_dentrymnt; + } + debug_assert!(path.starts_with('/')); + path + } + + /// Get the effective name of dentrymnt. + /// + /// If it is the root of mount, it will go up to the mountpoint to get the name + /// of the mountpoint recursively. + fn effective_name(&self) -> String { + if !self.dentry.is_root_of_mount() { + return self.dentry.name(); + } + + let Some(parent) = self.mount_node.parent() else { + return self.dentry.name(); + }; + let Some(mountpoint) = self.mount_node.mountpoint_dentry() else { + return self.dentry.name(); + }; + + let parent_dentrymnt = Self::new( + self.mount_node.parent().unwrap().upgrade().unwrap().clone(), + self.mount_node.mountpoint_dentry().unwrap().clone(), + ); + parent_dentrymnt.effective_name() + } + + /// Get the effective parent of dentrymnt. + /// + /// If it is the root of mount, it will go up to the mountpoint to get the parent + /// of the mountpoint recursively. + fn effective_parent(&self) -> Option> { + if !self.dentry.is_root_of_mount() { + return Some(Self::new( + self.mount_node.clone(), + self.dentry.parent().unwrap().clone(), + )); + } + + let parent = self.mount_node.parent()?; + let mountpoint = self.mount_node.mountpoint_dentry()?; + + let parent_dentrymnt = Self::new(parent.upgrade().unwrap(), mountpoint.clone()); + parent_dentrymnt.effective_parent() + } + + /// Get the top DentryMnt of self. + /// + /// When different file systems are mounted on the same mount point. + /// 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 DentryMnt. + fn get_top_dentrymnt(&self) -> Arc { + if !self.dentry.is_mountpoint() { + return self.this(); + } + match self.mount_node.get(self) { + Some(child_mount) => Self::new(child_mount.clone(), child_mount.root_dentry().clone()) + .get_top_dentrymnt(), + None => self.this(), + } + } + + /// Make this DentryMnt's dentry to be a mountpoint, + /// and set the mountpoint of the child mount to this DentryMnt's dentry. + fn set_mountpoint(&self, child_mount: Arc) { + child_mount.set_mountpoint_dentry(self.dentry.clone()); + self.dentry.set_mountpoint(); + } + + /// Mount the fs on this DentryMnt. It will make this DentryMnt's dentry to be a mountpoint. + /// + /// If the given mountpoint has already been mounted, then its mounted child mount + /// will be updated. + /// The root dentry cannot be mounted. + /// + /// Return the mounted child mount. + pub fn mount(&self, fs: Arc) -> Result> { + if self.dentry.inode().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())?; + self.set_mountpoint(child_mount.clone()); + Ok(child_mount) + } + + /// Unmount and return the mounted child mount. + /// + /// Note that the root mount cannot be unmounted. + pub fn umount(&self) -> Result> { + if !self.dentry.is_root_of_mount() { + return_errno_with_message!(Errno::EINVAL, "not mounted"); + } + + let mount_node = self.mount_node.clone(); + let Some(mountpoint_dentry) = 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_dentrymnt = + Self::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone()); + + let child_mount = mountpoint_mount_node.umount(&mountpoint_dentrymnt)?; + mountpoint_dentry.clear_mountpoint(); + Ok(child_mount) + } + + /// Create a DentryMnt by making a device inode. + pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc) -> Result> { + let dentry = self.dentry.mknod(name, mode, device)?; + Ok(Self::new(self.mount_node.clone(), dentry.clone())) + } + + /// Link a new name for the DentryMnt by linking inode. + pub fn link(&self, old: &Arc, name: &str) -> Result<()> { + if !Arc::ptr_eq(&old.mount_node, &self.mount_node) { + return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); + } + self.dentry.link(&old.dentry, name) + } + + /// Delete a DentryMnt by unlinking inode. + pub fn unlink(&self, name: &str) -> Result<()> { + self.dentry.unlink(name) + } + + /// Delete a directory dentry by rmdiring inode. + pub fn rmdir(&self, name: &str) -> Result<()> { + self.dentry.rmdir(name) + } + + /// Rename a dentry to the new dentry by renaming inode. + pub fn rename(&self, old_name: &str, new_dir: &Arc, new_name: &str) -> Result<()> { + if !Arc::ptr_eq(&self.mount_node, &new_dir.mount_node) { + return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); + } + self.dentry.rename(old_name, &new_dir.dentry, new_name) + } + + /// Get the arc reference to self. + fn this(&self) -> Arc { + self.this.upgrade().unwrap() + } + + /// Get the mount node of this dentrymnt. + pub fn mount_node(&self) -> &Arc { + &self.mount_node + } +} + +#[inherit_methods(from = "self.dentry")] +impl DentryMnt { + pub fn fs(&self) -> Arc; + pub fn sync(&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; + pub fn resize(&self, size: usize) -> Result<()>; + pub fn owner(&self) -> Result; + pub fn set_owner(&self, uid: Uid) -> Result<()>; + pub fn group(&self) -> Result; + pub fn set_group(&self, gid: Gid) -> Result<()>; + pub fn atime(&self) -> Duration; + pub fn set_atime(&self, time: Duration); + pub fn mtime(&self) -> Duration; + pub fn set_mtime(&self, time: Duration); + pub fn key(&self) -> DentryKey; + pub fn inode(&self) -> &Arc; +} diff --git a/kernel/aster-nix/src/fs/utils/dentrymnt.rs b/kernel/aster-nix/src/fs/utils/dentrymnt.rs deleted file mode 100644 index 9d9efc66..00000000 --- a/kernel/aster-nix/src/fs/utils/dentrymnt.rs +++ /dev/null @@ -1,210 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use super::{Dentry, FileSystem, InodeType, MountNode, NAME_MAX}; -use crate::prelude::*; - -/// The DentryMnt can represent a location in the mount tree. -#[derive(Debug)] -pub struct DentryMnt { - mount_node: Arc, - dentry: Arc, - this: Weak, -} - -impl DentryMnt { - pub fn new(mount_node: Arc, dentry: Arc) -> Arc { - Arc::new_cyclic(|weak_self| Self { - mount_node, - dentry, - this: weak_self.clone(), - }) - } - - /// Lookup a dentrymnt. - pub fn lookup(&self, name: &str) -> Result> { - if self.dentry.inode().type_() != InodeType::Dir { - return_errno!(Errno::ENOTDIR); - } - if !self.dentry.inode().mode()?.is_executable() { - return_errno!(Errno::EACCES); - } - if name.len() > NAME_MAX { - return_errno!(Errno::ENAMETOOLONG); - } - - let dentrymnt = match name { - "." => self.this(), - ".." => self.effective_parent().unwrap_or(self.this()), - name => { - let children_dentry = self.dentry.lookup_fast(name); - match children_dentry { - Some(dentry) => Self::new(self.mount_node().clone(), dentry.clone()), - None => { - let slow_dentry = self.dentry.lookup_slow(name)?; - Self::new(self.mount_node().clone(), slow_dentry.clone()) - } - } - } - }; - let dentrymnt = dentrymnt.overlaid_dentrymnt(); - Ok(dentrymnt) - } - - // Get the absolute path. - // - // It will resolve the mountpoint automatically. - pub fn abs_path(&self) -> String { - let mut path = self.effective_name(); - let mut dir_dentrymnt = self.this(); - - loop { - match dir_dentrymnt.effective_parent() { - None => break, - Some(parent_dir_dentrymnt) => { - path = { - let parent_name = parent_dir_dentrymnt.effective_name(); - if parent_name != "/" { - parent_name + "/" + &path - } else { - parent_name + &path - } - }; - dir_dentrymnt = parent_dir_dentrymnt; - } - } - } - debug_assert!(path.starts_with('/')); - path - } - - /// Get the effective name of dentrymnt. - /// - /// If it is the root of mount, it will go up to the mountpoint to get the name - /// of the mountpoint recursively. - fn effective_name(&self) -> String { - if !self.dentry.is_root_of_mount() { - return self.dentry.name(); - } - - if self.mount_node.parent().is_some() & self.mount_node.mountpoint_dentry().is_some() { - let parent_dentrymnt = Self::new( - self.mount_node.parent().unwrap().upgrade().unwrap().clone(), - self.mount_node.mountpoint_dentry().unwrap().clone(), - ); - parent_dentrymnt.effective_name() - } else { - self.dentry.name() - } - } - - /// Get the effective parent of dentrymnt. - /// - /// If it is the root of mount, it will go up to the mountpoint to get the parent - /// of the mountpoint recursively. - fn effective_parent(&self) -> Option> { - if !self.dentry.is_root_of_mount() { - return Some(Self::new( - self.mount_node.clone(), - self.dentry.parent().unwrap().clone(), - )); - } - if self.mount_node.parent().is_some() & self.mount_node.mountpoint_dentry().is_some() { - let parent_dentrymnt = Self::new( - self.mount_node.parent().unwrap().upgrade().unwrap().clone(), - self.mount_node.mountpoint_dentry().unwrap().clone(), - ); - parent_dentrymnt.effective_parent() - } else { - None - } - } - - /// Get the overlaid dentrymnt of self. - /// - /// It will jump into the child mount if it is a mountpoint. - fn overlaid_dentrymnt(&self) -> Arc { - if !self.dentry.is_mountpoint() { - return self.this(); - } - match self.mount_node.get(self) { - Some(child_mount) => Self::new(child_mount.clone(), child_mount.root_dentry().clone()) - .overlaid_dentrymnt(), - None => self.this(), - } - } - - /// Mount the fs on this dentrymnt. It will make this dentrymnt's dentry to be a mountpoint. - /// - /// If the given mountpoint has already been mounted, then its mounted child mount - /// will be updated. - /// The root dentry cannot be mounted. - /// - /// Return the mounted child mount. - pub fn mount(&self, fs: Arc) -> Result> { - if self.dentry.inode().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())?; - self.dentry().set_mountpoint(); - Ok(child_mount) - } - - /// Unmount and return the mounted child mount. - /// - /// Note that the root mount cannot be unmounted. - pub fn umount(&self) -> Result> { - if !self.dentry.is_root_of_mount() { - return_errno_with_message!(Errno::EINVAL, "not mounted"); - } - - let mount_node = self.mount_node.clone(); - let Some(mountpoint_dentry) = 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_dentrymnt = - Self::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone()); - - let child_mount = mountpoint_mount_node.umount(&mountpoint_dentrymnt)?; - mountpoint_dentry.clear_mountpoint(); - Ok(child_mount) - } - - /// Link a new name for the dentrymnt's dentry by linking inode. - pub fn link(&self, old: &Arc, name: &str) -> Result<()> { - if self.dentry.inode().type_() != InodeType::Dir { - return_errno!(Errno::ENOTDIR); - } - let children = self.dentry.lookup_fast(name); - if children.is_some() { - return_errno!(Errno::EEXIST); - } - if !Arc::ptr_eq(old.mount_node(), self.mount_node()) { - return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); - } - let old_inode = old.dentry.inode(); - self.dentry.inode().link(old_inode, name)?; - let dentry = self.dentry.new_child(old_inode.clone(), name); - self.dentry.insert_dentry(&dentry); - Ok(()) - } - - /// Get the arc reference to self. - fn this(&self) -> Arc { - self.this.upgrade().unwrap() - } - - /// Get the mount node of this dentrymnt. - pub fn mount_node(&self) -> &Arc { - &self.mount_node - } - - /// Get the dentry of this dentrymnt. - pub fn dentry(&self) -> &Arc { - &self.dentry - } -} diff --git a/kernel/aster-nix/src/fs/utils/mod.rs b/kernel/aster-nix/src/fs/utils/mod.rs index 6ca2b7d6..d05cbb10 100644 --- a/kernel/aster-nix/src/fs/utils/mod.rs +++ b/kernel/aster-nix/src/fs/utils/mod.rs @@ -5,8 +5,7 @@ pub use access_mode::AccessMode; pub use channel::{Channel, Consumer, Producer}; pub use creation_flags::CreationFlags; -pub use dentry::{Dentry, DentryKey}; -pub use dentrymnt::DentryMnt; +pub use dentry::{Dentry, DentryKey, DentryMnt}; pub use dirent_visitor::DirentVisitor; pub use direntry_vec::DirEntryVecExt; pub use file_creation_mask::FileCreationMask; @@ -22,7 +21,6 @@ mod access_mode; mod channel; mod creation_flags; mod dentry; -mod dentrymnt; mod dirent_visitor; mod direntry_vec; mod file_creation_mask; diff --git a/kernel/aster-nix/src/fs/utils/mount.rs b/kernel/aster-nix/src/fs/utils/mount.rs index 7054d6aa..b290629d 100644 --- a/kernel/aster-nix/src/fs/utils/mount.rs +++ b/kernel/aster-nix/src/fs/utils/mount.rs @@ -9,7 +9,7 @@ pub struct MountNode { root_dentry: Arc, /// Mountpoint dentry. A mount node can be mounted on one dentry of another mount node, /// which makes the mount being the child of the mount node. - mountpoint_dentry: Option>, + mountpoint_dentry: RwLock>>, /// The associated FS. fs: Arc, /// The parent mount node. @@ -29,20 +29,21 @@ impl MountNode { /// It is allowed to create a mount node even if the fs has been provided to another /// mount node. It is the fs's responsibility to ensure the data consistency. pub fn new_root(fs: Arc) -> Arc { - Self::new(fs, None, None) + Self::new(fs, None) } /// The internal constructor. /// /// Root mount node has no mountpoint which other mount nodes must have mountpoint. - fn new( - fs: Arc, - mountpoint: Option>, - parent_mount: Option>, - ) -> Arc { + /// + /// Here, a MountNode is instantiated without an initial mountpoint, + /// avoiding fixed mountpoint limitations. This allows the root mount node to + /// exist without a mountpoint, ensuring uniformity and security, while all other + /// mount nodes must be explicitly assigned a mountpoint to maintain structural integrity. + fn new(fs: Arc, parent_mount: Option>) -> Arc { Arc::new_cyclic(|weak_self| Self { root_dentry: Dentry::new_root(fs.root_inode()), - mountpoint_dentry: mountpoint, + mountpoint_dentry: RwLock::new(None), parent: RwLock::new(parent_mount), children: Mutex::new(BTreeMap::new()), fs, @@ -65,16 +66,12 @@ impl MountNode { if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) { return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this"); } - if mountpoint.dentry().type_() != InodeType::Dir { + if mountpoint.type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } - let key = mountpoint.dentry().key(); - let child_mount = Self::new( - fs, - Some(mountpoint.dentry().clone()), - Some(Arc::downgrade(mountpoint.mount_node())), - ); + let key = mountpoint.key(); + let child_mount = Self::new(fs, Some(Arc::downgrade(mountpoint.mount_node()))); self.children.lock().insert(key, child_mount.clone()); Ok(child_mount) } @@ -90,7 +87,7 @@ impl MountNode { let child_mount = self .children .lock() - .remove(&mountpoint.dentry().key()) + .remove(&mountpoint.key()) .ok_or_else(|| Error::with_message(Errno::ENOENT, "can not find child mount"))?; Ok(child_mount) } @@ -100,10 +97,7 @@ impl MountNode { if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) { return None; } - self.children - .lock() - .get(&mountpoint.dentry().key()) - .cloned() + self.children.lock().get(&mountpoint.key()).cloned() } /// Get the root dentry of this mount node. @@ -112,8 +106,17 @@ impl MountNode { } /// Try to get the mountpoint dentry of this mount node. - pub fn mountpoint_dentry(&self) -> Option<&Arc> { - self.mountpoint_dentry.as_ref() + pub fn mountpoint_dentry(&self) -> Option> { + self.mountpoint_dentry.read().clone() + } + + /// Set the mountpoint. + /// + /// In some cases we may need to reset the mountpoint of + /// the created MountNode, such as move mount. + pub fn set_mountpoint_dentry(&self, dentry: Arc) { + let mut mountpoint_dentry = self.mountpoint_dentry.write(); + *mountpoint_dentry = Some(dentry); } /// Flushes all pending filesystem metadata and cached file data to the device. @@ -133,6 +136,10 @@ impl MountNode { self.parent.read().as_ref().cloned() } + /// Set the parent. + /// + /// In some cases we may need to reset the parent of + /// the created MountNode, such as move mount. pub fn set_parent(&self, mount_node: Arc) { let mut parent = self.parent.write(); *parent = Some(Arc::downgrade(&mount_node)); diff --git a/kernel/aster-nix/src/net/socket/unix/addr.rs b/kernel/aster-nix/src/net/socket/unix/addr.rs index bfc36382..997b273b 100644 --- a/kernel/aster-nix/src/net/socket/unix/addr.rs +++ b/kernel/aster-nix/src/net/socket/unix/addr.rs @@ -18,9 +18,7 @@ impl PartialEq for UnixSocketAddrBound { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Abstract(l0), Self::Abstract(r0)) => l0 == r0, - (Self::Path(l0), Self::Path(r0)) => { - Arc::ptr_eq(l0.dentry().inode(), r0.dentry().inode()) - } + (Self::Path(l0), Self::Path(r0)) => Arc::ptr_eq(l0.inode(), r0.inode()), _ => false, } } diff --git a/kernel/aster-nix/src/net/socket/unix/stream/init.rs b/kernel/aster-nix/src/net/socket/unix/stream/init.rs index 107387c6..d9be230a 100644 --- a/kernel/aster-nix/src/net/socket/unix/stream/init.rs +++ b/kernel/aster-nix/src/net/socket/unix/stream/init.rs @@ -37,8 +37,8 @@ impl Init { let bound_addr = match addr_to_bind { UnixSocketAddr::Abstract(_) => todo!(), - UnixSocketAddr::Path(pathname) => { - let dentrymnt = create_socket_file(pathname)?; + UnixSocketAddr::Path(path) => { + let dentrymnt = create_socket_file(path)?; UnixSocketAddrBound::Path(dentrymnt) } }; @@ -87,19 +87,18 @@ impl Init { } } -fn create_socket_file(pathname: &str) -> Result> { - let (parent_pathname, file_name) = split_path(pathname); +fn create_socket_file(path: &str) -> Result> { + let (parent_pathname, file_name) = split_path(path); let parent = { let current = current!(); let fs = current.fs().read(); let parent_path = FsPath::try_from(parent_pathname)?; fs.lookup(&parent_path)? }; - let dentry = parent.dentry().create( + let dentrymnt = parent.new_fs_child( file_name, InodeType::Socket, InodeMode::S_IRUSR | InodeMode::S_IWUSR, )?; - let dentrymnt = DentryMnt::new(parent.mount_node().clone(), dentry.clone()); Ok(dentrymnt) } diff --git a/kernel/aster-nix/src/net/socket/unix/stream/listener.rs b/kernel/aster-nix/src/net/socket/unix/stream/listener.rs index 433e0a5b..59bef02a 100644 --- a/kernel/aster-nix/src/net/socket/unix/stream/listener.rs +++ b/kernel/aster-nix/src/net/socket/unix/stream/listener.rs @@ -213,7 +213,7 @@ impl Backlog { } fn create_keyable_inode(dentrymnt: &Arc) -> KeyableWeak { - let weak_inode = Arc::downgrade(dentrymnt.dentry().inode()); + let weak_inode = Arc::downgrade(dentrymnt.inode()); KeyableWeak::from(weak_inode) } diff --git a/kernel/aster-nix/src/net/socket/unix/stream/socket.rs b/kernel/aster-nix/src/net/socket/unix/stream/socket.rs index 645c5bc3..bc0110e2 100644 --- a/kernel/aster-nix/src/net/socket/unix/stream/socket.rs +++ b/kernel/aster-nix/src/net/socket/unix/stream/socket.rs @@ -161,8 +161,8 @@ impl Socket for UnixStreamSocket { UnixSocketAddr::Abstract(abstract_name) => { UnixSocketAddrBound::Abstract(abstract_name) } - UnixSocketAddr::Path(pathname) => { - let dentrymnt = lookup_socket_file(&pathname)?; + UnixSocketAddr::Path(path) => { + let dentrymnt = lookup_socket_file(&path)?; UnixSocketAddrBound::Path(dentrymnt) } } @@ -287,19 +287,19 @@ impl Drop for UnixStreamSocket { } } -fn lookup_socket_file(pathname: &str) -> Result> { +fn lookup_socket_file(path: &str) -> Result> { let dentrymnt = { let current = current!(); let fs = current.fs().read(); - let fs_path = FsPath::try_from(pathname)?; + let fs_path = FsPath::try_from(path)?; fs.lookup(&fs_path)? }; - if dentrymnt.dentry().type_() != InodeType::Socket { + if dentrymnt.type_() != InodeType::Socket { return_errno_with_message!(Errno::ENOTSOCK, "not a socket file") } - if !dentrymnt.dentry().mode()?.is_readable() || !dentrymnt.dentry().mode()?.is_writable() { + if !dentrymnt.mode()?.is_readable() || !dentrymnt.mode()?.is_writable() { return_errno_with_message!(Errno::EACCES, "the socket cannot be read or written") } Ok(dentrymnt) diff --git a/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs b/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs index 33f7bcc2..f7d321a4 100644 --- a/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs +++ b/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs @@ -12,7 +12,7 @@ use super::elf_file::Elf; use crate::{ fs::{ fs_resolver::{FsPath, FsResolver, AT_FDCWD}, - utils::{Dentry, DentryMnt}, + utils::DentryMnt, }, prelude::*, process::{ @@ -93,7 +93,7 @@ fn lookup_and_parse_ldso( elf: &Elf, file_header: &[u8], fs_resolver: &FsResolver, -) -> Result<(Arc, Elf)> { +) -> Result<(Arc, Elf)> { let ldso_file = { let ldso_path = elf.ldso_path(file_header)?; let fs_path = FsPath::new(AT_FDCWD, &ldso_path)?; @@ -101,14 +101,18 @@ fn lookup_and_parse_ldso( }; let ldso_elf = { let mut buf = Box::new([0u8; PAGE_SIZE]); - let inode = ldso_file.dentry().inode(); + let inode = ldso_file.inode(); inode.read_at(0, &mut *buf)?; Elf::parse_elf(&*buf)? }; - Ok((ldso_file.dentry().clone(), ldso_elf)) + Ok((ldso_file.clone(), ldso_elf)) } -fn load_ldso(root_vmar: &Vmar, ldso_file: &Dentry, ldso_elf: &Elf) -> Result { +fn load_ldso( + root_vmar: &Vmar, + ldso_file: &DentryMnt, + ldso_elf: &Elf, +) -> Result { let map_addr = map_segment_vmos(ldso_elf, root_vmar, ldso_file)?; Ok(LdsoLoadInfo::new( ldso_elf.entry_point() + map_addr, @@ -118,9 +122,9 @@ 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<(Arc, Elf)>, parsed_elf: &Elf, - elf_file: &Dentry, + elf_file: &DentryMnt, ) -> Result<(Vaddr, AuxVec)> { let root_vmar = process_vm.root_vmar(); @@ -199,7 +203,7 @@ impl ElfLoadInfo { } /// init vmo for each segment and then map segment to root vmar -pub fn map_segment_vmos(elf: &Elf, root_vmar: &Vmar, elf_file: &Dentry) -> Result { +pub fn map_segment_vmos(elf: &Elf, root_vmar: &Vmar, elf_file: &DentryMnt) -> Result { // all segments of the shared object must be mapped to a continuous vm range // to ensure the relative offset of each segment not changed. let base_addr = if elf.is_shared_object() { @@ -288,7 +292,10 @@ fn map_segment_vmo( /// Create VMO for each segment. Return the segment VMO and the size of /// additional anonymous mapping it needs. -fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Result<(Vmo, usize)> { +fn init_segment_vmo( + program_header: &ProgramHeader64, + elf_file: &DentryMnt, +) -> Result<(Vmo, usize)> { trace!( "mem range = 0x{:x} - 0x{:x}, mem_size = 0x{:x}", program_header.virtual_addr, diff --git a/kernel/aster-nix/src/process/program_loader/mod.rs b/kernel/aster-nix/src/process/program_loader/mod.rs index 379444e9..8859bab4 100644 --- a/kernel/aster-nix/src/process/program_loader/mod.rs +++ b/kernel/aster-nix/src/process/program_loader/mod.rs @@ -11,7 +11,7 @@ use super::process_vm::ProcessVm; use crate::{ fs::{ fs_resolver::{FsPath, FsResolver, AT_FDCWD}, - utils::{Dentry, DentryMnt}, + utils::DentryMnt, }, prelude::*, }; @@ -32,7 +32,7 @@ pub fn load_program_to_vm( recursion_limit: usize, ) -> Result<(String, ElfLoadInfo)> { let abs_path = elf_file.abs_path(); - let inode = elf_file.dentry().inode(); + let inode = elf_file.inode(); let file_header = { // read the first page of file header let mut file_header_buffer = Box::new([0u8; PAGE_SIZE]); @@ -49,7 +49,7 @@ pub fn load_program_to_vm( let fs_path = FsPath::new(AT_FDCWD, &filename)?; fs_resolver.lookup(&fs_path)? }; - check_executable_file(interpreter.dentry())?; + check_executable_file(&interpreter)?; return load_program_to_vm( process_vm, interpreter, @@ -68,16 +68,16 @@ pub fn load_program_to_vm( Ok((abs_path, elf_load_info)) } -pub fn check_executable_file(dentry: &Arc) -> Result<()> { - if dentry.type_().is_directory() { +pub fn check_executable_file(dentrymnt: &Arc) -> Result<()> { + if dentrymnt.type_().is_directory() { return_errno_with_message!(Errno::EISDIR, "the file is a directory"); } - if !dentry.type_().is_reguler_file() { + if !dentrymnt.type_().is_reguler_file() { return_errno_with_message!(Errno::EACCES, "the dentry is not a regular file"); } - if !dentry.mode()?.is_executable() { + if !dentrymnt.mode()?.is_executable() { return_errno_with_message!(Errno::EACCES, "the dentry is not executable"); } diff --git a/kernel/aster-nix/src/syscall/chdir.rs b/kernel/aster-nix/src/syscall/chdir.rs index dc84bb95..c2aaca4a 100644 --- a/kernel/aster-nix/src/syscall/chdir.rs +++ b/kernel/aster-nix/src/syscall/chdir.rs @@ -9,22 +9,22 @@ use crate::{ util::read_cstring_from_user, }; -pub fn sys_chdir(pathname_addr: Vaddr) -> Result { +pub fn sys_chdir(path_ptr: Vaddr) -> Result { log_syscall_entry!(SYS_CHDIR); - let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; - debug!("pathname = {:?}", pathname); + let path = read_cstring_from_user(path_ptr, MAX_FILENAME_LEN)?; + debug!("path = {:?}", path); let current = current!(); let mut fs = current.fs().write(); let dentrymnt = { - let pathname = pathname.to_string_lossy(); - if pathname.is_empty() { + let path = path.to_string_lossy(); + if path.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::try_from(pathname.as_ref())?; + let fs_path = FsPath::try_from(path.as_ref())?; fs.lookup(&fs_path)? }; - if dentrymnt.dentry().type_() != InodeType::Dir { + if dentrymnt.type_() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "must be directory"); } fs.set_cwd(dentrymnt); @@ -44,7 +44,7 @@ pub fn sys_fchdir(fd: FileDesc) -> Result { .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; inode_handle.dentrymnt().clone() }; - if dentrymnt.dentry().type_() != InodeType::Dir { + if dentrymnt.type_() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "must be directory"); } current.fs().write().set_cwd(dentrymnt); diff --git a/kernel/aster-nix/src/syscall/chmod.rs b/kernel/aster-nix/src/syscall/chmod.rs index bb50d1fb..2e0f678f 100644 --- a/kernel/aster-nix/src/syscall/chmod.rs +++ b/kernel/aster-nix/src/syscall/chmod.rs @@ -47,8 +47,6 @@ pub fn sys_fchmodat( let fs_path = FsPath::new(dirfd, path.as_ref())?; current.fs().read().lookup(&fs_path)? }; - dentrymnt - .dentry() - .set_mode(InodeMode::from_bits_truncate(mode))?; + dentrymnt.set_mode(InodeMode::from_bits_truncate(mode))?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/chown.rs b/kernel/aster-nix/src/syscall/chown.rs index d70c0277..06388200 100644 --- a/kernel/aster-nix/src/syscall/chown.rs +++ b/kernel/aster-nix/src/syscall/chown.rs @@ -90,10 +90,10 @@ pub fn sys_fchownat( } }; if let Some(uid) = uid { - dentrymnt.dentry().set_owner(uid)?; + dentrymnt.set_owner(uid)?; } if let Some(gid) = gid { - dentrymnt.dentry().set_group(gid)?; + dentrymnt.set_group(gid)?; } Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/chroot.rs b/kernel/aster-nix/src/syscall/chroot.rs index e9687075..fab96b73 100644 --- a/kernel/aster-nix/src/syscall/chroot.rs +++ b/kernel/aster-nix/src/syscall/chroot.rs @@ -9,22 +9,22 @@ use crate::{ util::read_cstring_from_user, }; -pub fn sys_chroot(pathname_addr: Vaddr) -> Result { +pub fn sys_chroot(path_ptr: Vaddr) -> Result { log_syscall_entry!(SYS_CHROOT); - let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; - debug!("pathname = {:?}", pathname); + let path = read_cstring_from_user(path_ptr, MAX_FILENAME_LEN)?; + debug!("path = {:?}", path); let current = current!(); let mut fs = current.fs().write(); let dentrymnt = { - let pathname = pathname.to_string_lossy(); - if pathname.is_empty() { + let path = path.to_string_lossy(); + if path.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::try_from(pathname.as_ref())?; + let fs_path = FsPath::try_from(path.as_ref())?; fs.lookup(&fs_path)? }; - if dentrymnt.dentry().type_() != InodeType::Dir { + if dentrymnt.type_() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "must be directory"); } fs.set_root(dentrymnt); diff --git a/kernel/aster-nix/src/syscall/execve.rs b/kernel/aster-nix/src/syscall/execve.rs index 0039b7e9..c84f7097 100644 --- a/kernel/aster-nix/src/syscall/execve.rs +++ b/kernel/aster-nix/src/syscall/execve.rs @@ -8,7 +8,7 @@ use crate::{ fs::{ file_table::FileDesc, fs_resolver::{FsPath, AT_FDCWD}, - utils::{Dentry, DentryMnt, InodeType}, + utils::{DentryMnt, InodeType}, }, log_syscall_entry, prelude::*, @@ -70,7 +70,7 @@ fn lookup_executable_file( let fs_path = FsPath::new(dfd, &filename)?; if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) { let dentrymnt = fs_resolver.lookup_no_follow(&fs_path)?; - if dentrymnt.dentry().type_() == InodeType::SymLink { + if dentrymnt.type_() == InodeType::SymLink { return_errno_with_message!(Errno::ELOOP, "the executable file is a symlink"); } Ok(dentrymnt) @@ -78,7 +78,7 @@ fn lookup_executable_file( fs_resolver.lookup(&fs_path) } }?; - check_executable_file(dentrymnt.dentry())?; + check_executable_file(&dentrymnt)?; Ok(dentrymnt) } @@ -121,8 +121,8 @@ fn do_execve( debug!("load elf in execve succeeds"); let credentials = credentials_mut(); - set_uid_from_elf(&credentials, elf_file.dentry())?; - set_gid_from_elf(&credentials, elf_file.dentry())?; + set_uid_from_elf(&credentials, &elf_file)?; + set_gid_from_elf(&credentials, &elf_file)?; // set executable path current.set_executable_path(new_executable_path); @@ -180,7 +180,7 @@ fn read_cstring_vec( } /// Sets uid for credentials as the same of uid of elf file if elf file has `set_uid` bit. -fn set_uid_from_elf(credentials: &Credentials, elf_file: &Arc) -> Result<()> { +fn set_uid_from_elf(credentials: &Credentials, elf_file: &Arc) -> Result<()> { if elf_file.mode()?.has_set_uid() { let uid = elf_file.owner()?; credentials.set_euid(uid); @@ -192,7 +192,7 @@ fn set_uid_from_elf(credentials: &Credentials, elf_file: &Arc) } /// Sets gid for credentials as the same of gid of elf file if elf file has `set_gid` bit. -fn set_gid_from_elf(credentials: &Credentials, elf_file: &Arc) -> Result<()> { +fn set_gid_from_elf(credentials: &Credentials, elf_file: &Arc) -> Result<()> { if elf_file.mode()?.has_set_gid() { let gid = elf_file.group()?; credentials.set_egid(gid); diff --git a/kernel/aster-nix/src/syscall/fsync.rs b/kernel/aster-nix/src/syscall/fsync.rs index 74cdb601..014d8c26 100644 --- a/kernel/aster-nix/src/syscall/fsync.rs +++ b/kernel/aster-nix/src/syscall/fsync.rs @@ -11,15 +11,15 @@ pub fn sys_fsync(fd: FileDesc) -> Result { log_syscall_entry!(SYS_FSYNC); debug!("fd = {}", fd); - let dentry = { + let dentrymnt = { let current = current!(); let file_table = current.file_table().lock(); let file = file_table.get_file(fd)?; let inode_handle = file .downcast_ref::() .ok_or(Error::with_message(Errno::EINVAL, "not inode"))?; - inode_handle.dentrymnt().dentry().clone() + inode_handle.dentrymnt().clone() }; - dentry.sync()?; + dentrymnt.sync()?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/getdents64.rs b/kernel/aster-nix/src/syscall/getdents64.rs index e5f8261a..ece1b868 100644 --- a/kernel/aster-nix/src/syscall/getdents64.rs +++ b/kernel/aster-nix/src/syscall/getdents64.rs @@ -29,7 +29,7 @@ pub fn sys_getdents64(fd: FileDesc, buf_addr: Vaddr, buf_len: usize) -> Result() .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; - if inode_handle.dentrymnt().dentry().type_() != InodeType::Dir { + if inode_handle.dentrymnt().type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } let mut buffer = vec![0u8; buf_len]; diff --git a/kernel/aster-nix/src/syscall/link.rs b/kernel/aster-nix/src/syscall/link.rs index 42bec4bf..30e396eb 100644 --- a/kernel/aster-nix/src/syscall/link.rs +++ b/kernel/aster-nix/src/syscall/link.rs @@ -14,37 +14,37 @@ use crate::{ pub fn sys_linkat( old_dirfd: FileDesc, - old_pathname_addr: Vaddr, + old_path_addr: Vaddr, new_dirfd: FileDesc, - new_pathname_addr: Vaddr, + new_path_addr: Vaddr, flags: u32, ) -> Result { log_syscall_entry!(SYS_LINKAT); - let old_pathname = read_cstring_from_user(old_pathname_addr, MAX_FILENAME_LEN)?; - let new_pathname = read_cstring_from_user(new_pathname_addr, MAX_FILENAME_LEN)?; + let old_path = read_cstring_from_user(old_path_addr, MAX_FILENAME_LEN)?; + let new_path = read_cstring_from_user(new_path_addr, MAX_FILENAME_LEN)?; let flags = LinkFlags::from_bits(flags).ok_or(Error::with_message(Errno::EINVAL, "invalid flags"))?; debug!( - "old_dirfd = {}, old_pathname = {:?}, new_dirfd = {}, new_pathname = {:?}, flags = {:?}", - old_dirfd, old_pathname, new_dirfd, new_pathname, flags + "old_dirfd = {}, old_path = {:?}, new_dirfd = {}, new_path = {:?}, flags = {:?}", + old_dirfd, old_path, new_dirfd, new_path, flags ); let current = current!(); let (old_dentrymnt, new_dir_dentrymnt, new_name) = { - let old_pathname = old_pathname.to_string_lossy(); - if old_pathname.ends_with('/') { + let old_path = old_path.to_string_lossy(); + if old_path.ends_with('/') { return_errno_with_message!(Errno::EPERM, "oldpath is dir"); } - if old_pathname.is_empty() && !flags.contains(LinkFlags::AT_EMPTY_PATH) { + if old_path.is_empty() && !flags.contains(LinkFlags::AT_EMPTY_PATH) { return_errno_with_message!(Errno::ENOENT, "oldpath is empty"); } - let new_pathname = new_pathname.to_string_lossy(); - if new_pathname.ends_with('/') || new_pathname.is_empty() { + let new_path = new_path.to_string_lossy(); + if new_path.ends_with('/') || new_path.is_empty() { return_errno_with_message!(Errno::ENOENT, "newpath is dir or is empty"); } - let old_fs_path = FsPath::new(old_dirfd, old_pathname.as_ref())?; - let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref())?; + let old_fs_path = FsPath::new(old_dirfd, old_path.as_ref())?; + let new_fs_path = FsPath::new(new_dirfd, new_path.as_ref())?; let fs = current.fs().read(); let old_dentrymnt = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) { fs.lookup(&old_fs_path)? @@ -54,12 +54,13 @@ pub fn sys_linkat( let (new_dir_dentrymnt, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?; (old_dentrymnt, new_dir_dentrymnt, new_name) }; + new_dir_dentrymnt.link(&old_dentrymnt, &new_name)?; Ok(SyscallReturn::Return(0)) } -pub fn sys_link(old_pathname_addr: Vaddr, new_pathname_addr: Vaddr) -> Result { - self::sys_linkat(AT_FDCWD, old_pathname_addr, AT_FDCWD, new_pathname_addr, 0) +pub fn sys_link(old_path_addr: Vaddr, new_path_addr: Vaddr) -> Result { + self::sys_linkat(AT_FDCWD, old_path_addr, AT_FDCWD, new_path_addr, 0) } bitflags::bitflags! { diff --git a/kernel/aster-nix/src/syscall/mkdir.rs b/kernel/aster-nix/src/syscall/mkdir.rs index 648f618e..79035f99 100644 --- a/kernel/aster-nix/src/syscall/mkdir.rs +++ b/kernel/aster-nix/src/syscall/mkdir.rs @@ -13,21 +13,18 @@ use crate::{ util::read_cstring_from_user, }; -pub fn sys_mkdirat(dirfd: FileDesc, pathname_addr: Vaddr, mode: u16) -> Result { +pub fn sys_mkdirat(dirfd: FileDesc, path_addr: Vaddr, mode: u16) -> Result { log_syscall_entry!(SYS_MKDIRAT); - let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; - debug!( - "dirfd = {}, pathname = {:?}, mode = {}", - dirfd, pathname, mode - ); + let path = read_cstring_from_user(path_addr, MAX_FILENAME_LEN)?; + debug!("dirfd = {}, path = {:?}, mode = {}", dirfd, path, mode); let current = current!(); let (dir_dentrymnt, name) = { - let pathname = pathname.to_string_lossy(); - if pathname.is_empty() { + let path = path.to_string_lossy(); + if path.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::new(dirfd, pathname.as_ref())?; + let fs_path = FsPath::new(dirfd, path.as_ref())?; current.fs().read().lookup_dir_and_base_name(&fs_path)? }; @@ -35,13 +32,10 @@ pub fn sys_mkdirat(dirfd: FileDesc, pathname_addr: Vaddr, mode: u16) -> Result Result { - self::sys_mkdirat(AT_FDCWD, pathname_addr, mode) +pub fn sys_mkdir(path_addr: Vaddr, mode: u16) -> Result { + self::sys_mkdirat(AT_FDCWD, path_addr, mode) } diff --git a/kernel/aster-nix/src/syscall/mmap.rs b/kernel/aster-nix/src/syscall/mmap.rs index a5dc9e62..a3a74dc1 100644 --- a/kernel/aster-nix/src/syscall/mmap.rs +++ b/kernel/aster-nix/src/syscall/mmap.rs @@ -101,7 +101,7 @@ fn alloc_filebacked_vmo( let page_cache_vmo = { let fs_resolver = current.fs().read(); let dentrymnt = fs_resolver.lookup_from_fd(fd)?; - let inode = dentrymnt.dentry().inode(); + let inode = dentrymnt.inode(); inode .page_cache() .ok_or(Error::with_message( diff --git a/kernel/aster-nix/src/syscall/open.rs b/kernel/aster-nix/src/syscall/open.rs index 4fd739fa..6244d5fe 100644 --- a/kernel/aster-nix/src/syscall/open.rs +++ b/kernel/aster-nix/src/syscall/open.rs @@ -16,21 +16,21 @@ use crate::{ pub fn sys_openat( dirfd: FileDesc, - pathname_addr: Vaddr, + path_addr: Vaddr, flags: u32, mode: u16, ) -> Result { log_syscall_entry!(SYS_OPENAT); - let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; + let path = read_cstring_from_user(path_addr, MAX_FILENAME_LEN)?; debug!( - "dirfd = {}, pathname = {:?}, flags = {}, mode = {}", - dirfd, pathname, flags, mode + "dirfd = {}, path = {:?}, flags = {}, mode = {}", + dirfd, path, flags, mode ); let current = current!(); let file_handle = { - let pathname = pathname.to_string_lossy(); - let fs_path = FsPath::new(dirfd, pathname.as_ref())?; + let path = path.to_string_lossy(); + let fs_path = FsPath::new(dirfd, path.as_ref())?; let mask_mode = mode & !current.umask().read().get(); let inode_handle = current.fs().read().open(&fs_path, flags, mask_mode)?; Arc::new(inode_handle) @@ -48,8 +48,8 @@ pub fn sys_openat( Ok(SyscallReturn::Return(fd as _)) } -pub fn sys_open(pathname_addr: Vaddr, flags: u32, mode: u16) -> Result { - self::sys_openat(AT_FDCWD, pathname_addr, flags, mode) +pub fn sys_open(path_addr: Vaddr, flags: u32, mode: u16) -> Result { + self::sys_openat(AT_FDCWD, path_addr, flags, mode) } /// File for output busybox ash log. diff --git a/kernel/aster-nix/src/syscall/readlink.rs b/kernel/aster-nix/src/syscall/readlink.rs index 96c02eac..81dc9f55 100644 --- a/kernel/aster-nix/src/syscall/readlink.rs +++ b/kernel/aster-nix/src/syscall/readlink.rs @@ -14,27 +14,27 @@ use crate::{ pub fn sys_readlinkat( dirfd: FileDesc, - pathname_addr: Vaddr, + path_addr: Vaddr, usr_buf_addr: Vaddr, usr_buf_len: usize, ) -> Result { log_syscall_entry!(SYS_READLINKAT); - let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; + let path = read_cstring_from_user(path_addr, MAX_FILENAME_LEN)?; debug!( - "dirfd = {}, pathname = {:?}, usr_buf_addr = 0x{:x}, usr_buf_len = 0x{:x}", - dirfd, pathname, usr_buf_addr, usr_buf_len + "dirfd = {}, path = {:?}, usr_buf_addr = 0x{:x}, usr_buf_len = 0x{:x}", + dirfd, path, usr_buf_addr, usr_buf_len ); let current = current!(); let dentrymnt = { - let pathname = pathname.to_string_lossy(); - if pathname.is_empty() { + let path = path.to_string_lossy(); + if path.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::new(dirfd, pathname.as_ref())?; + let fs_path = FsPath::new(dirfd, path.as_ref())?; current.fs().read().lookup_no_follow(&fs_path)? }; - let linkpath = dentrymnt.dentry().inode().read_link()?; + let linkpath = dentrymnt.inode().read_link()?; let bytes = linkpath.as_bytes(); let write_len = bytes.len().min(usr_buf_len); write_bytes_to_user(usr_buf_addr, &bytes[..write_len])?; @@ -42,9 +42,9 @@ pub fn sys_readlinkat( } pub fn sys_readlink( - pathname_addr: Vaddr, + path_addr: Vaddr, usr_buf_addr: Vaddr, usr_buf_len: usize, ) -> Result { - self::sys_readlinkat(AT_FDCWD, pathname_addr, usr_buf_addr, usr_buf_len) + self::sys_readlinkat(AT_FDCWD, path_addr, usr_buf_addr, usr_buf_len) } diff --git a/kernel/aster-nix/src/syscall/rename.rs b/kernel/aster-nix/src/syscall/rename.rs index 0d07f3a5..36c91d68 100644 --- a/kernel/aster-nix/src/syscall/rename.rs +++ b/kernel/aster-nix/src/syscall/rename.rs @@ -15,40 +15,40 @@ use crate::{ pub fn sys_renameat( old_dirfd: FileDesc, - old_pathname_addr: Vaddr, + old_path_addr: Vaddr, new_dirfd: FileDesc, - new_pathname_addr: Vaddr, + new_path_addr: Vaddr, ) -> Result { log_syscall_entry!(SYS_RENAMEAT); - let old_pathname = read_cstring_from_user(old_pathname_addr, MAX_FILENAME_LEN)?; - let new_pathname = read_cstring_from_user(new_pathname_addr, MAX_FILENAME_LEN)?; + let old_path = read_cstring_from_user(old_path_addr, MAX_FILENAME_LEN)?; + let new_path = read_cstring_from_user(new_path_addr, MAX_FILENAME_LEN)?; debug!( - "old_dirfd = {}, old_pathname = {:?}, new_dirfd = {}, new_pathname = {:?}", - old_dirfd, old_pathname, new_dirfd, new_pathname + "old_dirfd = {}, old_path = {:?}, new_dirfd = {}, new_path = {:?}", + old_dirfd, old_path, new_dirfd, new_path ); let current = current!(); let fs = current.fs().read(); let (old_dir_dentrymnt, old_name) = { - let old_pathname = old_pathname.to_string_lossy(); - if old_pathname.is_empty() { + let old_path = old_path.to_string_lossy(); + if old_path.is_empty() { return_errno_with_message!(Errno::ENOENT, "oldpath is empty"); } - let old_fs_path = FsPath::new(old_dirfd, old_pathname.as_ref())?; + let old_fs_path = FsPath::new(old_dirfd, old_path.as_ref())?; fs.lookup_dir_and_base_name(&old_fs_path)? }; let old_dentrymnt = old_dir_dentrymnt.lookup(&old_name)?; let (new_dir_dentrymnt, new_name) = { - let new_pathname = new_pathname.to_string_lossy(); - if new_pathname.is_empty() { + let new_path = new_path.to_string_lossy(); + if new_path.is_empty() { return_errno_with_message!(Errno::ENOENT, "newpath is empty"); } - if new_pathname.ends_with('/') && old_dentrymnt.dentry().type_() != InodeType::Dir { + if new_path.ends_with('/') && old_dentrymnt.type_() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "oldpath is not dir"); } - let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref().trim_end_matches('/'))?; + let new_fs_path = FsPath::new(new_dirfd, new_path.as_ref().trim_end_matches('/'))?; fs.lookup_dir_and_base_name(&new_fs_path)? }; @@ -66,20 +66,11 @@ pub fn sys_renameat( } } - if !Arc::ptr_eq( - old_dir_dentrymnt.mount_node(), - new_dir_dentrymnt.mount_node(), - ) { - return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); - } - - old_dir_dentrymnt - .dentry() - .rename(&old_name, new_dir_dentrymnt.dentry(), &new_name)?; + old_dir_dentrymnt.rename(&old_name, &new_dir_dentrymnt, &new_name)?; Ok(SyscallReturn::Return(0)) } -pub fn sys_rename(old_pathname_addr: Vaddr, new_pathname_addr: Vaddr) -> Result { - self::sys_renameat(AT_FDCWD, old_pathname_addr, AT_FDCWD, new_pathname_addr) +pub fn sys_rename(old_path_addr: Vaddr, new_path_addr: Vaddr) -> Result { + self::sys_renameat(AT_FDCWD, old_path_addr, AT_FDCWD, new_path_addr) } diff --git a/kernel/aster-nix/src/syscall/rmdir.rs b/kernel/aster-nix/src/syscall/rmdir.rs index 19635c50..e466a469 100644 --- a/kernel/aster-nix/src/syscall/rmdir.rs +++ b/kernel/aster-nix/src/syscall/rmdir.rs @@ -12,24 +12,24 @@ use crate::{ util::read_cstring_from_user, }; -pub fn sys_rmdir(pathname_addr: Vaddr) -> Result { - self::sys_rmdirat(AT_FDCWD, pathname_addr) +pub fn sys_rmdir(path_addr: Vaddr) -> Result { + self::sys_rmdirat(AT_FDCWD, path_addr) } -pub(super) fn sys_rmdirat(dirfd: FileDesc, pathname_addr: Vaddr) -> Result { +pub(super) fn sys_rmdirat(dirfd: FileDesc, path_addr: Vaddr) -> Result { log_syscall_entry!(SYS_RMDIR); - let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; - debug!("dirfd = {}, pathname = {:?}", dirfd, pathname); + let path_addr = read_cstring_from_user(path_addr, MAX_FILENAME_LEN)?; + debug!("dirfd = {}, path_addr = {:?}", dirfd, path_addr); let current = current!(); let (dir_dentrymnt, name) = { - let pathname = pathname.to_string_lossy(); - if pathname == "/" { + let path_addr = path_addr.to_string_lossy(); + if path_addr == "/" { return_errno_with_message!(Errno::EBUSY, "is root directory"); } - let fs_path = FsPath::new(dirfd, pathname.as_ref())?; + let fs_path = FsPath::new(dirfd, path_addr.as_ref())?; current.fs().read().lookup_dir_and_base_name(&fs_path)? }; - dir_dentrymnt.dentry().rmdir(name.trim_end_matches('/'))?; + dir_dentrymnt.rmdir(name.trim_end_matches('/'))?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/stat.rs b/kernel/aster-nix/src/syscall/stat.rs index f13eace7..dd261622 100644 --- a/kernel/aster-nix/src/syscall/stat.rs +++ b/kernel/aster-nix/src/syscall/stat.rs @@ -73,7 +73,7 @@ pub fn sys_fstatat( fs.lookup(&fs_path)? } }; - let stat = Stat::from(dentrymnt.dentry().metadata()); + let stat = Stat::from(dentrymnt.metadata()); write_val_to_user(stat_buf_ptr, &stat)?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/statfs.rs b/kernel/aster-nix/src/syscall/statfs.rs index e688bf6b..10a12c00 100644 --- a/kernel/aster-nix/src/syscall/statfs.rs +++ b/kernel/aster-nix/src/syscall/statfs.rs @@ -15,19 +15,16 @@ use crate::{ pub fn sys_statfs(path_ptr: Vaddr, statfs_buf_ptr: Vaddr) -> Result { log_syscall_entry!(SYS_STATFS); - let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?; - debug!( - "pathname = {:?}, statfs_buf_ptr = 0x{:x}", - pathname, statfs_buf_ptr, - ); + let path = read_cstring_from_user(path_ptr, PATH_MAX)?; + debug!("path = {:?}, statfs_buf_ptr = 0x{:x}", path, statfs_buf_ptr,); let current = current!(); - let path = { - let pathname = pathname.to_string_lossy(); - let fs_path = FsPath::try_from(pathname.as_ref())?; + let dentrymnt = { + let path = path.to_string_lossy(); + let fs_path = FsPath::try_from(path.as_ref())?; current.fs().read().lookup(&fs_path)? }; - let statfs = Statfs::from(path.dentry().fs().sb()); + let statfs = Statfs::from(dentrymnt.fs().sb()); write_val_to_user(statfs_buf_ptr, &statfs)?; Ok(SyscallReturn::Return(0)) } @@ -42,8 +39,8 @@ pub fn sys_fstatfs(fd: FileDesc, statfs_buf_ptr: Vaddr) -> Result let inode_handle = file .downcast_ref::() .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; - let dentry = inode_handle.dentrymnt().dentry(); - let statfs = Statfs::from(dentry.fs().sb()); + let dentrymnt = inode_handle.dentrymnt(); + let statfs = Statfs::from(dentrymnt.fs().sb()); write_val_to_user(statfs_buf_ptr, &statfs)?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/symlink.rs b/kernel/aster-nix/src/syscall/symlink.rs index 7f56d28c..6cd9808c 100644 --- a/kernel/aster-nix/src/syscall/symlink.rs +++ b/kernel/aster-nix/src/syscall/symlink.rs @@ -43,7 +43,7 @@ pub fn sys_symlinkat( current.fs().read().lookup_dir_and_base_name(&fs_path)? }; - let new_dentry = dir_dentrymnt.dentry().create( + let new_dentry = dir_dentrymnt.new_fs_child( &link_name, InodeType::SymLink, InodeMode::from_bits_truncate(0o777), diff --git a/kernel/aster-nix/src/syscall/truncate.rs b/kernel/aster-nix/src/syscall/truncate.rs index fdc82dd2..c82a7ca8 100644 --- a/kernel/aster-nix/src/syscall/truncate.rs +++ b/kernel/aster-nix/src/syscall/truncate.rs @@ -28,21 +28,21 @@ pub fn sys_ftruncate(fd: FileDesc, len: isize) -> Result { pub fn sys_truncate(path_ptr: Vaddr, len: isize) -> Result { log_syscall_entry!(SYS_TRUNCATE); - let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?; - debug!("pathname = {:?}, length = {}", pathname, len); + let path = read_cstring_from_user(path_ptr, PATH_MAX)?; + debug!("path = {:?}, length = {}", path, len); check_length(len)?; let current = current!(); let dir_dentrymnt = { - let pathname = pathname.to_string_lossy(); - if pathname.is_empty() { + let path = path.to_string_lossy(); + if path.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::new(AT_FDCWD, pathname.as_ref())?; + let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?; current.fs().read().lookup(&fs_path)? }; - dir_dentrymnt.dentry().resize(len as usize)?; + dir_dentrymnt.resize(len as usize)?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/unlink.rs b/kernel/aster-nix/src/syscall/unlink.rs index 2c8b12f8..acb9330a 100644 --- a/kernel/aster-nix/src/syscall/unlink.rs +++ b/kernel/aster-nix/src/syscall/unlink.rs @@ -12,35 +12,35 @@ use crate::{ util::read_cstring_from_user, }; -pub fn sys_unlinkat(dirfd: FileDesc, pathname_addr: Vaddr, flags: u32) -> Result { +pub fn sys_unlinkat(dirfd: FileDesc, path_addr: Vaddr, flags: u32) -> Result { let flags = UnlinkFlags::from_bits(flags).ok_or(Error::with_message(Errno::EINVAL, "invalid flags"))?; if flags.contains(UnlinkFlags::AT_REMOVEDIR) { - return super::rmdir::sys_rmdirat(dirfd, pathname_addr); + return super::rmdir::sys_rmdirat(dirfd, path_addr); } log_syscall_entry!(SYS_UNLINKAT); - let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; - debug!("dirfd = {}, pathname = {:?}", dirfd, pathname); + let path = read_cstring_from_user(path_addr, MAX_FILENAME_LEN)?; + debug!("dirfd = {}, path = {:?}", dirfd, path); let current = current!(); let (dir_dentrymnt, name) = { - let pathname = pathname.to_string_lossy(); - if pathname.is_empty() { + let path = path.to_string_lossy(); + if path.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - if pathname.ends_with('/') { + if path.ends_with('/') { return_errno_with_message!(Errno::EISDIR, "unlink on directory"); } - let fs_path = FsPath::new(dirfd, pathname.as_ref())?; + let fs_path = FsPath::new(dirfd, path.as_ref())?; current.fs().read().lookup_dir_and_base_name(&fs_path)? }; - dir_dentrymnt.dentry().unlink(&name)?; + dir_dentrymnt.unlink(&name)?; Ok(SyscallReturn::Return(0)) } -pub fn sys_unlink(pathname_addr: Vaddr) -> Result { - self::sys_unlinkat(AT_FDCWD, pathname_addr, 0) +pub fn sys_unlink(path_addr: Vaddr) -> Result { + self::sys_unlinkat(AT_FDCWD, path_addr, 0) } bitflags::bitflags! { diff --git a/kernel/aster-nix/src/syscall/utimens.rs b/kernel/aster-nix/src/syscall/utimens.rs index d356a0c3..14d8b364 100644 --- a/kernel/aster-nix/src/syscall/utimens.rs +++ b/kernel/aster-nix/src/syscall/utimens.rs @@ -14,12 +14,12 @@ use crate::{ pub fn sys_utimensat( dirfd: FileDesc, - pathname_ptr: Vaddr, + path_addr: Vaddr, timespecs_ptr: Vaddr, flags: u32, ) -> Result { log_syscall_entry!(SYS_UTIMENSAT); - let pathname = read_cstring_from_user(pathname_ptr, MAX_FILENAME_LEN)?; + let path = read_cstring_from_user(path_addr, MAX_FILENAME_LEN)?; let (atime, mtime) = { let (autime, mutime) = if timespecs_ptr == 0 { (timespec_t::utime_now(), timespec_t::utime_now()) @@ -53,8 +53,8 @@ pub fn sys_utimensat( let flags = UtimensFlags::from_bits(flags) .ok_or(Error::with_message(Errno::EINVAL, "invalid flags"))?; debug!( - "dirfd = {}, pathname = {:?}, atime = {:?}, mtime = {:?}, flags = {:?}", - dirfd, pathname, atime, mtime, flags + "dirfd = {}, path = {:?}, atime = {:?}, mtime = {:?}, flags = {:?}", + dirfd, path, atime, mtime, flags ); if atime.is_none() && mtime.is_none() { @@ -62,11 +62,11 @@ pub fn sys_utimensat( } let current = current!(); let dentrymnt = { - let pathname = pathname.to_string_lossy(); - if pathname.is_empty() { - return_errno_with_message!(Errno::ENOENT, "pathname is empty"); + let path = path.to_string_lossy(); + if path.is_empty() { + return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::new(dirfd, pathname.as_ref())?; + let fs_path = FsPath::new(dirfd, path.as_ref())?; let fs = current.fs().read(); if flags.contains(UtimensFlags::AT_SYMLINK_NOFOLLOW) { fs.lookup_no_follow(&fs_path)? @@ -75,10 +75,10 @@ pub fn sys_utimensat( } }; if let Some(time) = atime { - dentrymnt.dentry().set_atime(Duration::from(time)); + dentrymnt.set_atime(Duration::from(time)); } if let Some(time) = mtime { - dentrymnt.dentry().set_mtime(Duration::from(time)); + dentrymnt.set_mtime(Duration::from(time)); } Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/vdso.rs b/kernel/aster-nix/src/vdso.rs index 6905284e..077c2e59 100644 --- a/kernel/aster-nix/src/vdso.rs +++ b/kernel/aster-nix/src/vdso.rs @@ -220,7 +220,7 @@ impl Vdso { let vdso_path = FsPath::new(AT_FDCWD, "/lib/x86_64-linux-gnu/vdso64.so").unwrap(); let fs_resolver = FsResolver::new(); let vdso_lib = fs_resolver.lookup(&vdso_path).unwrap(); - vdso_lib.dentry().inode().page_cache().unwrap() + vdso_lib.inode().page_cache().unwrap() }; let mut vdso_text = Box::new([0u8; PAGE_SIZE]); vdso_lib_vmo.read_bytes(0, &mut *vdso_text).unwrap();