mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 13:56:48 +00:00
Optimize the cache and lock parts in MountNode
This commit is contained in:
parent
791c566b71
commit
ae4ac38471
@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use crate::{
|
||||
fs::{
|
||||
path::dentry::{Dentry, DentryKey, Dentry_},
|
||||
@ -8,28 +10,28 @@ use crate::{
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
/// The MountNode can form a mount tree to maintain the mount information.
|
||||
/// The `MountNode` is used to form a mount tree to maintain the mount information.
|
||||
pub struct MountNode {
|
||||
/// Root Dentry_.
|
||||
/// Root dentry.
|
||||
root_dentry: Arc<Dentry_>,
|
||||
/// Mountpoint Dentry_. A mount node can be mounted on one dentry of another mount node,
|
||||
/// Mountpoint dentry. A mount node can be mounted on one dentry of another mount node,
|
||||
/// which makes the mount being the child of the mount node.
|
||||
mountpoint_dentry: RwLock<Option<Arc<Dentry_>>>,
|
||||
mountpoint_dentry: RwMutex<Option<Arc<Dentry_>>>,
|
||||
/// The associated FS.
|
||||
fs: Arc<dyn FileSystem>,
|
||||
/// The parent mount node.
|
||||
parent: RwLock<Option<Weak<MountNode>>>,
|
||||
parent: RwMutex<Option<Weak<MountNode>>>,
|
||||
/// Child mount nodes which are mounted on one dentry of self.
|
||||
children: Mutex<BTreeMap<DentryKey, Arc<Self>>>,
|
||||
children: RwMutex<HashMap<DentryKey, Arc<Self>>>,
|
||||
/// Reference to self.
|
||||
this: Weak<Self>,
|
||||
}
|
||||
|
||||
impl MountNode {
|
||||
/// Create a root mount node with an associated FS.
|
||||
/// Creates a root mount node with an associated FS.
|
||||
///
|
||||
/// The root mount node is not mounted on other mount nodes(which means it has no
|
||||
/// parent). The root inode of the fs will form the root dentryinner of it.
|
||||
/// The root mount node is not mounted on other mount nodes (which means it has no
|
||||
/// parent). The root inode of the fs will form the inner root dentry.
|
||||
///
|
||||
/// 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.
|
||||
@ -48,15 +50,15 @@ impl MountNode {
|
||||
fn new(fs: Arc<dyn FileSystem>, parent_mount: Option<Weak<MountNode>>) -> Arc<Self> {
|
||||
Arc::new_cyclic(|weak_self| Self {
|
||||
root_dentry: Dentry_::new_root(fs.root_inode()),
|
||||
mountpoint_dentry: RwLock::new(None),
|
||||
parent: RwLock::new(parent_mount),
|
||||
children: Mutex::new(BTreeMap::new()),
|
||||
mountpoint_dentry: RwMutex::new(None),
|
||||
parent: RwMutex::new(parent_mount),
|
||||
children: RwMutex::new(HashMap::new()),
|
||||
fs,
|
||||
this: weak_self.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Mount an fs on the mountpoint, it will create a new child mount node.
|
||||
/// Mounts a fs on the mountpoint, it will create a new child mount node.
|
||||
///
|
||||
/// If the given mountpoint has already been mounted, then its mounted child mount
|
||||
/// node will be updated.
|
||||
@ -77,11 +79,11 @@ impl MountNode {
|
||||
|
||||
let key = mountpoint.key();
|
||||
let child_mount = Self::new(fs, Some(Arc::downgrade(mountpoint.mount_node())));
|
||||
self.children.lock().insert(key, child_mount.clone());
|
||||
self.children.write().insert(key, child_mount.clone());
|
||||
Ok(child_mount)
|
||||
}
|
||||
|
||||
/// Unmount a child mount node from the mountpoint and return it.
|
||||
/// Unmounts a child mount node from the mountpoint and returns it.
|
||||
///
|
||||
/// The mountpoint should belong to this mount node, or an error is returned.
|
||||
pub fn unmount(&self, mountpoint: &Dentry) -> Result<Arc<Self>> {
|
||||
@ -91,28 +93,28 @@ impl MountNode {
|
||||
|
||||
let child_mount = self
|
||||
.children
|
||||
.lock()
|
||||
.write()
|
||||
.remove(&mountpoint.key())
|
||||
.ok_or_else(|| Error::with_message(Errno::ENOENT, "can not find child mount"))?;
|
||||
Ok(child_mount)
|
||||
}
|
||||
|
||||
/// Clone a mount node with the an root `Dentry_`.
|
||||
/// Clones a mount node with the an root `Dentry_`.
|
||||
///
|
||||
/// The new mount node will have the same fs as the original one and
|
||||
/// have no parent and children. We should set the parent and children manually.
|
||||
fn clone_mount_node(&self, root_dentry: &Arc<Dentry_>) -> Arc<Self> {
|
||||
Arc::new_cyclic(|weak_self| Self {
|
||||
root_dentry: root_dentry.clone(),
|
||||
mountpoint_dentry: RwLock::new(None),
|
||||
parent: RwLock::new(None),
|
||||
children: Mutex::new(BTreeMap::new()),
|
||||
mountpoint_dentry: RwMutex::new(None),
|
||||
parent: RwMutex::new(None),
|
||||
children: RwMutex::new(HashMap::new()),
|
||||
fs: self.fs.clone(),
|
||||
this: weak_self.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Clone a mount tree starting from the specified root `Dentry_`.
|
||||
/// Clones a mount tree starting from the specified root `Dentry_`.
|
||||
///
|
||||
/// The new mount tree will replicate the structure of the original tree.
|
||||
/// The new tree is a separate entity rooted at the given `Dentry_`,
|
||||
@ -134,7 +136,7 @@ impl MountNode {
|
||||
|
||||
while let Some(old_mount) = stack.pop() {
|
||||
let new_parent_mount = new_stack.pop().unwrap().clone();
|
||||
let old_children = old_mount.children.lock();
|
||||
let old_children = old_mount.children.read();
|
||||
for old_child_mount in old_children.values() {
|
||||
let mountpoint_dentry = old_child_mount.mountpoint_dentry().unwrap();
|
||||
if !mountpoint_dentry.is_descendant_of(old_mount.root_dentry()) {
|
||||
@ -145,7 +147,7 @@ impl MountNode {
|
||||
let key = mountpoint_dentry.key();
|
||||
new_parent_mount
|
||||
.children
|
||||
.lock()
|
||||
.write()
|
||||
.insert(key, new_child_mount.clone());
|
||||
new_child_mount.set_parent(&new_parent_mount);
|
||||
new_child_mount
|
||||
@ -157,30 +159,30 @@ impl MountNode {
|
||||
new_root_mount.clone()
|
||||
}
|
||||
|
||||
/// Detach the mount node from the parent mount node.
|
||||
/// Detaches the mount node from the parent mount node.
|
||||
fn detach_mount_node(&self) {
|
||||
if let Some(parent) = self.parent() {
|
||||
let parent = parent.upgrade().unwrap();
|
||||
parent
|
||||
.children
|
||||
.lock()
|
||||
.write()
|
||||
.remove(&self.mountpoint_dentry().unwrap().key());
|
||||
}
|
||||
}
|
||||
|
||||
/// Attach the mount node to the mountpoint.
|
||||
/// Attaches the mount node to the mountpoint.
|
||||
fn attach_mount_node(&self, mountpoint: &Arc<Dentry>) {
|
||||
let key = mountpoint.key();
|
||||
mountpoint
|
||||
.mount_node()
|
||||
.children
|
||||
.lock()
|
||||
.write()
|
||||
.insert(key, self.this());
|
||||
self.set_parent(mountpoint.mount_node());
|
||||
mountpoint.set_mountpoint(self.this());
|
||||
}
|
||||
|
||||
/// Graft the mount node tree to the mountpoint.
|
||||
/// Grafts the mount node tree to the mountpoint.
|
||||
pub fn graft_mount_node_tree(&self, mountpoint: &Arc<Dentry>) -> Result<()> {
|
||||
if mountpoint.type_() != InodeType::Dir {
|
||||
return_errno!(Errno::ENOTDIR);
|
||||
@ -190,28 +192,28 @@ impl MountNode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Try to get a child mount node from the mountpoint.
|
||||
/// Gets a child mount node from the mountpoint if any.
|
||||
pub fn get(&self, mountpoint: &Dentry) -> Option<Arc<Self>> {
|
||||
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
|
||||
return None;
|
||||
}
|
||||
self.children.lock().get(&mountpoint.key()).cloned()
|
||||
self.children.read().get(&mountpoint.key()).cloned()
|
||||
}
|
||||
|
||||
/// Get the root `Dentry_` of this mount node.
|
||||
/// Gets the root `Dentry_` of this mount node.
|
||||
pub fn root_dentry(&self) -> &Arc<Dentry_> {
|
||||
&self.root_dentry
|
||||
}
|
||||
|
||||
/// Try to get the mountpoint `Dentry_` of this mount node.
|
||||
/// Gets the mountpoint `Dentry_` of this mount node if any.
|
||||
pub fn mountpoint_dentry(&self) -> Option<Arc<Dentry_>> {
|
||||
self.mountpoint_dentry.read().clone()
|
||||
}
|
||||
|
||||
/// Set the mountpoint.
|
||||
/// Sets the mountpoint.
|
||||
///
|
||||
/// In some cases we may need to reset the mountpoint of
|
||||
/// the created MountNode, such as move mount.
|
||||
/// the created `MountNode`, such as move mount.
|
||||
pub fn set_mountpoint_dentry(&self, inner: &Arc<Dentry_>) {
|
||||
let mut mountpoint_dentry = self.mountpoint_dentry.write();
|
||||
*mountpoint_dentry = Some(inner.clone());
|
||||
@ -219,7 +221,7 @@ impl MountNode {
|
||||
|
||||
/// Flushes all pending filesystem metadata and cached file data to the device.
|
||||
pub fn sync(&self) -> Result<()> {
|
||||
let children = self.children.lock();
|
||||
let children = self.children.read();
|
||||
for child in children.values() {
|
||||
child.sync()?;
|
||||
}
|
||||
@ -229,12 +231,12 @@ impl MountNode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Try to get the parent mount node.
|
||||
/// Gets the parent mount node if any.
|
||||
pub fn parent(&self) -> Option<Weak<Self>> {
|
||||
self.parent.read().as_ref().cloned()
|
||||
}
|
||||
|
||||
/// Set the parent.
|
||||
/// Sets the parent mount node.
|
||||
///
|
||||
/// In some cases we may need to reset the parent of
|
||||
/// the created MountNode, such as move mount.
|
||||
@ -243,12 +245,11 @@ impl MountNode {
|
||||
*parent = Some(Arc::downgrade(mount_node));
|
||||
}
|
||||
|
||||
/// Get strong reference to self.
|
||||
fn this(&self) -> Arc<Self> {
|
||||
self.this.upgrade().unwrap()
|
||||
}
|
||||
|
||||
/// Get the associated fs.
|
||||
/// Gets the associated fs.
|
||||
pub fn fs(&self) -> &Arc<dyn FileSystem> {
|
||||
&self.fs
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user