Refactor Dentry to optimize the vfs layer

This commit is contained in:
Shaowei Song
2024-10-10 12:51:26 +00:00
committed by Tate, Hongliang Tian
parent 271e893889
commit ea489252f4
14 changed files with 177 additions and 175 deletions

View File

@ -16,7 +16,7 @@ mod pty;
pub use pty::{PtyMaster, PtySlave};
use spin::Once;
static DEV_PTS: Once<Arc<Dentry>> = Once::new();
static DEV_PTS: Once<Dentry> = Once::new();
pub fn init() -> Result<()> {
let fs = FsResolver::new();

View File

@ -91,7 +91,7 @@ impl From<u64> for DeviceId {
///
/// If the parent path is not existing, `mkdir -p` the parent path.
/// This function is used in registering device.
pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<Dentry>> {
pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Dentry> {
let mut dentry = {
let fs_resolver = FsResolver::new();
fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())?

View File

@ -17,8 +17,8 @@ pub const AT_FDCWD: FileDesc = -100;
/// File system resolver.
#[derive(Debug, Clone)]
pub struct FsResolver {
root: Arc<Dentry>,
cwd: Arc<Dentry>,
root: Dentry,
cwd: Dentry,
}
impl FsResolver {
@ -31,22 +31,22 @@ impl FsResolver {
}
/// Gets the root directory.
pub fn root(&self) -> &Arc<Dentry> {
pub fn root(&self) -> &Dentry {
&self.root
}
/// Gets the current working directory.
pub fn cwd(&self) -> &Arc<Dentry> {
pub fn cwd(&self) -> &Dentry {
&self.cwd
}
/// Sets the current working directory to the given `dentry`.
pub fn set_cwd(&mut self, dentry: Arc<Dentry>) {
pub fn set_cwd(&mut self, dentry: Dentry) {
self.cwd = dentry;
}
/// Sets the root directory to the given `dentry`.
pub fn set_root(&mut self, dentry: Arc<Dentry>) {
pub fn set_root(&mut self, dentry: Dentry) {
self.root = dentry;
}
@ -76,7 +76,7 @@ impl FsResolver {
fn open_existing_file(
&self,
target_dentry: Arc<Dentry>,
target_dentry: Dentry,
open_args: &OpenArgs,
) -> Result<InodeHandle> {
let inode = target_dentry.inode();
@ -147,19 +147,19 @@ impl FsResolver {
/// Lookups the target dentry according to the `path`.
/// Symlinks are always followed.
pub fn lookup(&self, path: &FsPath) -> Result<Arc<Dentry>> {
pub fn lookup(&self, path: &FsPath) -> Result<Dentry> {
let (follow_tail_link, stop_on_parent) = (true, false);
self.lookup_inner(path, &mut LookupCtx::new(follow_tail_link, stop_on_parent))
}
/// Lookups the target dentry according to the `path`.
/// If the last component is a symlink, it will not be followed.
pub fn lookup_no_follow(&self, path: &FsPath) -> Result<Arc<Dentry>> {
pub fn lookup_no_follow(&self, path: &FsPath) -> Result<Dentry> {
let (follow_tail_link, stop_on_parent) = (false, false);
self.lookup_inner(path, &mut LookupCtx::new(follow_tail_link, stop_on_parent))
}
fn lookup_inner(&self, path: &FsPath, lookup_ctx: &mut LookupCtx) -> Result<Arc<Dentry>> {
fn lookup_inner(&self, path: &FsPath, lookup_ctx: &mut LookupCtx) -> Result<Dentry> {
let dentry = match path.inner {
FsPathInner::Absolute(path) => {
self.lookup_from_parent(&self.root, path.trim_start_matches('/'), lookup_ctx)?
@ -192,10 +192,10 @@ impl FsResolver {
#[allow(clippy::redundant_closure)]
fn lookup_from_parent(
&self,
parent: &Arc<Dentry>,
parent: &Dentry,
relative_path: &str,
lookup_ctx: &mut LookupCtx,
) -> Result<Arc<Dentry>> {
) -> Result<Dentry> {
debug_assert!(!relative_path.starts_with('/'));
if relative_path.len() > PATH_MAX {
@ -285,7 +285,7 @@ impl FsResolver {
}
/// Lookups the target dentry according to the given `fd`.
pub fn lookup_from_fd(&self, fd: FileDesc) -> Result<Arc<Dentry>> {
pub fn lookup_from_fd(&self, fd: FileDesc) -> Result<Dentry> {
let current = current!();
let file_table = current.file_table().lock();
let inode_handle = file_table
@ -299,7 +299,7 @@ impl FsResolver {
/// the base file name according to the given `path`.
///
/// If the last component is a symlink, do not deference it.
pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc<Dentry>, String)> {
pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Dentry, String)> {
if matches!(path.inner, FsPathInner::Fd(_)) {
return_errno!(Errno::ENOENT);
}
@ -327,7 +327,7 @@ impl FsResolver {
&self,
path: &FsPath,
is_dir: bool,
) -> Result<(Arc<Dentry>, String)> {
) -> Result<(Dentry, String)> {
if matches!(path.inner, FsPathInner::Fd(_)) {
return_errno!(Errno::ENOENT);
}
@ -364,7 +364,7 @@ struct LookupCtx {
stop_on_parent: bool,
// (file_name, file_is_dir)
tail_file: Option<(String, bool)>,
parent: Option<Arc<Dentry>>,
parent: Option<Dentry>,
}
impl LookupCtx {
@ -394,7 +394,7 @@ impl LookupCtx {
.unwrap_or(false)
}
pub fn parent(&self) -> Option<&Arc<Dentry>> {
pub fn parent(&self) -> Option<&Dentry> {
self.parent.as_ref()
}
@ -402,7 +402,7 @@ impl LookupCtx {
let _ = self.tail_file.insert((file_name.to_string(), file_is_dir));
}
pub fn set_parent(&mut self, parent: &Arc<Dentry>) {
pub fn set_parent(&mut self, parent: &Dentry) {
let _ = self.parent.insert(parent.clone());
}
}

View File

@ -7,11 +7,7 @@ use super::*;
use crate::{prelude::*, process::signal::Pollable};
impl InodeHandle<Rights> {
pub fn new(
dentry: Arc<Dentry>,
access_mode: AccessMode,
status_flags: StatusFlags,
) -> Result<Self> {
pub fn new(dentry: Dentry, access_mode: AccessMode, status_flags: StatusFlags) -> Result<Self> {
let inode_mode = dentry.inode().mode()?;
if access_mode.is_readable() && !inode_mode.is_readable() {
return_errno_with_message!(Errno::EACCES, "file is not readable");
@ -24,7 +20,7 @@ impl InodeHandle<Rights> {
}
pub fn new_unchecked_access(
dentry: Arc<Dentry>,
dentry: Dentry,
access_mode: AccessMode,
status_flags: StatusFlags,
) -> Result<Self> {

View File

@ -32,7 +32,7 @@ use crate::{
pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
struct InodeHandle_ {
dentry: Arc<Dentry>,
dentry: Dentry,
/// `file_io` is Similar to `file_private` field in `file` structure in linux. If
/// `file_io` is Some, typical file operations including `read`, `write`, `poll`,
/// `ioctl` will be provided by `file_io`, instead of `dentry`.
@ -354,7 +354,7 @@ impl Debug for InodeHandle_ {
/// Methods for both dyn and static
impl<R> InodeHandle<R> {
pub fn dentry(&self) -> &Arc<Dentry> {
pub fn dentry(&self) -> &Dentry {
&self.0.dentry
}

View File

@ -22,21 +22,20 @@ use crate::{
};
/// A `Dentry` is used to represent a location in the mount tree.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Dentry {
mount_node: Arc<MountNode>,
inner: Arc<Dentry_>,
this: Weak<Dentry>,
}
/// The inner structure of `Dentry` for caching helpful nodes
/// to accelerate the path lookup.
pub struct Dentry_ {
inode: Arc<dyn Inode>,
name_and_parent: RwMutex<Option<(String, Arc<Dentry_>)>>,
this: Weak<Dentry_>,
name_and_parent: RwLock<Option<(String, Arc<Dentry_>)>>,
children: RwMutex<Children>,
flags: AtomicU32,
this: Weak<Dentry_>,
}
impl Dentry_ {
@ -53,8 +52,8 @@ impl Dentry_ {
inode,
flags: AtomicU32::new(DentryFlags::empty().bits()),
name_and_parent: match options {
DentryOptions::Leaf(name_and_parent) => RwMutex::new(Some(name_and_parent)),
_ => RwMutex::new(None),
DentryOptions::Leaf(name_and_parent) => RwLock::new(Some(name_and_parent)),
_ => RwLock::new(None),
},
this: weak_self.clone(),
children: RwMutex::new(Children::new()),
@ -139,129 +138,116 @@ impl Dentry_ {
/// Creates a `Dentry_` by creating a new inode of the `type_` with the `mode`.
pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
if self.inode.type_() != InodeType::Dir {
if self.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let children = self.children.upread();
if children.find_dentry(name).is_some() {
if children.contains(name) {
return_errno!(Errno::EEXIST);
}
let child = {
let inode = self.inode.create(name, type_, mode)?;
let dentry = Self::new(
inode,
DentryOptions::Leaf((String::from(name), self.this())),
);
let new_inode = self.inode.create(name, type_, mode)?;
let name = String::from(name);
let new_child = Dentry_::new(new_inode, DentryOptions::Leaf((name.clone(), self.this())));
let mut children = children.upgrade();
children.insert_dentry(&dentry);
dentry
};
Ok(child)
children.insert(name, new_child.clone());
Ok(new_child)
}
/// Lookups a target `Dentry_` from the cache in children.
pub fn lookup_via_cache(&self, name: &str) -> Option<Arc<Dentry_>> {
let children = self.children.read();
children.find_dentry(name)
children.find(name)
}
/// Lookups a target `Dentry_` from the file system.
pub fn lookup_via_fs(&self, name: &str) -> Result<Arc<Dentry_>> {
let children = self.children.upread();
let inode = self.inode.lookup(name)?;
let inner = Self::new(
inode,
DentryOptions::Leaf((String::from(name), self.this())),
);
let name = String::from(name);
let target = Self::new(inode, DentryOptions::Leaf((name.clone(), self.this())));
let mut children = children.upgrade();
children.insert_dentry(&inner);
Ok(inner)
}
fn insert_dentry(&self, child_dentry: &Arc<Dentry_>) {
let mut children = self.children.write();
children.insert_dentry(child_dentry);
children.insert(name, target.clone());
Ok(target)
}
/// Creates a `Dentry_` by making an inode of the `type_` with the `mode`.
pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result<Arc<Self>> {
if self.inode.type_() != InodeType::Dir {
if self.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let children = self.children.upread();
if children.find_dentry(name).is_some() {
if children.contains(name) {
return_errno!(Errno::EEXIST);
}
let child = {
let inode = self.inode.mknod(name, mode, type_)?;
let dentry = Self::new(
inode,
DentryOptions::Leaf((String::from(name), self.this())),
);
let name = String::from(name);
let new_child = Dentry_::new(inode, DentryOptions::Leaf((name.clone(), self.this())));
let mut children = children.upgrade();
children.insert_dentry(&dentry);
dentry
};
Ok(child)
children.insert(name, new_child.clone());
Ok(new_child)
}
/// Links a new name for the `Dentry_` by `link()` the inner inode.
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
if self.inode.type_() != InodeType::Dir {
if self.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let children = self.children.upread();
if children.find_dentry(name).is_some() {
if children.contains(name) {
return_errno!(Errno::EEXIST);
}
let old_inode = old.inode();
self.inode.link(old_inode, name)?;
let dentry = Self::new(
let name = String::from(name);
let dentry = Dentry_::new(
old_inode.clone(),
DentryOptions::Leaf((String::from(name), self.this())),
DentryOptions::Leaf((name.clone(), self.this())),
);
let mut children = children.upgrade();
children.insert_dentry(&dentry);
children.insert(name, dentry);
Ok(())
}
/// Deletes a `Dentry_` by `unlink()` the inner inode.
pub fn unlink(&self, name: &str) -> Result<()> {
if self.inode.type_() != InodeType::Dir {
if self.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let children = self.children.upread();
let _ = children.find_dentry_with_checking_mountpoint(name)?;
children.check_mountpoint(name)?;
self.inode.unlink(name)?;
let mut children = children.upgrade();
children.delete_dentry(name);
children.delete(name);
Ok(())
}
/// Deletes a directory `Dentry_` by `rmdir()` the inner inode.
pub fn rmdir(&self, name: &str) -> Result<()> {
if self.inode.type_() != InodeType::Dir {
if self.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let children = self.children.upread();
let _ = children.find_dentry_with_checking_mountpoint(name)?;
children.check_mountpoint(name)?;
self.inode.rmdir(name)?;
let mut children = children.upgrade();
children.delete_dentry(name);
children.delete(name);
Ok(())
}
@ -270,7 +256,7 @@ impl Dentry_ {
if old_name == "." || old_name == ".." || new_name == "." || new_name == ".." {
return_errno_with_message!(Errno::EISDIR, "old_name or new_name is a directory");
}
if self.inode.type_() != InodeType::Dir || new_dir.inode.type_() != InodeType::Dir {
if self.type_() != InodeType::Dir || new_dir.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
@ -281,37 +267,38 @@ impl Dentry_ {
}
let children = self.children.upread();
let old_dentry = children.find_dentry_with_checking_mountpoint(old_name)?;
let _ = children.find_dentry_with_checking_mountpoint(new_name)?;
let old_dentry = children.check_mountpoint_then_find(old_name)?;
children.check_mountpoint(new_name)?;
self.inode.rename(old_name, &self.inode, new_name)?;
let mut children = children.upgrade();
match old_dentry.as_ref() {
Some(dentry) => {
children.delete_dentry(old_name);
children.delete(old_name);
dentry.set_name_and_parent(new_name, self.this());
children.insert_dentry(dentry);
children.insert(new_name.to_string(), dentry.clone());
}
None => {
children.delete_dentry(new_name);
children.delete(new_name);
}
}
} else {
// The two are different dentries
let (mut self_children, mut new_dir_children) =
write_lock_children_on_two_dentries(self, new_dir);
let old_dentry = self_children.find_dentry_with_checking_mountpoint(old_name)?;
let _ = new_dir_children.find_dentry_with_checking_mountpoint(new_name)?;
let old_dentry = self_children.check_mountpoint_then_find(old_name)?;
new_dir_children.check_mountpoint(new_name)?;
self.inode.rename(old_name, &new_dir.inode, new_name)?;
match old_dentry.as_ref() {
Some(dentry) => {
self_children.delete_dentry(old_name);
self_children.delete(old_name);
dentry.set_name_and_parent(new_name, new_dir.this());
new_dir_children.insert_dentry(dentry);
new_dir_children.insert(new_name.to_string(), dentry.clone());
}
None => {
new_dir_children.delete_dentry(new_name);
new_dir_children.delete(new_name);
}
}
}
@ -387,41 +374,60 @@ enum DentryOptions {
}
struct Children {
inner: HashMap<String, Arc<Dentry_>>,
dentries: HashMap<String, Arc<Dentry_>>,
}
impl Children {
pub fn new() -> Self {
Self {
inner: HashMap::new(),
dentries: HashMap::new(),
}
}
pub fn insert_dentry(&mut self, dentry: &Arc<Dentry_>) {
pub fn len(&self) -> usize {
self.dentries.len()
}
pub fn contains(&self, name: &str) -> bool {
self.dentries.contains_key(name)
}
pub fn find(&self, name: &str) -> Option<Arc<Dentry_>> {
self.dentries.get(name).cloned()
}
pub fn insert(&mut self, name: String, dentry: Arc<Dentry_>) {
// Do not cache it in the children if is not cacheable.
// When we lookup it from the parent, it will always be newly created.
if !dentry.inode().is_dentry_cacheable() {
if !dentry.inode.is_dentry_cacheable() {
return;
}
let _ = self.inner.insert(dentry.name(), dentry.clone());
let _ = self.dentries.insert(name, dentry);
}
pub fn delete_dentry(&mut self, name: &str) -> Option<Arc<Dentry_>> {
self.inner.remove(name)
pub fn delete(&mut self, name: &str) -> Option<Arc<Dentry_>> {
self.dentries.remove(name)
}
pub fn find_dentry(&self, name: &str) -> Option<Arc<Dentry_>> {
self.inner.get(name).cloned()
}
pub fn find_dentry_with_checking_mountpoint(&self, name: &str) -> Result<Option<Arc<Dentry_>>> {
let dentry = self.find_dentry(name);
if let Some(dentry) = dentry.as_ref() {
pub fn check_mountpoint(&self, name: &str) -> Result<()> {
if let Some(dentry) = self.dentries.get(name) {
if dentry.is_mountpoint() {
return_errno_with_message!(Errno::EBUSY, "dentry is mountpint");
}
}
Ok(())
}
pub fn check_mountpoint_then_find(&self, name: &str) -> Result<Option<Arc<Dentry_>>> {
let dentry = if let Some(dentry) = self.dentries.get(name) {
if dentry.is_mountpoint() {
return_errno_with_message!(Errno::EBUSY, "dentry is mountpint");
}
Some(dentry.clone())
} else {
None
};
Ok(dentry)
}
}
@ -448,52 +454,50 @@ fn write_lock_children_on_two_dentries<'a>(
impl Dentry {
/// Creates a new `Dentry` to represent the root directory of a file system.
pub fn new_fs_root(mount_node: Arc<MountNode>) -> Arc<Self> {
Self::new(mount_node.clone(), mount_node.root_dentry().clone())
pub fn new_fs_root(mount_node: Arc<MountNode>) -> Self {
let inner = mount_node.root_dentry().clone();
Self::new(mount_node, inner)
}
/// Creates a new `Dentry` to represent the child directory of a file system.
pub fn new_fs_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
pub fn new_fs_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Self> {
let new_child_dentry = self.inner.create(name, type_, mode)?;
Ok(Self::new(self.mount_node.clone(), new_child_dentry.clone()))
Ok(Self::new(self.mount_node.clone(), new_child_dentry))
}
fn new(mount_node: Arc<MountNode>, inner: Arc<Dentry_>) -> Arc<Self> {
Arc::new_cyclic(|weak_self| Self {
mount_node,
inner,
this: weak_self.clone(),
})
fn new(mount_node: Arc<MountNode>, inner: Arc<Dentry_>) -> Self {
Self { mount_node, inner }
}
/// Lookups the target `Dentry` given the `name`.
pub fn lookup(&self, name: &str) -> Result<Arc<Self>> {
if self.inner.inode().type_() != InodeType::Dir {
pub fn lookup(&self, name: &str) -> Result<Self> {
if self.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if !self.inner.inode().mode()?.is_executable() {
if !self.mode()?.is_executable() {
return_errno!(Errno::EACCES);
}
if name.len() > NAME_MAX {
return_errno!(Errno::ENAMETOOLONG);
}
let dentry = match name {
let target_dentry = match name {
"." => self.this(),
".." => self.effective_parent().unwrap_or_else(|| self.this()),
name => {
let children_inner = self.inner.lookup_via_cache(name);
match children_inner {
Some(inner) => Self::new(self.mount_node().clone(), inner.clone()),
let target_inner_opt = self.inner.lookup_via_cache(name);
match target_inner_opt {
Some(target_inner) => Self::new(self.mount_node.clone(), target_inner),
None => {
let fs_inner = self.inner.lookup_via_fs(name)?;
Self::new(self.mount_node().clone(), fs_inner.clone())
let target_inner = self.inner.lookup_via_fs(name)?;
Self::new(self.mount_node.clone(), target_inner)
}
}
}
};
let dentry = dentry.get_top_dentry();
Ok(dentry)
let target_dentry = target_dentry.get_top_dentry();
Ok(target_dentry)
}
/// Gets the absolute path.
@ -535,8 +539,8 @@ impl Dentry {
};
let parent_inner = Self::new(
self.mount_node.parent().unwrap().upgrade().unwrap().clone(),
self.mount_node.mountpoint_dentry().unwrap().clone(),
self.mount_node.parent().unwrap().upgrade().unwrap(),
self.mount_node.mountpoint_dentry().unwrap(),
);
parent_inner.effective_name()
}
@ -545,18 +549,18 @@ impl Dentry {
///
/// If it is the root of a mount, it will go up to the mountpoint
/// to get the parent of the mountpoint recursively.
fn effective_parent(&self) -> Option<Arc<Self>> {
fn effective_parent(&self) -> Option<Self> {
if !self.inner.is_root_of_mount() {
return Some(Self::new(
self.mount_node.clone(),
self.inner.parent().unwrap().clone(),
self.inner.parent().unwrap(),
));
}
let parent = self.mount_node.parent()?;
let mountpoint = self.mount_node.mountpoint_dentry()?;
let parent_dentry = Self::new(parent.upgrade().unwrap(), mountpoint.clone());
let parent_dentry = Self::new(parent.upgrade().unwrap(), mountpoint);
parent_dentry.effective_parent()
}
@ -567,15 +571,17 @@ impl Dentry {
/// For example, first `mount /dev/sda1 /mnt` and then `mount /dev/sda2 /mnt`.
/// After the second mount is completed, the content of the first mount will be overridden.
/// We need to recursively obtain the top `Dentry`.
fn get_top_dentry(&self) -> Arc<Self> {
fn get_top_dentry(self) -> Self {
if !self.inner.is_mountpoint() {
return self.this();
return self;
}
match self.mount_node.get(self) {
match self.mount_node.get(&self) {
Some(child_mount) => {
Self::new(child_mount.clone(), child_mount.root_dentry().clone()).get_top_dentry()
let inner = child_mount.root_dentry().clone();
Self::new(child_mount, inner).get_top_dentry()
}
None => self.this(),
None => self,
}
}
@ -594,14 +600,14 @@ impl Dentry {
///
/// Returns the mounted child mount.
pub fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountNode>> {
if self.inner.inode().type_() != InodeType::Dir {
if self.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if self.effective_parent().is_none() {
return_errno_with_message!(Errno::EINVAL, "can not mount on root");
}
let child_mount = self.mount_node().mount(fs, &self.this())?;
let child_mount = self.mount_node.mount(fs, &self.this())?;
self.set_mountpoint(child_mount.clone());
Ok(child_mount)
}
@ -614,12 +620,11 @@ impl Dentry {
return_errno_with_message!(Errno::EINVAL, "not mounted");
}
let mount_node = self.mount_node.clone();
let Some(mountpoint_dentry) = mount_node.mountpoint_dentry() else {
let Some(mountpoint_dentry) = self.mount_node.mountpoint_dentry() else {
return_errno_with_message!(Errno::EINVAL, "cannot umount root mount");
};
let mountpoint_mount_node = mount_node.parent().unwrap().upgrade().unwrap();
let mountpoint_mount_node = self.mount_node.parent().unwrap().upgrade().unwrap();
let mountpoint = Self::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone());
let child_mount = mountpoint_mount_node.unmount(&mountpoint)?;
@ -628,13 +633,13 @@ impl Dentry {
}
/// Creates a `Dentry` by making an inode of the `type_` with the `mode`.
pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result<Arc<Self>> {
pub fn mknod(&self, name: &str, mode: InodeMode, type_: MknodType) -> Result<Self> {
let inner = self.inner.mknod(name, mode, type_)?;
Ok(Self::new(self.mount_node.clone(), inner.clone()))
Ok(Self::new(self.mount_node.clone(), inner))
}
/// Links a new name for the `Dentry`.
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
pub fn link(&self, old: &Self, name: &str) -> Result<()> {
if !Arc::ptr_eq(&old.mount_node, &self.mount_node) {
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
}
@ -652,7 +657,7 @@ impl Dentry {
}
/// Renames a `Dentry` to the new `Dentry` by `rename()` the inner inode.
pub fn rename(&self, old_name: &str, new_dir: &Arc<Self>, new_name: &str) -> Result<()> {
pub fn rename(&self, old_name: &str, new_dir: &Self, new_name: &str) -> Result<()> {
if !Arc::ptr_eq(&self.mount_node, &new_dir.mount_node) {
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
}
@ -664,7 +669,7 @@ impl Dentry {
/// If `recursive` is true, it will bind mount the whole mount tree
/// to the destination `Dentry`. Otherwise, it will only bind mount
/// the root mount node.
pub fn bind_mount_to(&self, dst_dentry: &Arc<Self>, recursive: bool) -> Result<()> {
pub fn bind_mount_to(&self, dst_dentry: &Self, recursive: bool) -> Result<()> {
let src_mount = self
.mount_node
.clone_mount_node_tree(&self.inner, recursive);
@ -672,8 +677,8 @@ impl Dentry {
Ok(())
}
fn this(&self) -> Arc<Self> {
self.this.upgrade().unwrap()
fn this(&self) -> Self {
self.clone()
}
/// Gets the mount node of current `Dentry`.

View File

@ -69,7 +69,7 @@ impl MountNode {
/// mountpoint. It is the fs's responsibility to ensure the data consistency.
///
/// Return the mounted child mount.
pub fn mount(&self, fs: Arc<dyn FileSystem>, mountpoint: &Arc<Dentry>) -> Result<Arc<Self>> {
pub fn mount(&self, fs: Arc<dyn FileSystem>, mountpoint: &Dentry) -> Result<Arc<Self>> {
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
}
@ -129,13 +129,13 @@ impl MountNode {
) -> Arc<Self> {
let new_root_mount = self.clone_mount_node(root_dentry);
if !recursive {
return new_root_mount.clone();
return new_root_mount;
}
let mut stack = vec![self.this()];
let mut new_stack = vec![new_root_mount.clone()];
while let Some(old_mount) = stack.pop() {
let new_parent_mount = new_stack.pop().unwrap().clone();
let new_parent_mount = new_stack.pop().unwrap();
let old_children = old_mount.children.read();
for old_child_mount in old_children.values() {
let mountpoint_dentry = old_child_mount.mountpoint_dentry().unwrap();
@ -153,10 +153,11 @@ impl MountNode {
new_child_mount
.set_mountpoint_dentry(&old_child_mount.mountpoint_dentry().unwrap());
stack.push(old_child_mount.clone());
new_stack.push(new_child_mount.clone());
new_stack.push(new_child_mount);
}
}
new_root_mount.clone()
new_root_mount
}
/// Detaches the mount node from the parent mount node.
@ -171,7 +172,7 @@ impl MountNode {
}
/// Attaches the mount node to the mountpoint.
fn attach_mount_node(&self, mountpoint: &Arc<Dentry>) {
fn attach_mount_node(&self, mountpoint: &Dentry) {
let key = mountpoint.key();
mountpoint
.mount_node()
@ -183,7 +184,7 @@ impl MountNode {
}
/// Grafts the mount node tree to the mountpoint.
pub fn graft_mount_node_tree(&self, mountpoint: &Arc<Dentry>) -> Result<()> {
pub fn graft_mount_node_tree(&self, mountpoint: &Dentry) -> Result<()> {
if mountpoint.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}

View File

@ -72,7 +72,7 @@ impl TryFrom<SocketAddr> for UnixSocketAddr {
#[derive(Clone, Debug)]
pub(super) enum UnixSocketAddrBound {
Path(Arc<str>, Arc<Dentry>),
Path(Arc<str>, Dentry),
Abstract(Arc<AbstractHandle>),
}

View File

@ -9,7 +9,7 @@ use crate::{
prelude::*,
};
pub fn lookup_socket_file(path: &str) -> Result<Arc<Dentry>> {
pub fn lookup_socket_file(path: &str) -> Result<Dentry> {
let dentry = {
let current = current!();
let fs = current.fs().read();
@ -31,7 +31,7 @@ pub fn lookup_socket_file(path: &str) -> Result<Arc<Dentry>> {
Ok(dentry)
}
pub fn create_socket_file(path: &str) -> Result<Arc<Dentry>> {
pub fn create_socket_file(path: &str) -> Result<Dentry> {
let (parent_pathname, file_name) = split_path(path);
let parent = {

View File

@ -34,7 +34,7 @@ use crate::{
pub fn load_elf_to_vm(
process_vm: &ProcessVm,
file_header: &[u8],
elf_file: Arc<Dentry>,
elf_file: Dentry,
fs_resolver: &FsResolver,
argv: Vec<CString>,
envp: Vec<CString>,
@ -85,7 +85,7 @@ fn lookup_and_parse_ldso(
elf: &Elf,
file_header: &[u8],
fs_resolver: &FsResolver,
) -> Result<Option<(Arc<Dentry>, Elf)>> {
) -> Result<Option<(Dentry, Elf)>> {
let ldso_file = {
let Some(ldso_path) = elf.ldso_path(file_header)? else {
return Ok(None);
@ -112,7 +112,7 @@ fn load_ldso(root_vmar: &Vmar<Full>, ldso_file: &Dentry, ldso_elf: &Elf) -> Resu
fn init_and_map_vmos(
process_vm: &ProcessVm,
ldso: Option<(Arc<Dentry>, Elf)>,
ldso: Option<(Dentry, Elf)>,
parsed_elf: &Elf,
elf_file: &Dentry,
) -> Result<(Vaddr, AuxVec)> {

View File

@ -25,7 +25,7 @@ use crate::{
/// because the interpreter is usually an elf binary(e.g., /bin/bash)
pub fn load_program_to_vm(
process_vm: &ProcessVm,
elf_file: Arc<Dentry>,
elf_file: Dentry,
argv: Vec<CString>,
envp: Vec<CString>,
fs_resolver: &FsResolver,
@ -68,7 +68,7 @@ pub fn load_program_to_vm(
Ok((abs_path, elf_load_info))
}
pub fn check_executable_file(dentry: &Arc<Dentry>) -> Result<()> {
pub fn check_executable_file(dentry: &Dentry) -> Result<()> {
if dentry.type_().is_directory() {
return_errno_with_message!(Errno::EISDIR, "the file is a directory");
}

View File

@ -58,7 +58,7 @@ fn lookup_executable_file(
filename: String,
flags: OpenFlags,
ctx: &Context,
) -> Result<Arc<Dentry>> {
) -> Result<Dentry> {
let fs_resolver = ctx.process.fs().read();
let dentry = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() {
fs_resolver.lookup_from_fd(dfd)
@ -79,7 +79,7 @@ fn lookup_executable_file(
}
fn do_execve(
elf_file: Arc<Dentry>,
elf_file: Dentry,
argv_ptr_ptr: Vaddr,
envp_ptr_ptr: Vaddr,
ctx: &Context,
@ -193,7 +193,7 @@ fn read_cstring_vec(
fn set_uid_from_elf(
current: &Process,
credentials: &Credentials<WriteOp>,
elf_file: &Arc<Dentry>,
elf_file: &Dentry,
) -> Result<()> {
if elf_file.mode()?.has_set_uid() {
let uid = elf_file.owner()?;
@ -211,7 +211,7 @@ fn set_uid_from_elf(
fn set_gid_from_elf(
current: &Process,
credentials: &Credentials<WriteOp>,
elf_file: &Arc<Dentry>,
elf_file: &Dentry,
) -> Result<()> {
if elf_file.mode()?.has_set_gid() {
let gid = elf_file.group()?;

View File

@ -83,7 +83,7 @@ fn do_remount() -> Result<()> {
/// Such as use user command `mount --rbind src dst`.
fn do_bind_mount(
src_name: CString,
dst_dentry: Arc<Dentry>,
dst_dentry: Dentry,
recursive: bool,
ctx: &Context,
) -> Result<()> {
@ -109,7 +109,7 @@ fn do_change_type() -> Result<()> {
}
/// Move a mount from src location to dst location.
fn do_move_mount_old(src_name: CString, dst_dentry: Arc<Dentry>, ctx: &Context) -> Result<()> {
fn do_move_mount_old(src_name: CString, dst_dentry: Dentry, ctx: &Context) -> Result<()> {
let src_dentry = {
let src_name = src_name.to_string_lossy();
if src_name.is_empty() {
@ -135,7 +135,7 @@ fn do_move_mount_old(src_name: CString, dst_dentry: Arc<Dentry>, ctx: &Context)
fn do_new_mount(
devname: CString,
fs_type: Vaddr,
target_dentry: Arc<Dentry>,
target_dentry: Dentry,
ctx: &Context,
) -> Result<()> {
if target_dentry.type_() != InodeType::Dir {

View File

@ -109,7 +109,7 @@ struct Utimbuf {
modtime: i64,
}
fn vfs_utimes(dentry: &Arc<Dentry>, times: Option<TimeSpecPair>) -> Result<SyscallReturn> {
fn vfs_utimes(dentry: &Dentry, times: Option<TimeSpecPair>) -> Result<SyscallReturn> {
let (atime, mtime, ctime) = match times {
Some(times) => {
if !times.atime.is_valid() || !times.mtime.is_valid() {