|
@@ -1,22 +1,29 @@
|
|
use core::{
|
|
use core::{
|
|
any::Any,
|
|
any::Any,
|
|
|
|
+ fmt::Debug,
|
|
sync::atomic::{compiler_fence, Ordering},
|
|
sync::atomic::{compiler_fence, Ordering},
|
|
};
|
|
};
|
|
|
|
|
|
use alloc::{
|
|
use alloc::{
|
|
collections::BTreeMap,
|
|
collections::BTreeMap,
|
|
|
|
+ string::{String, ToString},
|
|
sync::{Arc, Weak},
|
|
sync::{Arc, Weak},
|
|
};
|
|
};
|
|
use system_error::SystemError;
|
|
use system_error::SystemError;
|
|
|
|
|
|
use crate::{
|
|
use crate::{
|
|
driver::base::device::device_number::DeviceNumber,
|
|
driver::base::device::device_number::DeviceNumber,
|
|
- libs::spinlock::{SpinLock, SpinLockGuard},
|
|
|
|
|
|
+ filesystem::vfs::ROOT_INODE,
|
|
|
|
+ libs::{
|
|
|
|
+ casting::DowncastArc,
|
|
|
|
+ rwlock::RwLock,
|
|
|
|
+ spinlock::{SpinLock, SpinLockGuard},
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
use super::{
|
|
use super::{
|
|
- file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, InodeId,
|
|
|
|
- Magic, SuperBlock,
|
|
|
|
|
|
+ file::FileMode, syscall::ModeType, utils::DName, FilePrivateData, FileSystem, FileType,
|
|
|
|
+ IndexNode, InodeId, Magic, SuperBlock,
|
|
};
|
|
};
|
|
|
|
|
|
const MOUNTFS_BLOCK_SIZE: u64 = 512;
|
|
const MOUNTFS_BLOCK_SIZE: u64 = 512;
|
|
@@ -49,21 +56,22 @@ pub struct MountFSInode {
|
|
|
|
|
|
impl MountFS {
|
|
impl MountFS {
|
|
pub fn new(
|
|
pub fn new(
|
|
- inner_fs: Arc<dyn FileSystem>,
|
|
|
|
|
|
+ inner_filesystem: Arc<dyn FileSystem>,
|
|
self_mountpoint: Option<Arc<MountFSInode>>,
|
|
self_mountpoint: Option<Arc<MountFSInode>>,
|
|
) -> Arc<Self> {
|
|
) -> Arc<Self> {
|
|
- return MountFS {
|
|
|
|
- inner_filesystem: inner_fs,
|
|
|
|
|
|
+ return Arc::new_cyclic(|self_ref| MountFS {
|
|
|
|
+ inner_filesystem,
|
|
mountpoints: SpinLock::new(BTreeMap::new()),
|
|
mountpoints: SpinLock::new(BTreeMap::new()),
|
|
self_mountpoint,
|
|
self_mountpoint,
|
|
- self_ref: Weak::default(),
|
|
|
|
- }
|
|
|
|
- .wrap();
|
|
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief 用Arc指针包裹MountFS对象。
|
|
/// @brief 用Arc指针包裹MountFS对象。
|
|
/// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针
|
|
/// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针
|
|
/// 本函数只应在构造器中被调用
|
|
/// 本函数只应在构造器中被调用
|
|
|
|
+ #[allow(dead_code)]
|
|
|
|
+ #[deprecated]
|
|
fn wrap(self) -> Arc<Self> {
|
|
fn wrap(self) -> Arc<Self> {
|
|
// 创建Arc指针
|
|
// 创建Arc指针
|
|
let mount_fs: Arc<MountFS> = Arc::new(self);
|
|
let mount_fs: Arc<MountFS> = Arc::new(self);
|
|
@@ -81,12 +89,11 @@ impl MountFS {
|
|
|
|
|
|
/// @brief 获取挂载点的文件系统的root inode
|
|
/// @brief 获取挂载点的文件系统的root inode
|
|
pub fn mountpoint_root_inode(&self) -> Arc<MountFSInode> {
|
|
pub fn mountpoint_root_inode(&self) -> Arc<MountFSInode> {
|
|
- return MountFSInode {
|
|
|
|
|
|
+ return Arc::new_cyclic(|self_ref| MountFSInode {
|
|
inner_inode: self.inner_filesystem.root_inode(),
|
|
inner_inode: self.inner_filesystem.root_inode(),
|
|
mount_fs: self.self_ref.upgrade().unwrap(),
|
|
mount_fs: self.self_ref.upgrade().unwrap(),
|
|
- self_ref: Weak::default(),
|
|
|
|
- }
|
|
|
|
- .wrap();
|
|
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
pub fn inner_filesystem(&self) -> Arc<dyn FileSystem> {
|
|
pub fn inner_filesystem(&self) -> Arc<dyn FileSystem> {
|
|
@@ -96,12 +103,24 @@ impl MountFS {
|
|
pub fn self_ref(&self) -> Arc<Self> {
|
|
pub fn self_ref(&self) -> Arc<Self> {
|
|
self.self_ref.upgrade().unwrap()
|
|
self.self_ref.upgrade().unwrap()
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /// 卸载文件系统
|
|
|
|
+ /// # Errors
|
|
|
|
+ /// 如果当前文件系统是根文件系统,那么将会返回`EINVAL`
|
|
|
|
+ pub fn umount(&self) -> Result<Arc<MountFS>, SystemError> {
|
|
|
|
+ self.self_mountpoint
|
|
|
|
+ .as_ref()
|
|
|
|
+ .ok_or(SystemError::EINVAL)?
|
|
|
|
+ .do_umount()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
impl MountFSInode {
|
|
impl MountFSInode {
|
|
/// @brief 用Arc指针包裹MountFSInode对象。
|
|
/// @brief 用Arc指针包裹MountFSInode对象。
|
|
/// 本函数的主要功能为,初始化MountFSInode对象中的自引用Weak指针
|
|
/// 本函数的主要功能为,初始化MountFSInode对象中的自引用Weak指针
|
|
/// 本函数只应在构造器中被调用
|
|
/// 本函数只应在构造器中被调用
|
|
|
|
+ #[allow(dead_code)]
|
|
|
|
+ #[deprecated]
|
|
fn wrap(self) -> Arc<Self> {
|
|
fn wrap(self) -> Arc<Self> {
|
|
// 创建Arc指针
|
|
// 创建Arc指针
|
|
let inode: Arc<MountFSInode> = Arc::new(self);
|
|
let inode: Arc<MountFSInode> = Arc::new(self);
|
|
@@ -159,6 +178,66 @@ impl MountFSInode {
|
|
pub(super) fn inode_id(&self) -> InodeId {
|
|
pub(super) fn inode_id(&self) -> InodeId {
|
|
self.metadata().map(|x| x.inode_id).unwrap()
|
|
self.metadata().map(|x| x.inode_id).unwrap()
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ fn do_find(&self, name: &str) -> Result<Arc<MountFSInode>, SystemError> {
|
|
|
|
+ // 直接调用当前inode所在的文件系统的find方法进行查找
|
|
|
|
+ // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode
|
|
|
|
+ let inner_inode = self.inner_inode.find(name)?;
|
|
|
|
+ return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
|
|
|
|
+ inner_inode,
|
|
|
|
+ mount_fs: self.mount_fs.clone(),
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ })
|
|
|
|
+ .overlaid_inode());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub(super) fn do_parent(&self) -> Result<Arc<MountFSInode>, SystemError> {
|
|
|
|
+ if self.is_mountpoint_root()? {
|
|
|
|
+ // 当前inode是它所在的文件系统的root inode
|
|
|
|
+ match &self.mount_fs.self_mountpoint {
|
|
|
|
+ Some(inode) => {
|
|
|
|
+ let inner_inode = inode.parent()?;
|
|
|
|
+ return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
|
|
|
|
+ inner_inode,
|
|
|
|
+ mount_fs: self.mount_fs.clone(),
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+ None => {
|
|
|
|
+ return Ok(self.self_ref.upgrade().unwrap());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ let inner_inode = self.inner_inode.parent()?;
|
|
|
|
+ // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找
|
|
|
|
+ return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
|
|
|
|
+ inner_inode,
|
|
|
|
+ mount_fs: self.mount_fs.clone(),
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// 移除挂载点下的文件系统
|
|
|
|
+ fn do_umount(&self) -> Result<Arc<MountFS>, SystemError> {
|
|
|
|
+ if self.metadata()?.file_type != FileType::Dir {
|
|
|
|
+ return Err(SystemError::ENOTDIR);
|
|
|
|
+ }
|
|
|
|
+ return self
|
|
|
|
+ .mount_fs
|
|
|
|
+ .mountpoints
|
|
|
|
+ .lock()
|
|
|
|
+ .remove(&self.inner_inode.metadata()?.inode_id)
|
|
|
|
+ .ok_or(SystemError::ENOENT);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn do_absolute_path(&self, len: usize) -> Result<String, SystemError> {
|
|
|
|
+ if self.metadata()?.inode_id == ROOT_INODE().metadata()?.inode_id {
|
|
|
|
+ return Ok(String::with_capacity(len));
|
|
|
|
+ }
|
|
|
|
+ let name = self.dname()?;
|
|
|
|
+ return Ok(self.do_parent()?.do_absolute_path(len + name.0.len() + 1)? + "/" + &name.0);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
impl IndexNode for MountFSInode {
|
|
impl IndexNode for MountFSInode {
|
|
@@ -181,14 +260,14 @@ impl IndexNode for MountFSInode {
|
|
mode: ModeType,
|
|
mode: ModeType,
|
|
data: usize,
|
|
data: usize,
|
|
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
- return Ok(MountFSInode {
|
|
|
|
- inner_inode: self
|
|
|
|
- .inner_inode
|
|
|
|
- .create_with_data(name, file_type, mode, data)?,
|
|
|
|
|
|
+ let inner_inode = self
|
|
|
|
+ .inner_inode
|
|
|
|
+ .create_with_data(name, file_type, mode, data)?;
|
|
|
|
+ return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
|
|
|
|
+ inner_inode,
|
|
mount_fs: self.mount_fs.clone(),
|
|
mount_fs: self.mount_fs.clone(),
|
|
- self_ref: Weak::default(),
|
|
|
|
- }
|
|
|
|
- .wrap());
|
|
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ }));
|
|
}
|
|
}
|
|
|
|
|
|
fn truncate(&self, len: usize) -> Result<(), SystemError> {
|
|
fn truncate(&self, len: usize) -> Result<(), SystemError> {
|
|
@@ -247,12 +326,12 @@ impl IndexNode for MountFSInode {
|
|
file_type: FileType,
|
|
file_type: FileType,
|
|
mode: ModeType,
|
|
mode: ModeType,
|
|
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
- return Ok(MountFSInode {
|
|
|
|
- inner_inode: self.inner_inode.create(name, file_type, mode)?,
|
|
|
|
|
|
+ let inner_inode = self.inner_inode.create(name, file_type, mode)?;
|
|
|
|
+ return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
|
|
|
|
+ inner_inode,
|
|
mount_fs: self.mount_fs.clone(),
|
|
mount_fs: self.mount_fs.clone(),
|
|
- self_ref: Weak::default(),
|
|
|
|
- }
|
|
|
|
- .wrap());
|
|
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ }));
|
|
}
|
|
}
|
|
|
|
|
|
fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
|
|
fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
|
|
@@ -299,41 +378,17 @@ impl IndexNode for MountFSInode {
|
|
fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
match name {
|
|
match name {
|
|
// 查找的是当前目录
|
|
// 查找的是当前目录
|
|
- "" | "." => return Ok(self.self_ref.upgrade().unwrap()),
|
|
|
|
|
|
+ "" | "." => self
|
|
|
|
+ .self_ref
|
|
|
|
+ .upgrade()
|
|
|
|
+ .map(|inode| inode as Arc<dyn IndexNode>)
|
|
|
|
+ .ok_or(SystemError::ENOENT),
|
|
// 往父级查找
|
|
// 往父级查找
|
|
- ".." => {
|
|
|
|
- if self.is_mountpoint_root()? {
|
|
|
|
- // 当前inode是它所在的文件系统的root inode
|
|
|
|
- match &self.mount_fs.self_mountpoint {
|
|
|
|
- Some(inode) => {
|
|
|
|
- return inode.find(name);
|
|
|
|
- }
|
|
|
|
- None => {
|
|
|
|
- return Ok(self.self_ref.upgrade().unwrap());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找
|
|
|
|
- return Ok(MountFSInode {
|
|
|
|
- inner_inode: self.inner_inode.find(name)?,
|
|
|
|
- mount_fs: self.mount_fs.clone(),
|
|
|
|
- self_ref: Weak::default(),
|
|
|
|
- }
|
|
|
|
- .wrap());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ ".." => self.parent(),
|
|
// 在当前目录下查找
|
|
// 在当前目录下查找
|
|
- _ => {
|
|
|
|
- // 直接调用当前inode所在的文件系统的find方法进行查找
|
|
|
|
- // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode
|
|
|
|
- return Ok(MountFSInode {
|
|
|
|
- inner_inode: self.inner_inode.find(name)?,
|
|
|
|
- mount_fs: self.mount_fs.clone(),
|
|
|
|
- self_ref: Weak::default(),
|
|
|
|
- }
|
|
|
|
- .wrap()
|
|
|
|
- .overlaid_inode());
|
|
|
|
- }
|
|
|
|
|
|
+ // 直接调用当前inode所在的文件系统的find方法进行查找
|
|
|
|
+ // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode
|
|
|
|
+ _ => self.do_find(name).map(|inode| inode as Arc<dyn IndexNode>),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -365,21 +420,65 @@ impl IndexNode for MountFSInode {
|
|
return self.inner_inode.list();
|
|
return self.inner_inode.list();
|
|
}
|
|
}
|
|
|
|
|
|
- /// @brief 在当前inode下,挂载一个文件系统
|
|
|
|
- ///
|
|
|
|
- /// @return Ok(Arc<MountFS>) 挂载成功,返回指向MountFS的指针
|
|
|
|
fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> {
|
|
fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> {
|
|
let metadata = self.inner_inode.metadata()?;
|
|
let metadata = self.inner_inode.metadata()?;
|
|
if metadata.file_type != FileType::Dir {
|
|
if metadata.file_type != FileType::Dir {
|
|
return Err(SystemError::ENOTDIR);
|
|
return Err(SystemError::ENOTDIR);
|
|
}
|
|
}
|
|
|
|
|
|
- // 为新的挂载点创建挂载文件系统
|
|
|
|
- let new_mount_fs: Arc<MountFS> = MountFS::new(fs, Some(self.self_ref.upgrade().unwrap()));
|
|
|
|
- self.do_mount(metadata.inode_id, new_mount_fs.clone())?;
|
|
|
|
|
|
+ if self.is_mountpoint_root()? {
|
|
|
|
+ return Err(SystemError::EBUSY);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 若已有挂载系统,保证MountFS只包一层
|
|
|
|
+ let to_mount_fs = fs
|
|
|
|
+ .clone()
|
|
|
|
+ .downcast_arc::<MountFS>()
|
|
|
|
+ .map(|it| it.inner_filesystem())
|
|
|
|
+ .unwrap_or(fs);
|
|
|
|
+ let new_mount_fs = MountFS::new(to_mount_fs, Some(self.self_ref.upgrade().unwrap()));
|
|
|
|
+ self.mount_fs
|
|
|
|
+ .mountpoints
|
|
|
|
+ .lock()
|
|
|
|
+ .insert(metadata.inode_id, new_mount_fs.clone());
|
|
|
|
+
|
|
|
|
+ let mount_path = self.absolute_path();
|
|
|
|
+
|
|
|
|
+ MOUNT_LIST().insert(mount_path?, new_mount_fs.clone());
|
|
return Ok(new_mount_fs);
|
|
return Ok(new_mount_fs);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fn mount_from(&self, from: Arc<dyn IndexNode>) -> Result<Arc<MountFS>, SystemError> {
|
|
|
|
+ let metadata = self.metadata()?;
|
|
|
|
+ if from.metadata()?.file_type != FileType::Dir || metadata.file_type != FileType::Dir {
|
|
|
|
+ return Err(SystemError::ENOTDIR);
|
|
|
|
+ }
|
|
|
|
+ if self.is_mountpoint_root()? {
|
|
|
|
+ return Err(SystemError::EBUSY);
|
|
|
|
+ }
|
|
|
|
+ // kdebug!("from {:?}, to {:?}", from, self);
|
|
|
|
+ let new_mount_fs = from.umount()?;
|
|
|
|
+ self.mount_fs
|
|
|
|
+ .mountpoints
|
|
|
|
+ .lock()
|
|
|
|
+ .insert(metadata.inode_id, new_mount_fs.clone());
|
|
|
|
+
|
|
|
|
+ // MOUNT_LIST().remove(from.absolute_path()?);
|
|
|
|
+ // MOUNT_LIST().insert(self.absolute_path()?, new_mount_fs.clone());
|
|
|
|
+ return Ok(new_mount_fs);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn umount(&self) -> Result<Arc<MountFS>, SystemError> {
|
|
|
|
+ if !self.is_mountpoint_root()? {
|
|
|
|
+ return Err(SystemError::EINVAL);
|
|
|
|
+ }
|
|
|
|
+ return self.mount_fs.umount();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn absolute_path(&self) -> Result<String, SystemError> {
|
|
|
|
+ self.do_absolute_path(0)
|
|
|
|
+ }
|
|
|
|
+
|
|
#[inline]
|
|
#[inline]
|
|
fn mknod(
|
|
fn mknod(
|
|
&self,
|
|
&self,
|
|
@@ -387,12 +486,12 @@ impl IndexNode for MountFSInode {
|
|
mode: ModeType,
|
|
mode: ModeType,
|
|
dev_t: DeviceNumber,
|
|
dev_t: DeviceNumber,
|
|
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
- return Ok(MountFSInode {
|
|
|
|
- inner_inode: self.inner_inode.mknod(filename, mode, dev_t)?,
|
|
|
|
|
|
+ let inner_inode = self.inner_inode.mknod(filename, mode, dev_t)?;
|
|
|
|
+ return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
|
|
|
|
+ inner_inode,
|
|
mount_fs: self.mount_fs.clone(),
|
|
mount_fs: self.mount_fs.clone(),
|
|
- self_ref: Weak::default(),
|
|
|
|
- }
|
|
|
|
- .wrap());
|
|
|
|
|
|
+ self_ref: self_ref.clone(),
|
|
|
|
+ }));
|
|
}
|
|
}
|
|
|
|
|
|
#[inline]
|
|
#[inline]
|
|
@@ -404,6 +503,23 @@ impl IndexNode for MountFSInode {
|
|
fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
|
|
fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
|
|
self.inner_inode.poll(private_data)
|
|
self.inner_inode.poll(private_data)
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /// 若不支持,则调用第二种情况来从父目录获取文件名
|
|
|
|
+ /// # Performance
|
|
|
|
+ /// 应尽可能引入DName,
|
|
|
|
+ /// 在默认情况下,性能非常差!!!
|
|
|
|
+ fn dname(&self) -> Result<DName, SystemError> {
|
|
|
|
+ if self.is_mountpoint_root()? {
|
|
|
|
+ if let Some(inode) = &self.mount_fs.self_mountpoint {
|
|
|
|
+ return inode.inner_inode.dname();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return self.inner_inode.dname();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
|
|
|
|
+ return self.do_parent().map(|inode| inode as Arc<dyn IndexNode>);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
impl FileSystem for MountFS {
|
|
impl FileSystem for MountFS {
|
|
@@ -432,3 +548,168 @@ impl FileSystem for MountFS {
|
|
SuperBlock::new(Magic::MOUNT_MAGIC, MOUNTFS_BLOCK_SIZE, MOUNTFS_MAX_NAMELEN)
|
|
SuperBlock::new(Magic::MOUNT_MAGIC, MOUNTFS_BLOCK_SIZE, MOUNTFS_MAX_NAMELEN)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/// MountList
|
|
|
|
+/// ```rust
|
|
|
|
+/// use alloc::collection::BTreeSet;
|
|
|
|
+/// let map = BTreeSet::from([
|
|
|
|
+/// "/sys", "/dev", "/", "/bin", "/proc"
|
|
|
|
+/// ]);
|
|
|
|
+/// assert_eq!(format!("{:?}", map), "{\"/\", \"/bin\", \"/dev\", \"/proc\", \"/sys\"}");
|
|
|
|
+/// // {"/", "/bin", "/dev", "/proc", "/sys"}
|
|
|
|
+/// ```
|
|
|
|
+#[derive(PartialEq, Eq, Debug)]
|
|
|
|
+pub struct MountPath(String);
|
|
|
|
+
|
|
|
|
+impl From<&str> for MountPath {
|
|
|
|
+ fn from(value: &str) -> Self {
|
|
|
|
+ Self(String::from(value))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl From<String> for MountPath {
|
|
|
|
+ fn from(value: String) -> Self {
|
|
|
|
+ Self(value)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl AsRef<str> for MountPath {
|
|
|
|
+ fn as_ref(&self) -> &str {
|
|
|
|
+ &self.0
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl PartialOrd for MountPath {
|
|
|
|
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
|
|
|
+ Some(self.cmp(other))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Ord for MountPath {
|
|
|
|
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
|
|
|
+ let self_dep = self.0.chars().filter(|c| *c == '/').count();
|
|
|
|
+ let othe_dep = other.0.chars().filter(|c| *c == '/').count();
|
|
|
|
+ if self_dep == othe_dep {
|
|
|
|
+ // 深度一样时反序来排
|
|
|
|
+ // 根目录和根目录下的文件的绝对路径都只有一个'/'
|
|
|
|
+ other.0.cmp(&self.0)
|
|
|
|
+ } else {
|
|
|
|
+ // 根据深度,深度
|
|
|
|
+ othe_dep.cmp(&self_dep)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 维护一个挂载点的记录,以支持特定于文件系统的索引
|
|
|
|
+pub struct MountList(RwLock<BTreeMap<MountPath, Arc<MountFS>>>);
|
|
|
|
+// pub struct MountList(Option<Arc<MountListInner>>);
|
|
|
|
+static mut __MOUNTS_LIST: Option<Arc<MountList>> = None;
|
|
|
|
+
|
|
|
|
+/// # init_mountlist - 初始化挂载列表
|
|
|
|
+///
|
|
|
|
+/// 此函数用于初始化系统的挂载列表。挂载列表记录了系统中所有的文件系统挂载点及其属性。
|
|
|
|
+///
|
|
|
|
+/// ## 参数
|
|
|
|
+///
|
|
|
|
+/// - 无
|
|
|
|
+///
|
|
|
|
+/// ## 返回值
|
|
|
|
+///
|
|
|
|
+/// - 无
|
|
|
|
+#[inline(always)]
|
|
|
|
+pub fn init_mountlist() {
|
|
|
|
+ unsafe {
|
|
|
|
+ __MOUNTS_LIST = Some(Arc::new(MountList(RwLock::new(BTreeMap::new()))));
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// # MOUNT_LIST - 获取全局挂载列表
|
|
|
|
+///
|
|
|
|
+/// 该函数用于获取一个对全局挂载列表的引用。全局挂载列表是系统中所有挂载点的集合。
|
|
|
|
+///
|
|
|
|
+/// ## 返回值
|
|
|
|
+/// - &'static Arc<MountList>: 返回全局挂载列表的引用。
|
|
|
|
+#[inline(always)]
|
|
|
|
+#[allow(non_snake_case)]
|
|
|
|
+pub fn MOUNT_LIST() -> &'static Arc<MountList> {
|
|
|
|
+ unsafe {
|
|
|
|
+ return __MOUNTS_LIST.as_ref().unwrap();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl MountList {
|
|
|
|
+ /// # insert - 将文件系统挂载点插入到挂载表中
|
|
|
|
+ ///
|
|
|
|
+ /// 将一个新的文件系统挂载点插入到挂载表中。如果挂载点已经存在,则会更新对应的文件系统。
|
|
|
|
+ ///
|
|
|
|
+ /// 此函数是线程安全的,因为它使用了RwLock来保证并发访问。
|
|
|
|
+ ///
|
|
|
|
+ /// ## 参数
|
|
|
|
+ ///
|
|
|
|
+ /// - `path`: &str, 挂载点的路径。这个路径会被转换成`MountPath`类型。
|
|
|
|
+ /// - `fs`: Arc<MountFS>, 共享的文件系统实例。
|
|
|
|
+ ///
|
|
|
|
+ /// ## 返回值
|
|
|
|
+ ///
|
|
|
|
+ /// - 无
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn insert<T: AsRef<str>>(&self, path: T, fs: Arc<MountFS>) {
|
|
|
|
+ self.0.write().insert(MountPath::from(path.as_ref()), fs);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// # get_mount_point - 获取挂载点的路径
|
|
|
|
+ ///
|
|
|
|
+ /// 这个函数用于查找给定路径的挂载点。它搜索一个内部映射,找到与路径匹配的挂载点。
|
|
|
|
+ ///
|
|
|
|
+ /// ## 参数
|
|
|
|
+ ///
|
|
|
|
+ /// - `path: T`: 这是一个可转换为字符串的引用,表示要查找其挂载点的路径。
|
|
|
|
+ ///
|
|
|
|
+ /// ## 返回值
|
|
|
|
+ ///
|
|
|
|
+ /// - `Option<(String, String, Arc<MountFS>)>`:
|
|
|
|
+ /// - `Some((mount_point, rest_path, fs))`: 如果找到了匹配的挂载点,返回一个包含挂载点路径、剩余路径和挂载文件系统的元组。
|
|
|
|
+ /// - `None`: 如果没有找到匹配的挂载点,返回 None。
|
|
|
|
+ #[inline]
|
|
|
|
+ #[allow(dead_code)]
|
|
|
|
+ pub fn get_mount_point<T: AsRef<str>>(
|
|
|
|
+ &self,
|
|
|
|
+ path: T,
|
|
|
|
+ ) -> Option<(String, String, Arc<MountFS>)> {
|
|
|
|
+ self.0
|
|
|
|
+ .upgradeable_read()
|
|
|
|
+ .iter()
|
|
|
|
+ .filter_map(|(key, fs)| {
|
|
|
|
+ let strkey = key.as_ref();
|
|
|
|
+ if let Some(rest) = path.as_ref().strip_prefix(strkey) {
|
|
|
|
+ return Some((strkey.to_string(), rest.to_string(), fs.clone()));
|
|
|
|
+ }
|
|
|
|
+ None
|
|
|
|
+ })
|
|
|
|
+ .next()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// # remove - 移除挂载点
|
|
|
|
+ ///
|
|
|
|
+ /// 从挂载点管理器中移除一个挂载点。
|
|
|
|
+ ///
|
|
|
|
+ /// 此函数用于从挂载点管理器中移除一个已经存在的挂载点。如果挂载点不存在,则不进行任何操作。
|
|
|
|
+ ///
|
|
|
|
+ /// ## 参数
|
|
|
|
+ ///
|
|
|
|
+ /// - `path: T`: `T` 实现了 `Into<MountPath>` trait,代表要移除的挂载点的路径。
|
|
|
|
+ ///
|
|
|
|
+ /// ## 返回值
|
|
|
|
+ ///
|
|
|
|
+ /// - `Option<Arc<MountFS>>`: 返回一个 `Arc<MountFS>` 类型的可选值,表示被移除的挂载点,如果挂载点不存在则返回 `None`。
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn remove<T: Into<MountPath>>(&self, path: T) -> Option<Arc<MountFS>> {
|
|
|
|
+ self.0.write().remove(&path.into())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Debug for MountList {
|
|
|
|
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
|
|
+ f.debug_map().entries(MOUNT_LIST().0.read().iter()).finish()
|
|
|
|
+ }
|
|
|
|
+}
|