From 6d486c6c0176a3a5af667b1826eec9f6732539a2 Mon Sep 17 00:00:00 2001 From: plucky Date: Tue, 9 Apr 2024 09:30:58 +0800 Subject: [PATCH] Add struct Path for VFS Signed-off-by: Zhenchen Wang --- kernel/aster-nix/src/device/pty/mod.rs | 17 +- kernel/aster-nix/src/fs/device.rs | 26 +- kernel/aster-nix/src/fs/fs_resolver.rs | 140 ++++++----- .../aster-nix/src/fs/inode_handle/dyn_cap.rs | 8 +- kernel/aster-nix/src/fs/inode_handle/mod.rs | 36 +-- kernel/aster-nix/src/fs/procfs/pid/fd.rs | 6 +- kernel/aster-nix/src/fs/rootfs.rs | 18 +- kernel/aster-nix/src/fs/utils/dentry.rs | 229 +++--------------- kernel/aster-nix/src/fs/utils/mod.rs | 2 + kernel/aster-nix/src/fs/utils/mount.rs | 55 +++-- kernel/aster-nix/src/fs/utils/path.rs | 210 ++++++++++++++++ kernel/aster-nix/src/lib.rs | 1 - kernel/aster-nix/src/net/socket/unix/addr.rs | 12 +- .../src/net/socket/unix/stream/init.rs | 17 +- .../src/net/socket/unix/stream/listener.rs | 14 +- .../src/net/socket/unix/stream/socket.rs | 20 +- .../process/posix_thread/posix_thread_ext.rs | 2 +- .../process/program_loader/elf/load_elf.rs | 8 +- .../src/process/program_loader/mod.rs | 8 +- kernel/aster-nix/src/syscall/chdir.rs | 14 +- kernel/aster-nix/src/syscall/chmod.rs | 18 +- kernel/aster-nix/src/syscall/chown.rs | 16 +- kernel/aster-nix/src/syscall/chroot.rs | 6 +- kernel/aster-nix/src/syscall/execve.rs | 22 +- kernel/aster-nix/src/syscall/fsync.rs | 2 +- kernel/aster-nix/src/syscall/getdents64.rs | 2 +- kernel/aster-nix/src/syscall/link.rs | 10 +- kernel/aster-nix/src/syscall/mkdir.rs | 6 +- kernel/aster-nix/src/syscall/mmap.rs | 4 +- kernel/aster-nix/src/syscall/readlink.rs | 4 +- kernel/aster-nix/src/syscall/rename.rs | 20 +- kernel/aster-nix/src/syscall/rmdir.rs | 4 +- kernel/aster-nix/src/syscall/stat.rs | 4 +- kernel/aster-nix/src/syscall/statfs.rs | 17 +- kernel/aster-nix/src/syscall/symlink.rs | 4 +- kernel/aster-nix/src/syscall/truncate.rs | 14 +- kernel/aster-nix/src/syscall/unlink.rs | 4 +- kernel/aster-nix/src/syscall/utimens.rs | 6 +- kernel/aster-nix/src/vdso.rs | 2 +- 39 files changed, 561 insertions(+), 447 deletions(-) create mode 100644 kernel/aster-nix/src/fs/utils/path.rs diff --git a/kernel/aster-nix/src/device/pty/mod.rs b/kernel/aster-nix/src/device/pty/mod.rs index ae94ab09e..281cfc33b 100644 --- a/kernel/aster-nix/src/device/pty/mod.rs +++ b/kernel/aster-nix/src/device/pty/mod.rs @@ -4,7 +4,7 @@ use crate::{ fs::{ devpts::DevPts, fs_resolver::{FsPath, FsResolver}, - utils::{Dentry, Inode, InodeMode, InodeType}, + utils::{Inode, InodeMode, InodeType, Path}, }, prelude::*, }; @@ -15,20 +15,29 @@ 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(); let dev = fs.lookup(&FsPath::try_from("/dev")?)?; // Create the "pts" directory and mount devpts on it. - let devpts = dev.create("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?; + let devpts_dentry = + dev.dentry() + .create("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?; + let devpts_mount_node = + Path::new(dev.mount_node().clone(), devpts_dentry.clone()).mount(DevPts::new())?; + let devpts = Path::new( + devpts_mount_node.clone(), + devpts_mount_node.root_dentry().clone(), + ); + devpts.mount(DevPts::new())?; DEV_PTS.call_once(|| devpts); // Create the "ptmx" symlink. - let ptmx = dev.create( + let ptmx = dev.dentry().create( "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 ca7b78add..5800e0be2 100644 --- a/kernel/aster-nix/src/fs/device.rs +++ b/kernel/aster-nix/src/fs/device.rs @@ -84,13 +84,15 @@ 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, path: &str) -> Result> { - let mut dentry = { +pub fn add_node(device: Arc, pathname: &str) -> Result> { + let mut path = { let fs_resolver = FsResolver::new(); fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())? }; + let mut dentry = path.dentry().clone(); + let mut relative_path = { - let relative_path = path.trim_start_matches('/'); + let relative_path = pathname.trim_start_matches('/'); if relative_path.is_empty() { return_errno_with_message!(Errno::EINVAL, "invalid device path"); } @@ -105,24 +107,24 @@ pub fn add_node(device: Arc, path: &str) -> Result> { (relative_path, "") }; - match dentry.lookup(next_name) { - Ok(next_dentry) => { + match path.lookup(next_name) { + Ok(next_path) => { if path_remain.is_empty() { return_errno_with_message!(Errno::EEXIST, "device node is existing"); } - dentry = next_dentry; + path = next_path; } Err(_) => { if path_remain.is_empty() { // Create the device node - dentry = dentry.mknod( + dentry = path.dentry().mknod( next_name, InodeMode::from_bits_truncate(0o666), device.clone(), )?; } else { // Mkdir parent path - dentry = dentry.create( + dentry = path.dentry().create( next_name, InodeType::Dir, InodeMode::from_bits_truncate(0o755), @@ -139,20 +141,20 @@ pub fn add_node(device: Arc, path: &str) -> Result> { /// Delete the device node from FS for the device. /// /// This function is used in unregistering device. -pub fn delete_node(path: &str) -> Result<()> { +pub fn delete_node(pathname: &str) -> Result<()> { let abs_path = { - let device_path = path.trim_start_matches('/'); + let device_path = pathname.trim_start_matches('/'); if device_path.is_empty() { return_errno_with_message!(Errno::EINVAL, "invalid device path"); } String::from("/dev") + "/" + device_path }; - let (parent_dentry, name) = { + let (parent_path, name) = { let fs_resolver = FsResolver::new(); fs_resolver.lookup_dir_and_base_name(&FsPath::try_from(abs_path.as_str()).unwrap())? }; - parent_dentry.unlink(&name)?; + parent_path.dentry().unlink(&name)?; Ok(()) } diff --git a/kernel/aster-nix/src/fs/fs_resolver.rs b/kernel/aster-nix/src/fs/fs_resolver.rs index 0ff2d700e..2eea07b29 100644 --- a/kernel/aster-nix/src/fs/fs_resolver.rs +++ b/kernel/aster-nix/src/fs/fs_resolver.rs @@ -7,16 +7,15 @@ use super::{ inode_handle::InodeHandle, rootfs::root_mount, utils::{ - AccessMode, CreationFlags, Dentry, InodeMode, InodeType, StatusFlags, PATH_MAX, - SYMLINKS_MAX, + AccessMode, CreationFlags, InodeMode, InodeType, Path, StatusFlags, PATH_MAX, SYMLINKS_MAX, }, }; use crate::prelude::*; #[derive(Debug)] pub struct FsResolver { - root: Arc, - cwd: Arc, + root: Arc, + cwd: Arc, } impl Clone for FsResolver { @@ -37,33 +36,33 @@ impl Default for FsResolver { impl FsResolver { pub fn new() -> Self { Self { - root: root_mount().root_dentry().clone(), - cwd: root_mount().root_dentry().clone(), + root: Path::new(root_mount().clone(), root_mount().root_dentry().clone()), + cwd: Path::new(root_mount().clone(), root_mount().root_dentry().clone()), } } /// Get the root directory - pub fn root(&self) -> &Arc { + pub fn root(&self) -> &Arc { &self.root } /// Get the current working directory - pub fn cwd(&self) -> &Arc { + pub fn cwd(&self) -> &Arc { &self.cwd } /// Set the current working directory. - pub fn set_cwd(&mut self, dentry: Arc) { - self.cwd = dentry; + pub fn set_cwd(&mut self, path: Arc) { + self.cwd = path; } /// Set the root directory - pub fn set_root(&mut self, dentry: Arc) { - self.root = dentry; + pub fn set_root(&mut self, path: Arc) { + self.root = path; } /// Open or create a file inode handler. - pub fn open(&self, path: &FsPath, flags: u32, mode: u16) -> Result { + pub fn open(&self, pathname: &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 +71,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 dentry = match self.lookup_inner(path, follow_tail_link) { - Ok(dentry) => { - let inode = dentry.inode(); + let path = match self.lookup_inner(pathname, follow_tail_link) { + Ok(path) => { + let inode = path.dentry().inode(); if inode.type_() == InodeType::SymLink && creation_flags.contains(CreationFlags::O_NOFOLLOW) && !status_flags.contains(StatusFlags::O_PATH) @@ -94,7 +93,7 @@ impl FsResolver { "O_DIRECTORY is specified but file is not a directory" ); } - dentry + path } Err(e) if e.error() == Errno::ENOENT @@ -103,50 +102,56 @@ impl FsResolver { if creation_flags.contains(CreationFlags::O_DIRECTORY) { return_errno_with_message!(Errno::ENOTDIR, "cannot create directory"); } - let (dir_dentry, file_name) = - self.lookup_dir_and_base_name_inner(path, follow_tail_link)?; + let (dir_path, file_name) = + self.lookup_dir_and_base_name_inner(pathname, follow_tail_link)?; if file_name.ends_with('/') { return_errno_with_message!(Errno::EISDIR, "path refers to a directory"); } - if !dir_dentry.mode()?.is_writable() { + if !dir_path.dentry().mode()?.is_writable() { return_errno_with_message!(Errno::EACCES, "file cannot be created"); } - dir_dentry.create(&file_name, InodeType::File, inode_mode)? + let dir_dentry = + dir_path + .dentry() + .create(&file_name, InodeType::File, inode_mode)?; + Path::new(dir_path.mount_node().clone(), dir_dentry.clone()) } Err(e) => return Err(e), }; - let inode_handle = InodeHandle::new(dentry, access_mode, status_flags)?; + let inode_handle = InodeHandle::new(path, access_mode, status_flags)?; Ok(inode_handle) } - /// Lookup dentry according to FsPath, always follow symlinks - pub fn lookup(&self, path: &FsPath) -> Result> { - self.lookup_inner(path, true) + /// Lookup path according to FsPath, always follow symlinks + pub fn lookup(&self, pathname: &FsPath) -> Result> { + self.lookup_inner(pathname, true) } - /// Lookup dentry according to FsPath, do not follow it if last component is a symlink - pub fn lookup_no_follow(&self, path: &FsPath) -> Result> { - self.lookup_inner(path, false) + /// Lookup path 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) } - fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result> { - let dentry = 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)? + fn lookup_inner(&self, pathname: &FsPath, follow_tail_link: bool) -> Result> { + let path = 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)? } FsPathInner::Cwd => self.cwd.clone(), - FsPathInner::FdRelative(fd, path) => { + FsPathInner::FdRelative(fd, pathname) => { let parent = self.lookup_from_fd(fd)?; - self.lookup_from_parent(&parent, path, follow_tail_link)? + self.lookup_from_parent(&parent, pathname, follow_tail_link)? } FsPathInner::Fd(fd) => self.lookup_from_fd(fd)?, }; - Ok(dentry) + Ok(path) } /// Lookup dentry from parent @@ -162,10 +167,10 @@ impl FsResolver { /// Symlinks in earlier components of the path will always be followed. fn lookup_from_parent( &self, - parent: &Arc, + parent: &Arc, relative_path: &str, follow_tail_link: bool, - ) -> Result> { + ) -> Result> { debug_assert!(!relative_path.starts_with('/')); if relative_path.len() > PATH_MAX { @@ -176,8 +181,8 @@ impl FsResolver { let mut link_path = String::new(); let mut follows = 0; - // Initialize the first dentry and the relative path - let (mut dentry, mut relative_path) = (parent.clone(), relative_path); + // Initialize the first path and the relative path + let (mut path, mut relative_path) = (parent.clone(), relative_path); while !relative_path.is_empty() { let (next_name, path_remain, must_be_dir) = @@ -189,7 +194,8 @@ impl FsResolver { }; // Iterate next dentry - let next_dentry = dentry.lookup(next_name)?; + let next_path = path.lookup(next_name)?; + let next_dentry = next_path.dentry(); let next_type = next_dentry.type_(); let next_is_tail = path_remain.is_empty(); @@ -212,9 +218,9 @@ impl FsResolver { tmp_link_path }; - // Change the dentry and relative path according to symlink + // Change the path and relative path according to symlink if link_path_remain.starts_with('/') { - dentry = self.root.clone(); + path = self.root.clone(); } link_path.clear(); link_path.push_str(link_path_remain.trim_start_matches('/')); @@ -225,12 +231,12 @@ impl FsResolver { if must_be_dir && next_type != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "inode is not dir"); } - dentry = next_dentry; + path = next_path; relative_path = path_remain; } } - Ok(dentry) + Ok(path) } /// Lookup dentry from the giving fd @@ -241,38 +247,38 @@ impl FsResolver { .get_file(fd)? .downcast_ref::() .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; - Ok(inode_handle.dentry().clone()) + Ok(inode_handle.path().clone()) } - /// Lookup the dir dentry and base file name of the giving path. + /// Lookup the dir path and base file name of the giving pathname. /// /// If the last component is a symlink, do not deference it - pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc, String)> { - self.lookup_dir_and_base_name_inner(path, false) + pub fn lookup_dir_and_base_name(&self, pathname: &FsPath) -> Result<(Arc, String)> { + self.lookup_dir_and_base_name_inner(pathname, false) } fn lookup_dir_and_base_name_inner( &self, - path: &FsPath, + pathname: &FsPath, follow_tail_link: bool, - ) -> Result<(Arc, String)> { - let (mut dir_dentry, mut base_name) = match path.inner { - FsPathInner::Absolute(path) => { - let (dir, file_name) = split_path(path); + ) -> Result<(Arc, String)> { + let (mut dir_path, mut base_name) = match pathname.inner { + FsPathInner::Absolute(pathname) => { + let (dir, file_name) = split_path(pathname); ( self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?, String::from(file_name), ) } - FsPathInner::CwdRelative(path) => { - let (dir, file_name) = split_path(path); + FsPathInner::CwdRelative(pathname) => { + let (dir, file_name) = split_path(pathname); ( self.lookup_from_parent(&self.cwd, dir, true)?, String::from(file_name), ) } - FsPathInner::FdRelative(fd, path) => { - let (dir, file_name) = split_path(path); + FsPathInner::FdRelative(fd, pathname) => { + let (dir, file_name) = split_path(pathname); let parent = self.lookup_from_fd(fd)?; ( self.lookup_from_parent(&parent, dir, true)?, @@ -282,15 +288,15 @@ impl FsResolver { _ => return_errno!(Errno::ENOENT), }; if !follow_tail_link { - return Ok((dir_dentry, base_name)); + return Ok((dir_path, base_name)); } // Dereference the tail symlinks if needed loop { - match dir_dentry.lookup(base_name.trim_end_matches('/')) { - Ok(dentry) if dentry.type_() == InodeType::SymLink => { + match dir_path.lookup(base_name.trim_end_matches('/')) { + Ok(path) if path.dentry().type_() == InodeType::SymLink => { let link = { - let mut link = dentry.inode().read_link()?; + let mut link = path.dentry().inode().read_link()?; if link.is_empty() { return_errno_with_message!(Errno::ENOENT, "invalid symlink"); } @@ -301,11 +307,11 @@ impl FsResolver { }; let (dir, file_name) = split_path(&link); if dir.starts_with('/') { - dir_dentry = + dir_path = self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?; base_name = String::from(file_name); } else { - dir_dentry = self.lookup_from_parent(&dir_dentry, dir, true)?; + dir_path = self.lookup_from_parent(&dir_path, dir, true)?; base_name = String::from(file_name); } } @@ -313,7 +319,7 @@ impl FsResolver { } } - Ok((dir_dentry, base_name)) + Ok((dir_path, base_name)) } } 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 83c40a4f1..497aef45a 100644 --- a/kernel/aster-nix/src/fs/inode_handle/dyn_cap.rs +++ b/kernel/aster-nix/src/fs/inode_handle/dyn_cap.rs @@ -8,11 +8,11 @@ use crate::prelude::*; impl InodeHandle { pub fn new( - dentry: Arc, + path: Arc, access_mode: AccessMode, status_flags: StatusFlags, ) -> Result { - let inode = dentry.inode(); + let inode = path.dentry().inode(); if access_mode.is_readable() && !inode.mode()?.is_readable() { return_errno_with_message!(Errno::EACCES, "File is not readable"); } @@ -30,7 +30,7 @@ impl InodeHandle { }; let inner = Arc::new(InodeHandle_ { - dentry, + path, file_io, offset: Mutex::new(0), access_mode, @@ -116,6 +116,6 @@ impl FileLike for InodeHandle { } fn as_device(&self) -> Option> { - self.dentry().inode().as_device() + self.0.path.dentry().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 9234053ce..f48b044c0 100644 --- a/kernel/aster-nix/src/fs/inode_handle/mod.rs +++ b/kernel/aster-nix/src/fs/inode_handle/mod.rs @@ -16,7 +16,7 @@ use crate::{ device::Device, file_handle::FileLike, utils::{ - AccessMode, Dentry, DirentVisitor, InodeMode, InodeType, IoctlCmd, Metadata, SeekFrom, + AccessMode, DirentVisitor, InodeMode, InodeType, IoctlCmd, Metadata, Path, SeekFrom, StatusFlags, }, }, @@ -28,7 +28,7 @@ use crate::{ pub struct InodeHandle(Arc, R); struct InodeHandle_ { - dentry: Arc, + path: Arc, /// `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`. @@ -47,9 +47,9 @@ impl InodeHandle_ { } let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentry.inode().read_direct_at(*offset, buf)? + self.path.dentry().inode().read_direct_at(*offset, buf)? } else { - self.dentry.inode().read_at(*offset, buf)? + self.path.dentry().inode().read_at(*offset, buf)? }; *offset += len; @@ -64,12 +64,12 @@ impl InodeHandle_ { } if self.status_flags().contains(StatusFlags::O_APPEND) { - *offset = self.dentry.size(); + *offset = self.path.dentry().size(); } let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentry.inode().write_direct_at(*offset, buf)? + self.path.dentry().inode().write_direct_at(*offset, buf)? } else { - self.dentry.inode().write_at(*offset, buf)? + self.path.dentry().inode().write_at(*offset, buf)? }; *offset += len; @@ -82,9 +82,9 @@ impl InodeHandle_ { } let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { - self.dentry.inode().read_direct_all(buf)? + self.path.dentry().inode().read_direct_all(buf)? } else { - self.dentry.inode().read_all(buf)? + self.path.dentry().inode().read_all(buf)? }; Ok(len) } @@ -99,7 +99,7 @@ impl InodeHandle_ { off as isize } SeekFrom::End(off /* as isize */) => { - let file_size = self.dentry.size() as isize; + let file_size = self.path.dentry().size() as isize; assert!(file_size >= 0); file_size .checked_add(off) @@ -127,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.dentry.resize(new_size) + self.path.dentry().resize(new_size) } pub fn access_mode(&self) -> AccessMode { @@ -146,7 +146,7 @@ impl InodeHandle_ { pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result { let mut offset = self.offset.lock(); - let read_cnt = self.dentry.inode().readdir_at(*offset, visitor)?; + let read_cnt = self.path.dentry().inode().readdir_at(*offset, visitor)?; *offset += read_cnt; Ok(read_cnt) } @@ -156,7 +156,7 @@ impl InodeHandle_ { return file_io.poll(mask, poller); } - self.dentry.inode().poll(mask, poller) + self.path.dentry().inode().poll(mask, poller) } fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result { @@ -164,11 +164,11 @@ impl InodeHandle_ { return file_io.ioctl(cmd, arg); } - self.dentry.inode().ioctl(cmd, arg) + self.path.dentry().inode().ioctl(cmd, arg) } } -#[inherit_methods(from = "self.dentry")] +#[inherit_methods(from = "self.path.dentry()")] impl InodeHandle_ { pub fn size(&self) -> usize; pub fn metadata(&self) -> Metadata; @@ -183,7 +183,7 @@ impl InodeHandle_ { impl Debug for InodeHandle_ { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("InodeHandle_") - .field("dentry", &self.dentry) + .field("path", &self.path) .field("offset", &self.offset()) .field("access_mode", &self.access_mode()) .field("status_flags", &self.status_flags()) @@ -193,8 +193,8 @@ impl Debug for InodeHandle_ { /// Methods for both dyn and static impl InodeHandle { - pub fn dentry(&self) -> &Arc { - &self.0.dentry + pub fn path(&self) -> &Arc { + &self.0.path } } diff --git a/kernel/aster-nix/src/fs/procfs/pid/fd.rs b/kernel/aster-nix/src/fs/procfs/pid/fd.rs index 2c2315625..47395103e 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 path = if let Some(inode_handle) = self.0.downcast_ref::() { - inode_handle.dentry().abs_path() + let pathname = if let Some(inode_handle) = self.0.downcast_ref::() { + inode_handle.path().abs_path() } else { // TODO: get the real path for other FileLike object String::from("/dev/tty") }; - Ok(path) + Ok(pathname) } } diff --git a/kernel/aster-nix/src/fs/rootfs.rs b/kernel/aster-nix/src/fs/rootfs.rs index 132251a97..41c30c7bd 100644 --- a/kernel/aster-nix/src/fs/rootfs.rs +++ b/kernel/aster-nix/src/fs/rootfs.rs @@ -54,14 +54,14 @@ 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.create(name, InodeType::File, mode)?; + let dentry = parent.dentry().create(name, InodeType::File, mode)?; entry.read_all(dentry.inode().writer(0))?; } FileType::Dir => { - let _ = parent.create(name, InodeType::Dir, mode)?; + let _ = parent.dentry().create(name, InodeType::Dir, mode)?; } FileType::Link => { - let dentry = parent.create(name, InodeType::SymLink, mode)?; + let dentry = parent.dentry().create(name, InodeType::SymLink, mode)?; let link_content = { let mut link_data: Vec = Vec::new(); entry.read_all(&mut link_data)?; @@ -75,11 +75,11 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> { } } // Mount ProcFS - let proc_dentry = fs.lookup(&FsPath::try_from("/proc")?)?; - proc_dentry.mount(ProcFS::new())?; + let proc_path = fs.lookup(&FsPath::try_from("/proc")?)?; + proc_path.mount(ProcFS::new())?; // Mount DevFS - let dev_dentry = fs.lookup(&FsPath::try_from("/dev")?)?; - dev_dentry.mount(RamFS::new())?; + let dev_path = fs.lookup(&FsPath::try_from("/dev")?)?; + dev_path.mount(RamFS::new())?; println!("[kernel] rootfs is ready"); @@ -87,8 +87,8 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> { } pub fn mount_fs_at(fs: Arc, fs_path: &FsPath) -> Result<()> { - let target_dentry = FsResolver::new().lookup(fs_path)?; - target_dentry.mount(fs)?; + let target_path = FsResolver::new().lookup(fs_path)?; + target_path.mount(fs)?; Ok(()) } diff --git a/kernel/aster-nix/src/fs/utils/dentry.rs b/kernel/aster-nix/src/fs/utils/dentry.rs index ae24b14cc..211b9ca60 100644 --- a/kernel/aster-nix/src/fs/utils/dentry.rs +++ b/kernel/aster-nix/src/fs/utils/dentry.rs @@ -7,7 +7,7 @@ use core::{ use inherit_methods_macro::inherit_methods; -use super::{FileSystem, Inode, InodeMode, InodeType, Metadata, MountNode, NAME_MAX}; +use super::{FileSystem, Inode, InodeMode, InodeType, Metadata}; use crate::{ fs::device::Device, prelude::*, @@ -24,7 +24,6 @@ pub struct Dentry { name_and_parent: RwLock)>>, this: Weak, children: Mutex, - mount_node: Weak, flags: AtomicU32, } @@ -34,20 +33,23 @@ impl Dentry { /// 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. - pub(super) fn new_root(inode: Arc, mount: Weak) -> Arc { - let root = Self::new(inode, DentryOptions::Root(mount)); + 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 { inode, - mount_node: match &options { - DentryOptions::Root(mount) => mount.clone(), - DentryOptions::Leaf(name_and_parent) => name_and_parent.1.mount_node.clone(), - }, flags: AtomicU32::new(DentryFlags::empty().bits()), name_and_parent: match options { DentryOptions::Leaf(name_and_parent) => RwLock::new(Some(name_and_parent)), @@ -58,69 +60,26 @@ impl Dentry { }) } - /// Get the overlaid dentry of self. - /// - /// It will jump into the child mount if it is a mountpoint. - fn overlaid_dentry(&self) -> Arc { - if !self.is_mountpoint() { - return self.this(); - } - match self.mount_node().get(self) { - Some(child_mount) => child_mount.root_dentry().overlaid_dentry(), - None => self.this(), - } - } - /// Get the name of dentry. /// /// Returns "/" if it is a root dentry. - fn name(&self) -> String { + pub fn name(&self) -> String { match self.name_and_parent.read().as_ref() { Some(name_and_parent) => name_and_parent.0.clone(), None => String::from("/"), } } - /// Get the effective name of dentry. - /// - /// 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.is_root_of_mount() { - return self.name(); - } - - match self.mount_node().mountpoint_dentry() { - Some(self_mountpoint) => self_mountpoint.effective_name(), - None => self.name(), - } - } - /// Get the parent. /// /// Returns None if it is root dentry. - fn parent(&self) -> Option> { + pub fn parent(&self) -> Option> { self.name_and_parent .read() .as_ref() .map(|name_and_parent| name_and_parent.1.clone()) } - /// Get the effective parent of dentry. - /// - /// 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.is_root_of_mount() { - return self.parent(); - } - - match self.mount_node().mountpoint_dentry() { - Some(self_mountpoint) => self_mountpoint.effective_parent(), - None => self.parent(), - } - } - fn set_name_and_parent(&self, name: &str, parent: Arc) { let mut name_and_parent = self.name_and_parent.write(); *name_and_parent = Some((String::from(name), parent)); @@ -147,30 +106,25 @@ impl Dentry { DentryFlags::from_bits(flags).unwrap() } - fn is_mountpoint(&self) -> bool { + pub fn is_mountpoint(&self) -> bool { self.flags().contains(DentryFlags::MOUNTED) } - fn set_mountpoint(&self) { + pub fn set_mountpoint(&self) { self.flags .fetch_or(DentryFlags::MOUNTED.bits(), Ordering::Release); } - fn clear_mountpoint(&self) { + pub 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. - fn is_root_of_mount(&self) -> bool { + pub fn is_root_of_mount(&self) -> bool { self.name_and_parent.read().as_ref().is_none() } - /// Get the mount node which the dentry belongs to. - pub fn mount_node(&self) -> Arc { - self.mount_node.upgrade().unwrap() - } - /// Create a dentry by making inode. pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { if self.inode.type_() != InodeType::Dir { @@ -193,6 +147,29 @@ impl Dentry { Ok(child) } + /// Lookup a dentry from DCACHE. + pub fn lookup_fast(&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> { + let mut children = self.children.lock(); + let inode = self.inode.lookup(name)?; + let dentry = Self::new( + inode, + DentryOptions::Leaf((String::from(name), self.this())), + ); + children.insert_dentry(&dentry); + Ok(dentry) + } + + pub 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> { if self.inode.type_() != InodeType::Dir { @@ -215,62 +192,6 @@ impl Dentry { Ok(child) } - /// Lookup a dentry. - pub fn lookup(&self, name: &str) -> Result> { - if self.inode.type_() != InodeType::Dir { - return_errno!(Errno::ENOTDIR); - } - if !self.inode.mode()?.is_executable() { - return_errno!(Errno::EACCES); - } - if name.len() > NAME_MAX { - return_errno!(Errno::ENAMETOOLONG); - } - - let dentry = match name { - "." => self.this(), - ".." => self.effective_parent().unwrap_or(self.this()), - name => { - let mut children = self.children.lock(); - match children.find_dentry(name) { - Some(dentry) => dentry.overlaid_dentry(), - None => { - let inode = self.inode.lookup(name)?; - let dentry = Self::new( - inode, - DentryOptions::Leaf((String::from(name), self.this())), - ); - children.insert_dentry(&dentry); - dentry - } - } - } - }; - Ok(dentry) - } - - /// Link a new name for the dentry by linking inode. - pub 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); - } - if !Arc::ptr_eq(&old.mount_node(), &self.mount_node()) { - return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); - } - 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<()> { if self.inode.type_() != InodeType::Dir { @@ -325,9 +246,6 @@ impl Dentry { } } else { // Self and new_dir are different Dentry - if !Arc::ptr_eq(&self.mount_node(), &new_dir.mount_node()) { - return_errno_with_message!(Errno::EXDEV, "cannot cross mount"); - } 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)?; @@ -346,72 +264,6 @@ impl Dentry { } Ok(()) } - - /// Mount the fs on this dentry. It will make this 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.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(); - 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.is_root_of_mount() { - return_errno_with_message!(Errno::EINVAL, "not mounted"); - } - - let mount_node = self.mount_node(); - let Some(mountpoint) = mount_node.mountpoint_dentry() else { - return_errno_with_message!(Errno::EINVAL, "cannot umount root mount"); - }; - - let child_mount = mountpoint.mount_node().umount(mountpoint)?; - mountpoint.clear_mountpoint(); - Ok(child_mount) - } - - /// Get the absolute path. - /// - /// It will resolve the mountpoint automatically. - pub fn abs_path(&self) -> String { - let mut path = self.effective_name(); - let mut dentry = self.this(); - - loop { - match dentry.effective_parent() { - None => break, - Some(parent_dentry) => { - path = { - let parent_name = parent_dentry.effective_name(); - if parent_name != "/" { - parent_name + "/" + &path - } else { - parent_name + &path - } - }; - dentry = parent_dentry; - } - } - } - - debug_assert!(path.starts_with('/')); - path - } } #[inherit_methods(from = "self.inode")] @@ -437,7 +289,6 @@ impl Dentry { impl Debug for Dentry { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("Dentry") - .field("abs_path", &self.abs_path()) .field("inode", &self.inode) .field("flags", &self.flags()) .finish() @@ -475,7 +326,7 @@ bitflags! { } enum DentryOptions { - Root(Weak), + Root, Leaf((String, Arc)), } diff --git a/kernel/aster-nix/src/fs/utils/mod.rs b/kernel/aster-nix/src/fs/utils/mod.rs index dcfdb837c..734d696f5 100644 --- a/kernel/aster-nix/src/fs/utils/mod.rs +++ b/kernel/aster-nix/src/fs/utils/mod.rs @@ -14,6 +14,7 @@ pub use inode::{Inode, InodeMode, InodeType, Metadata}; pub use ioctl::IoctlCmd; pub use mount::MountNode; pub use page_cache::{PageCache, PageCacheBackend}; +pub use path::Path; pub use random_test::{generate_random_operation, new_fs_in_memory}; pub use status_flags::StatusFlags; @@ -29,6 +30,7 @@ mod inode; mod ioctl; mod mount; mod page_cache; +mod path; mod random_test; mod status_flags; diff --git a/kernel/aster-nix/src/fs/utils/mount.rs b/kernel/aster-nix/src/fs/utils/mount.rs index 6007fcd8a..cc92269b9 100644 --- a/kernel/aster-nix/src/fs/utils/mount.rs +++ b/kernel/aster-nix/src/fs/utils/mount.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -use super::{Dentry, DentryKey, FileSystem, InodeType}; +use super::{Dentry, DentryKey, FileSystem, InodeType, Path}; use crate::prelude::*; /// The MountNode can form a mount tree to maintain the mount information. @@ -12,6 +12,8 @@ pub struct MountNode { mountpoint_dentry: Option>, /// The associated FS. fs: Arc, + /// The parent mount node. + parent: RwLock>>, /// Child mount nodes which are mounted on one dentry of self. children: Mutex>>, /// Reference to self. @@ -27,16 +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) + Self::new(fs, None, None) } /// The internal constructor. /// /// Root mount node has no mountpoint which other mount nodes must have mountpoint. - fn new(fs: Arc, mountpoint: Option>) -> Arc { + fn new( + fs: Arc, + mountpoint: Option>, + parent_mount: Option>, + ) -> Arc { Arc::new_cyclic(|weak_self| Self { - root_dentry: Dentry::new_root(fs.root_inode(), weak_self.clone()), + root_dentry: Dentry::new_root(fs.root_inode()), mountpoint_dentry: mountpoint, + parent: RwLock::new(parent_mount), children: Mutex::new(BTreeMap::new()), fs, this: weak_self.clone(), @@ -54,16 +61,20 @@ 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> { - if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) { + pub fn mount(&self, fs: Arc, mountpoint: &Arc) -> Result> { + if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) { return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this"); } - if mountpoint.type_() != InodeType::Dir { + if mountpoint.dentry().type_() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } - let key = mountpoint.key(); - let child_mount = Self::new(fs, Some(mountpoint.clone())); + let key = mountpoint.dentry().key(); + let child_mount = Self::new( + fs, + Some(mountpoint.dentry().clone()), + Some(Arc::downgrade(mountpoint.mount_node())), + ); self.children.lock().insert(key, child_mount.clone()); Ok(child_mount) } @@ -71,25 +82,28 @@ impl MountNode { /// Unmount a child mount node from the mountpoint and return it. /// /// The mountpoint should belong to this mount node, or an error is returned. - pub fn umount(&self, mountpoint: &Dentry) -> Result> { - if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) { + pub fn umount(&self, mountpoint: &Path) -> Result> { + if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) { return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this"); } let child_mount = self .children .lock() - .remove(&mountpoint.key()) + .remove(&mountpoint.dentry().key()) .ok_or_else(|| Error::with_message(Errno::ENOENT, "can not find child mount"))?; Ok(child_mount) } /// Try to get a child mount node from the mountpoint. - pub fn get(&self, mountpoint: &Dentry) -> Option> { - if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) { + pub fn get(&self, mountpoint: &Path) -> Option> { + if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) { return None; } - self.children.lock().get(&mountpoint.key()).cloned() + self.children + .lock() + .get(&mountpoint.dentry().key()) + .cloned() } /// Get the root dentry of this mount node. @@ -115,10 +129,13 @@ impl MountNode { } /// Try to get the parent mount node. - pub fn parent(&self) -> Option> { - self.mountpoint_dentry - .as_ref() - .map(|dentry| dentry.mount_node()) + pub fn parent(&self) -> Option> { + self.parent.read().as_ref().cloned() + } + + pub fn set_parent(&self, mount_node: Arc) { + let mut parent = self.parent.write(); + *parent = Some(Arc::downgrade(&mount_node)); } /// Get strong reference to self. diff --git a/kernel/aster-nix/src/fs/utils/path.rs b/kernel/aster-nix/src/fs/utils/path.rs new file mode 100644 index 000000000..8a247504e --- /dev/null +++ b/kernel/aster-nix/src/fs/utils/path.rs @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: MPL-2.0 + +use super::{Dentry, FileSystem, InodeType, MountNode, NAME_MAX}; +use crate::prelude::*; + +/// The Path can represent a location in the mount tree. +#[derive(Debug)] +pub struct Path { + mount_node: Arc, + dentry: Arc, + this: Weak, +} + +impl Path { + pub fn new(mount_node: Arc, dentry: Arc) -> Arc { + Arc::new_cyclic(|weak_self| Self { + mount_node, + dentry, + this: weak_self.clone(), + }) + } + + /// Lookup a path. + 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 path = 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) => Path::new(self.mount_node().clone(), dentry.clone()), + None => { + let slow_dentry = self.dentry.lookup_slow(name)?; + Path::new(self.mount_node().clone(), slow_dentry.clone()) + } + } + } + }; + let path = path.overlaid_path(); + Ok(path) + } + + // 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_path = self.this(); + + loop { + match dir_path.effective_parent() { + None => break, + Some(parent_dir_path) => { + path = { + let parent_name = parent_dir_path.effective_name(); + if parent_name != "/" { + parent_name + "/" + &path + } else { + parent_name + &path + } + }; + dir_path = parent_dir_path; + } + } + } + debug_assert!(path.starts_with('/')); + path + } + + /// Get the effective name of path. + /// + /// 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_path = Path::new( + self.mount_node.parent().unwrap().upgrade().unwrap().clone(), + self.mount_node.mountpoint_dentry().unwrap().clone(), + ); + parent_path.effective_name() + } else { + self.dentry.name() + } + } + + /// Get the effective parent of path. + /// + /// 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(Path::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_path = Path::new( + self.mount_node.parent().unwrap().upgrade().unwrap().clone(), + self.mount_node.mountpoint_dentry().unwrap().clone(), + ); + parent_path.effective_parent() + } else { + None + } + } + + /// Get the overlaid path of self. + /// + /// It will jump into the child mount if it is a mountpoint. + fn overlaid_path(&self) -> Arc { + if !self.dentry.is_mountpoint() { + return self.this(); + } + match self.mount_node.get(self) { + Some(child_mount) => { + Path::new(child_mount.clone(), child_mount.root_dentry().clone()).overlaid_path() + } + None => self.this(), + } + } + + /// Mount the fs on this path. It will make this path'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_path = Path::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone()); + + let child_mount = mountpoint_mount_node.umount(&mountpoint_path)?; + mountpoint_dentry.clear_mountpoint(); + Ok(child_mount) + } + + /// Link a new name for the path'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 path. + pub fn mount_node(&self) -> &Arc { + &self.mount_node + } + + /// Get the dentry of this path. + pub fn dentry(&self) -> &Arc { + &self.dentry + } +} diff --git a/kernel/aster-nix/src/lib.rs b/kernel/aster-nix/src/lib.rs index dc29a7efd..2fdfcf7da 100644 --- a/kernel/aster-nix/src/lib.rs +++ b/kernel/aster-nix/src/lib.rs @@ -112,7 +112,6 @@ fn init_thread() { karg.get_initproc_envp().to_vec(), ) .expect("Run init process failed."); - // Wait till initproc become zombie. while !initproc.is_zombie() { // We don't have preemptive scheduler now. diff --git a/kernel/aster-nix/src/net/socket/unix/addr.rs b/kernel/aster-nix/src/net/socket/unix/addr.rs index d8c705c66..675d2e4f8 100644 --- a/kernel/aster-nix/src/net/socket/unix/addr.rs +++ b/kernel/aster-nix/src/net/socket/unix/addr.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -use crate::{fs::utils::Dentry, net::socket::util::socket_addr::SocketAddr, prelude::*}; +use crate::{fs::utils::Path, net::socket::util::socket_addr::SocketAddr, prelude::*}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum UnixSocketAddr { @@ -10,7 +10,7 @@ pub enum UnixSocketAddr { #[derive(Clone)] pub(super) enum UnixSocketAddrBound { - Path(Arc), + Path(Arc), Abstract(String), } @@ -18,7 +18,9 @@ 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.inode(), r0.inode()), + (Self::Path(l0), Self::Path(r0)) => { + Arc::ptr_eq(l0.dentry().inode(), r0.dentry().inode()) + } _ => false, } } @@ -38,8 +40,8 @@ impl TryFrom for UnixSocketAddr { impl From for UnixSocketAddr { fn from(value: UnixSocketAddrBound) -> Self { match value { - UnixSocketAddrBound::Path(dentry) => { - let abs_path = dentry.abs_path(); + UnixSocketAddrBound::Path(path) => { + let abs_path = path.abs_path(); Self::Path(abs_path) } UnixSocketAddrBound::Abstract(name) => Self::Abstract(name), 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 038be98f9..fe6b1ce58 100644 --- a/kernel/aster-nix/src/net/socket/unix/stream/init.rs +++ b/kernel/aster-nix/src/net/socket/unix/stream/init.rs @@ -7,7 +7,7 @@ use crate::{ events::IoEvents, fs::{ fs_resolver::{split_path, FsPath}, - utils::{Dentry, InodeMode, InodeType}, + utils::{InodeMode, InodeType, Path}, }, net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound}, prelude::*, @@ -37,9 +37,9 @@ impl Init { let bound_addr = match addr_to_bind { UnixSocketAddr::Abstract(_) => todo!(), - UnixSocketAddr::Path(path) => { - let dentry = create_socket_file(path)?; - UnixSocketAddrBound::Path(dentry) + UnixSocketAddr::Path(pathname) => { + let path = create_socket_file(pathname)?; + UnixSocketAddrBound::Path(path) } }; @@ -87,18 +87,19 @@ impl Init { } } -fn create_socket_file(path: &str) -> Result> { - let (parent_pathname, file_name) = split_path(path); +fn create_socket_file(pathname: &str) -> Result> { + let (parent_pathname, file_name) = split_path(pathname); 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.create( + let dentry = parent.dentry().create( file_name, InodeType::Socket, InodeMode::S_IRUSR | InodeMode::S_IWUSR, )?; - Ok(dentry) + let path = Path::new(parent.mount_node().clone(), dentry.clone()); + Ok(path) } 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 67b106ca3..a2173a938 100644 --- a/kernel/aster-nix/src/net/socket/unix/stream/listener.rs +++ b/kernel/aster-nix/src/net/socket/unix/stream/listener.rs @@ -9,7 +9,7 @@ use crate::{ events::IoEvents, fs::{ file_handle::FileLike, - utils::{Dentry, Inode}, + utils::{Inode, Path}, }, net::socket::{ unix::addr::{UnixSocketAddr, UnixSocketAddrBound}, @@ -91,10 +91,10 @@ impl BacklogTable { fn add_backlog(&self, addr: &UnixSocketAddrBound, backlog: usize) -> Result<()> { let inode = { - let UnixSocketAddrBound::Path(dentry) = addr else { + let UnixSocketAddrBound::Path(path) = addr else { todo!() }; - create_keyable_inode(dentry) + create_keyable_inode(path) }; let mut backlog_sockets = self.backlog_sockets.write(); @@ -108,10 +108,10 @@ impl BacklogTable { fn get_backlog(&self, addr: &UnixSocketAddrBound) -> Result> { let inode = { - let UnixSocketAddrBound::Path(dentry) = addr else { + let UnixSocketAddrBound::Path(path) = addr else { todo!() }; - create_keyable_inode(dentry) + create_keyable_inode(path) }; let backlog_sockets = self.backlog_sockets.read(); @@ -212,8 +212,8 @@ impl Backlog { } } -fn create_keyable_inode(dentry: &Arc) -> KeyableWeak { - let weak_inode = Arc::downgrade(dentry.inode()); +fn create_keyable_inode(path: &Arc) -> KeyableWeak { + let weak_inode = Arc::downgrade(path.dentry().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 ef812d9d1..4632bd849 100644 --- a/kernel/aster-nix/src/net/socket/unix/stream/socket.rs +++ b/kernel/aster-nix/src/net/socket/unix/stream/socket.rs @@ -11,7 +11,7 @@ use crate::{ fs::{ file_handle::FileLike, fs_resolver::FsPath, - utils::{Dentry, InodeType, StatusFlags}, + utils::{InodeType, Path, StatusFlags}, }, net::socket::{ unix::{addr::UnixSocketAddrBound, UnixSocketAddr}, @@ -161,9 +161,9 @@ impl Socket for UnixStreamSocket { UnixSocketAddr::Abstract(abstract_name) => { UnixSocketAddrBound::Abstract(abstract_name) } - UnixSocketAddr::Path(path) => { - let dentry = lookup_socket_file(&path)?; - UnixSocketAddrBound::Path(dentry) + UnixSocketAddr::Path(pathname) => { + let path = lookup_socket_file(&pathname)?; + UnixSocketAddrBound::Path(path) } } }; @@ -287,20 +287,20 @@ impl Drop for UnixStreamSocket { } } -fn lookup_socket_file(path: &str) -> Result> { - let dentry = { +fn lookup_socket_file(pathname: &str) -> Result> { + let path = { let current = current!(); let fs = current.fs().read(); - let fs_path = FsPath::try_from(path)?; + let fs_path = FsPath::try_from(pathname)?; fs.lookup(&fs_path)? }; - if dentry.type_() != InodeType::Socket { + if path.dentry().type_() != InodeType::Socket { return_errno_with_message!(Errno::ENOTSOCK, "not a socket file") } - if !dentry.mode()?.is_readable() || !dentry.mode()?.is_writable() { + if !path.dentry().mode()?.is_readable() || !path.dentry().mode()?.is_writable() { return_errno_with_message!(Errno::EACCES, "the socket cannot be read or written") } - Ok(dentry) + Ok(path) } diff --git a/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs b/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs index f44ec0c1c..c3dd255dd 100644 --- a/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs +++ b/kernel/aster-nix/src/process/posix_thread/posix_thread_ext.rs @@ -41,7 +41,7 @@ impl PosixThreadExt for Thread { fs_resolver.lookup(&fs_path)? }; let (_, elf_load_info) = - load_program_to_vm(process_vm, elf_file, argv, envp, fs_resolver, 1)?; + load_program_to_vm(process_vm, elf_file.clone(), argv, envp, fs_resolver, 1)?; let vm_space = process_vm.root_vmar().vm_space().clone(); let mut cpu_ctx = UserContext::default(); 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 c3b4135b6..297debd4b 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, + utils::{Dentry, Path}, }, prelude::*, process::{ @@ -35,7 +35,7 @@ use crate::{ pub fn load_elf_to_vm( process_vm: &ProcessVm, file_header: &[u8], - elf_file: Arc, + elf_file: Arc, fs_resolver: &FsResolver, argv: Vec, envp: Vec, @@ -101,11 +101,11 @@ fn lookup_and_parse_ldso( }; let ldso_elf = { let mut buf = Box::new([0u8; PAGE_SIZE]); - let inode = ldso_file.inode(); + let inode = ldso_file.dentry().inode(); inode.read_at(0, &mut *buf)?; Elf::parse_elf(&*buf)? }; - Ok((ldso_file, ldso_elf)) + Ok((ldso_file.dentry().clone(), ldso_elf)) } fn load_ldso(root_vmar: &Vmar, ldso_file: &Dentry, ldso_elf: &Elf) -> Result { diff --git a/kernel/aster-nix/src/process/program_loader/mod.rs b/kernel/aster-nix/src/process/program_loader/mod.rs index ecfee504a..33995b79b 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, + utils::{Dentry, Path}, }, prelude::*, }; @@ -25,14 +25,14 @@ 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: Arc, argv: Vec, envp: Vec, fs_resolver: &FsResolver, recursion_limit: usize, ) -> Result<(String, ElfLoadInfo)> { let abs_path = elf_file.abs_path(); - let inode = elf_file.inode(); + let inode = elf_file.dentry().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)?; + check_executable_file(interpreter.dentry())?; return load_program_to_vm( process_vm, interpreter, diff --git a/kernel/aster-nix/src/syscall/chdir.rs b/kernel/aster-nix/src/syscall/chdir.rs index 4f52cc403..064c2e549 100644 --- a/kernel/aster-nix/src/syscall/chdir.rs +++ b/kernel/aster-nix/src/syscall/chdir.rs @@ -16,7 +16,7 @@ pub fn sys_chdir(pathname_addr: Vaddr) -> Result { let current = current!(); let mut fs = current.fs().write(); - let dentry = { + let path = { let pathname = pathname.to_string_lossy(); if pathname.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); @@ -24,10 +24,10 @@ pub fn sys_chdir(pathname_addr: Vaddr) -> Result { let fs_path = FsPath::try_from(pathname.as_ref())?; fs.lookup(&fs_path)? }; - if dentry.type_() != InodeType::Dir { + if path.dentry().type_() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "must be directory"); } - fs.set_cwd(dentry); + fs.set_cwd(path); Ok(SyscallReturn::Return(0)) } @@ -36,17 +36,17 @@ pub fn sys_fchdir(fd: FileDesc) -> Result { debug!("fd = {}", fd); let current = current!(); - let dentry = { + let path = { 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::EBADF, "not inode"))?; - inode_handle.dentry().clone() + inode_handle.path().clone() }; - if dentry.type_() != InodeType::Dir { + if path.dentry().type_() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "must be directory"); } - current.fs().write().set_cwd(dentry); + current.fs().write().set_cwd(path); Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/chmod.rs b/kernel/aster-nix/src/syscall/chmod.rs index fccbeebe5..8e2c18c5b 100644 --- a/kernel/aster-nix/src/syscall/chmod.rs +++ b/kernel/aster-nix/src/syscall/chmod.rs @@ -35,18 +35,22 @@ pub fn sys_fchmodat( /* flags: u32, */ ) -> Result { log_syscall_entry!(SYS_FCHMODAT); - let path = read_cstring_from_user(path_ptr, PATH_MAX)?; - debug!("dirfd = {}, path = {:?}, mode = 0o{:o}", dirfd, path, mode,); + let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?; + debug!( + "dirfd = {}, path = {:?}, mode = 0o{:o}", + dirfd, pathname, mode, + ); let current = current!(); - let dentry = { - let path = path.to_string_lossy(); - if path.is_empty() { + let path = { + let pathname = pathname.to_string_lossy(); + if pathname.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::new(dirfd, path.as_ref())?; + let fs_path = FsPath::new(dirfd, pathname.as_ref())?; current.fs().read().lookup(&fs_path)? }; - dentry.set_mode(InodeMode::from_bits_truncate(mode))?; + path.dentry() + .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 a01425bf3..d1c4d2cf4 100644 --- a/kernel/aster-nix/src/syscall/chown.rs +++ b/kernel/aster-nix/src/syscall/chown.rs @@ -57,15 +57,15 @@ pub fn sys_fchownat( flags: u32, ) -> Result { log_syscall_entry!(SYS_FCHOWNAT); - let path = read_cstring_from_user(path_ptr, PATH_MAX)?; + let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?; let flags = ChownFlags::from_bits(flags) .ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid flags"))?; debug!( "dirfd = {}, path = {:?}, uid = {}, gid = {}, flags = {:?}", - dirfd, path, uid, gid, flags + dirfd, pathname, uid, gid, flags ); - if path.is_empty() { + if pathname.is_empty() { if !flags.contains(ChownFlags::AT_EMPTY_PATH) { return_errno_with_message!(Errno::ENOENT, "path is empty"); } @@ -79,9 +79,9 @@ pub fn sys_fchownat( } let current = current!(); - let dentry = { - let path = path.to_string_lossy(); - let fs_path = FsPath::new(dirfd, path.as_ref())?; + let path = { + let pathname = pathname.to_string_lossy(); + let fs_path = FsPath::new(dirfd, pathname.as_ref())?; let fs = current.fs().read(); if flags.contains(ChownFlags::AT_SYMLINK_NOFOLLOW) { fs.lookup_no_follow(&fs_path)? @@ -90,10 +90,10 @@ pub fn sys_fchownat( } }; if let Some(uid) = uid { - dentry.set_owner(uid)?; + path.dentry().set_owner(uid)?; } if let Some(gid) = gid { - dentry.set_group(gid)?; + path.dentry().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 d5ad8384b..425d586c5 100644 --- a/kernel/aster-nix/src/syscall/chroot.rs +++ b/kernel/aster-nix/src/syscall/chroot.rs @@ -16,7 +16,7 @@ pub fn sys_chroot(pathname_addr: Vaddr) -> Result { let current = current!(); let mut fs = current.fs().write(); - let dentry = { + let path = { let pathname = pathname.to_string_lossy(); if pathname.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); @@ -24,9 +24,9 @@ pub fn sys_chroot(pathname_addr: Vaddr) -> Result { let fs_path = FsPath::try_from(pathname.as_ref())?; fs.lookup(&fs_path)? }; - if dentry.type_() != InodeType::Dir { + if path.dentry().type_() != InodeType::Dir { return_errno_with_message!(Errno::ENOTDIR, "must be directory"); } - fs.set_root(dentry); + fs.set_root(path); Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/execve.rs b/kernel/aster-nix/src/syscall/execve.rs index 6d028f1ea..c542e093e 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, InodeType}, + utils::{Dentry, InodeType, Path}, }, log_syscall_entry, prelude::*, @@ -61,29 +61,29 @@ fn lookup_executable_file( dfd: FileDesc, filename: String, flags: OpenFlags, -) -> Result> { +) -> Result> { let current = current!(); let fs_resolver = current.fs().read(); - let dentry = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() { + let path = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() { fs_resolver.lookup_from_fd(dfd) } else { let fs_path = FsPath::new(dfd, &filename)?; if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) { - let dentry = fs_resolver.lookup_no_follow(&fs_path)?; - if dentry.type_() == InodeType::SymLink { + let path = fs_resolver.lookup_no_follow(&fs_path)?; + if path.dentry().type_() == InodeType::SymLink { return_errno_with_message!(Errno::ELOOP, "the executable file is a symlink"); } - Ok(dentry) + Ok(path) } else { fs_resolver.lookup(&fs_path) } }?; - check_executable_file(&dentry)?; - Ok(dentry) + check_executable_file(path.dentry())?; + Ok(path) } fn do_execve( - elf_file: Arc, + elf_file: Arc, argv_ptr_ptr: Vaddr, envp_ptr_ptr: Vaddr, context: &mut UserContext, @@ -121,8 +121,8 @@ fn do_execve( debug!("load elf in execve succeeds"); let credentials = credentials_mut(); - set_uid_from_elf(&credentials, &elf_file)?; - set_gid_from_elf(&credentials, &elf_file)?; + set_uid_from_elf(&credentials, elf_file.dentry())?; + set_gid_from_elf(&credentials, elf_file.dentry())?; // set executable path current.set_executable_path(new_executable_path); diff --git a/kernel/aster-nix/src/syscall/fsync.rs b/kernel/aster-nix/src/syscall/fsync.rs index 2e657f46b..5b3339d1e 100644 --- a/kernel/aster-nix/src/syscall/fsync.rs +++ b/kernel/aster-nix/src/syscall/fsync.rs @@ -18,7 +18,7 @@ pub fn sys_fsync(fd: FileDesc) -> Result { let inode_handle = file .downcast_ref::() .ok_or(Error::with_message(Errno::EINVAL, "not inode"))?; - inode_handle.dentry().clone() + inode_handle.path().dentry().clone() }; dentry.sync()?; Ok(SyscallReturn::Return(0)) diff --git a/kernel/aster-nix/src/syscall/getdents64.rs b/kernel/aster-nix/src/syscall/getdents64.rs index 0772678b2..3c4810157 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.dentry().type_() != InodeType::Dir { + if inode_handle.path().dentry().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 c53da44c0..326b6a9cb 100644 --- a/kernel/aster-nix/src/syscall/link.rs +++ b/kernel/aster-nix/src/syscall/link.rs @@ -30,7 +30,7 @@ pub fn sys_linkat( ); let current = current!(); - let (old_dentry, new_dir_dentry, new_name) = { + let (old_path, new_dir_path, new_name) = { let old_pathname = old_pathname.to_string_lossy(); if old_pathname.ends_with('/') { return_errno_with_message!(Errno::EPERM, "oldpath is dir"); @@ -46,15 +46,15 @@ pub fn sys_linkat( 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 fs = current.fs().read(); - let old_dentry = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) { + let old_path = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) { fs.lookup(&old_fs_path)? } else { fs.lookup_no_follow(&old_fs_path)? }; - let (new_dir_dentry, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?; - (old_dentry, new_dir_dentry, new_name) + let (new_dir_path, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?; + (old_path, new_dir_path, new_name) }; - new_dir_dentry.link(&old_dentry, &new_name)?; + new_dir_path.link(&old_path, &new_name)?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/mkdir.rs b/kernel/aster-nix/src/syscall/mkdir.rs index 461af7f33..18b083fb4 100644 --- a/kernel/aster-nix/src/syscall/mkdir.rs +++ b/kernel/aster-nix/src/syscall/mkdir.rs @@ -22,7 +22,7 @@ pub fn sys_mkdirat(dirfd: FileDesc, pathname_addr: Vaddr, mode: u16) -> Result Result Result Result Result { log_syscall_entry!(SYS_STATFS); - let path = read_cstring_from_user(path_ptr, PATH_MAX)?; - debug!("path = {:?}, statfs_buf_ptr = 0x{:x}", path, statfs_buf_ptr,); + let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?; + debug!( + "pathname = {:?}, statfs_buf_ptr = 0x{:x}", + pathname, statfs_buf_ptr, + ); let current = current!(); - let dentry = { - let path = path.to_string_lossy(); - let fs_path = FsPath::try_from(path.as_ref())?; + let path = { + let pathname = pathname.to_string_lossy(); + let fs_path = FsPath::try_from(pathname.as_ref())?; current.fs().read().lookup(&fs_path)? }; - let statfs = Statfs::from(dentry.fs().sb()); + let statfs = Statfs::from(path.dentry().fs().sb()); write_val_to_user(statfs_buf_ptr, &statfs)?; Ok(SyscallReturn::Return(0)) } @@ -39,7 +42,7 @@ 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.dentry(); + let dentry = inode_handle.path().dentry(); let statfs = Statfs::from(dentry.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 987bbcbf8..c65a96ad8 100644 --- a/kernel/aster-nix/src/syscall/symlink.rs +++ b/kernel/aster-nix/src/syscall/symlink.rs @@ -31,7 +31,7 @@ pub fn sys_symlinkat( if target.is_empty() { return_errno_with_message!(Errno::ENOENT, "target is empty"); } - let (dir_dentry, link_name) = { + let (dir_path, link_name) = { let linkpath = linkpath.to_string_lossy(); if linkpath.is_empty() { return_errno_with_message!(Errno::ENOENT, "linkpath is empty"); @@ -43,7 +43,7 @@ pub fn sys_symlinkat( current.fs().read().lookup_dir_and_base_name(&fs_path)? }; - let new_dentry = dir_dentry.create( + let new_dentry = dir_path.dentry().create( &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 0c1e68336..4ee0c2cfa 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 path = read_cstring_from_user(path_ptr, PATH_MAX)?; - debug!("path = {:?}, length = {}", path, len); + let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?; + debug!("pathname = {:?}, length = {}", pathname, len); check_length(len)?; let current = current!(); - let dentry = { - let path = path.to_string_lossy(); - if path.is_empty() { + let path = { + let pathname = pathname.to_string_lossy(); + if pathname.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); } - let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?; + let fs_path = FsPath::new(AT_FDCWD, pathname.as_ref())?; current.fs().read().lookup(&fs_path)? }; - dentry.resize(len as usize)?; + path.dentry().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 4eb4f99d8..0dd2ec35f 100644 --- a/kernel/aster-nix/src/syscall/unlink.rs +++ b/kernel/aster-nix/src/syscall/unlink.rs @@ -24,7 +24,7 @@ pub fn sys_unlinkat(dirfd: FileDesc, pathname_addr: Vaddr, flags: u32) -> Result debug!("dirfd = {}, pathname = {:?}", dirfd, pathname); let current = current!(); - let (dir_dentry, name) = { + let (dir_path, name) = { let pathname = pathname.to_string_lossy(); if pathname.is_empty() { return_errno_with_message!(Errno::ENOENT, "path is empty"); @@ -35,7 +35,7 @@ pub fn sys_unlinkat(dirfd: FileDesc, pathname_addr: Vaddr, flags: u32) -> Result let fs_path = FsPath::new(dirfd, pathname.as_ref())?; current.fs().read().lookup_dir_and_base_name(&fs_path)? }; - dir_dentry.unlink(&name)?; + dir_path.dentry().unlink(&name)?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/utimens.rs b/kernel/aster-nix/src/syscall/utimens.rs index e92a4212f..dc917d4c5 100644 --- a/kernel/aster-nix/src/syscall/utimens.rs +++ b/kernel/aster-nix/src/syscall/utimens.rs @@ -61,7 +61,7 @@ pub fn sys_utimensat( return Ok(SyscallReturn::Return(0)); } let current = current!(); - let dentry = { + let path = { let pathname = pathname.to_string_lossy(); if pathname.is_empty() { return_errno_with_message!(Errno::ENOENT, "pathname is empty"); @@ -75,10 +75,10 @@ pub fn sys_utimensat( } }; if let Some(time) = atime { - dentry.set_atime(Duration::from(time)); + path.dentry().set_atime(Duration::from(time)); } if let Some(time) = mtime { - dentry.set_mtime(Duration::from(time)); + path.dentry().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 077c2e593..6905284e3 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.inode().page_cache().unwrap() + vdso_lib.dentry().inode().page_cache().unwrap() }; let mut vdso_text = Box::new([0u8; PAGE_SIZE]); vdso_lib_vmo.read_bytes(0, &mut *vdso_text).unwrap();