11496ba7bSLoGin use core::{
21496ba7bSLoGin any::Any,
31074eb34SSamuel Dai fmt::Debug,
41496ba7bSLoGin sync::atomic::{compiler_fence, Ordering},
51496ba7bSLoGin };
6004e86ffSlogin
7004e86ffSlogin use alloc::{
8004e86ffSlogin collections::BTreeMap,
91074eb34SSamuel Dai string::{String, ToString},
10004e86ffSlogin sync::{Arc, Weak},
11004e86ffSlogin };
1291e9d4abSLoGin use system_error::SystemError;
13004e86ffSlogin
14dfe53cf0SGnoCiYeH use crate::{
15dfe53cf0SGnoCiYeH driver::base::device::device_number::DeviceNumber,
161074eb34SSamuel Dai filesystem::vfs::ROOT_INODE,
171074eb34SSamuel Dai libs::{
181074eb34SSamuel Dai casting::DowncastArc,
191074eb34SSamuel Dai rwlock::RwLock,
201074eb34SSamuel Dai spinlock::{SpinLock, SpinLockGuard},
211074eb34SSamuel Dai },
22*cf7f801eSMemoryShore mm::{fault::PageFaultMessage, VmFaultReason},
23dfe53cf0SGnoCiYeH };
24004e86ffSlogin
256b4e7a29SLoGin use super::{
26*cf7f801eSMemoryShore file::{FileMode, PageCache},
27*cf7f801eSMemoryShore syscall::ModeType,
28*cf7f801eSMemoryShore utils::DName,
29*cf7f801eSMemoryShore FilePrivateData, FileSystem, FileType, IndexNode, InodeId, Magic, SuperBlock,
306b4e7a29SLoGin };
31004e86ffSlogin
32597ecc08STTaq const MOUNTFS_BLOCK_SIZE: u64 = 512;
33597ecc08STTaq const MOUNTFS_MAX_NAMELEN: u64 = 64;
34004e86ffSlogin /// @brief 挂载文件系统
35004e86ffSlogin /// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载
36004e86ffSlogin #[derive(Debug)]
37004e86ffSlogin pub struct MountFS {
38004e86ffSlogin // MountFS内部的文件系统
39004e86ffSlogin inner_filesystem: Arc<dyn FileSystem>,
40004e86ffSlogin /// 用来存储InodeID->挂载点的MountFS的B树
41004e86ffSlogin mountpoints: SpinLock<BTreeMap<InodeId, Arc<MountFS>>>,
42004e86ffSlogin /// 当前文件系统挂载到的那个挂载点的Inode
43004e86ffSlogin self_mountpoint: Option<Arc<MountFSInode>>,
44004e86ffSlogin /// 指向当前MountFS的弱引用
45004e86ffSlogin self_ref: Weak<MountFS>,
46004e86ffSlogin }
47004e86ffSlogin
48004e86ffSlogin /// @brief MountFS的Index Node 注意,这个IndexNode只是一个中间层。它的目的是将具体文件系统的Inode与挂载机制连接在一起。
49004e86ffSlogin #[derive(Debug)]
50dfe53cf0SGnoCiYeH #[cast_to([sync] IndexNode)]
51004e86ffSlogin pub struct MountFSInode {
52004e86ffSlogin /// 当前挂载点对应到具体的文件系统的Inode
53004e86ffSlogin inner_inode: Arc<dyn IndexNode>,
54004e86ffSlogin /// 当前Inode对应的MountFS
55004e86ffSlogin mount_fs: Arc<MountFS>,
56004e86ffSlogin /// 指向自身的弱引用
57004e86ffSlogin self_ref: Weak<MountFSInode>,
58004e86ffSlogin }
59004e86ffSlogin
60004e86ffSlogin impl MountFS {
new( inner_filesystem: Arc<dyn FileSystem>, self_mountpoint: Option<Arc<MountFSInode>>, ) -> Arc<Self>61004e86ffSlogin pub fn new(
621074eb34SSamuel Dai inner_filesystem: Arc<dyn FileSystem>,
63004e86ffSlogin self_mountpoint: Option<Arc<MountFSInode>>,
64004e86ffSlogin ) -> Arc<Self> {
651074eb34SSamuel Dai return Arc::new_cyclic(|self_ref| MountFS {
661074eb34SSamuel Dai inner_filesystem,
67004e86ffSlogin mountpoints: SpinLock::new(BTreeMap::new()),
68b5b571e0SLoGin self_mountpoint,
691074eb34SSamuel Dai self_ref: self_ref.clone(),
701074eb34SSamuel Dai });
71004e86ffSlogin }
72004e86ffSlogin
73004e86ffSlogin /// @brief 用Arc指针包裹MountFS对象。
74004e86ffSlogin /// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针
75004e86ffSlogin /// 本函数只应在构造器中被调用
761074eb34SSamuel Dai #[allow(dead_code)]
771074eb34SSamuel Dai #[deprecated]
wrap(self) -> Arc<Self>78004e86ffSlogin fn wrap(self) -> Arc<Self> {
79004e86ffSlogin // 创建Arc指针
80004e86ffSlogin let mount_fs: Arc<MountFS> = Arc::new(self);
81004e86ffSlogin // 创建weak指针
82004e86ffSlogin let weak: Weak<MountFS> = Arc::downgrade(&mount_fs);
83004e86ffSlogin
84004e86ffSlogin // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值
8534e6d6c8Syuyi2439 let ptr: *mut MountFS = mount_fs.as_ref() as *const Self as *mut Self;
86004e86ffSlogin unsafe {
87004e86ffSlogin (*ptr).self_ref = weak;
88004e86ffSlogin // 返回初始化好的MountFS对象
8934e6d6c8Syuyi2439 return mount_fs;
90004e86ffSlogin }
91004e86ffSlogin }
92004e86ffSlogin
93004e86ffSlogin /// @brief 获取挂载点的文件系统的root inode
mountpoint_root_inode(&self) -> Arc<MountFSInode>94004e86ffSlogin pub fn mountpoint_root_inode(&self) -> Arc<MountFSInode> {
951074eb34SSamuel Dai return Arc::new_cyclic(|self_ref| MountFSInode {
96004e86ffSlogin inner_inode: self.inner_filesystem.root_inode(),
97004e86ffSlogin mount_fs: self.self_ref.upgrade().unwrap(),
981074eb34SSamuel Dai self_ref: self_ref.clone(),
991074eb34SSamuel Dai });
100004e86ffSlogin }
101004e86ffSlogin
inner_filesystem(&self) -> Arc<dyn FileSystem>102004e86ffSlogin pub fn inner_filesystem(&self) -> Arc<dyn FileSystem> {
103004e86ffSlogin return self.inner_filesystem.clone();
104004e86ffSlogin }
105dfe53cf0SGnoCiYeH
self_ref(&self) -> Arc<Self>106dfe53cf0SGnoCiYeH pub fn self_ref(&self) -> Arc<Self> {
107dfe53cf0SGnoCiYeH self.self_ref.upgrade().unwrap()
108dfe53cf0SGnoCiYeH }
1091074eb34SSamuel Dai
1101074eb34SSamuel Dai /// 卸载文件系统
1111074eb34SSamuel Dai /// # Errors
1121074eb34SSamuel Dai /// 如果当前文件系统是根文件系统,那么将会返回`EINVAL`
umount(&self) -> Result<Arc<MountFS>, SystemError>1131074eb34SSamuel Dai pub fn umount(&self) -> Result<Arc<MountFS>, SystemError> {
1141074eb34SSamuel Dai self.self_mountpoint
1151074eb34SSamuel Dai .as_ref()
1161074eb34SSamuel Dai .ok_or(SystemError::EINVAL)?
1171074eb34SSamuel Dai .do_umount()
1181074eb34SSamuel Dai }
119004e86ffSlogin }
120004e86ffSlogin
121004e86ffSlogin impl MountFSInode {
122004e86ffSlogin /// @brief 用Arc指针包裹MountFSInode对象。
123004e86ffSlogin /// 本函数的主要功能为,初始化MountFSInode对象中的自引用Weak指针
124004e86ffSlogin /// 本函数只应在构造器中被调用
1251074eb34SSamuel Dai #[allow(dead_code)]
1261074eb34SSamuel Dai #[deprecated]
wrap(self) -> Arc<Self>127004e86ffSlogin fn wrap(self) -> Arc<Self> {
128004e86ffSlogin // 创建Arc指针
129004e86ffSlogin let inode: Arc<MountFSInode> = Arc::new(self);
130004e86ffSlogin // 创建Weak指针
131004e86ffSlogin let weak: Weak<MountFSInode> = Arc::downgrade(&inode);
132004e86ffSlogin // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值
1331496ba7bSLoGin compiler_fence(Ordering::SeqCst);
13434e6d6c8Syuyi2439 let ptr: *mut MountFSInode = inode.as_ref() as *const Self as *mut Self;
1351496ba7bSLoGin compiler_fence(Ordering::SeqCst);
136004e86ffSlogin unsafe {
137004e86ffSlogin (*ptr).self_ref = weak;
1381496ba7bSLoGin compiler_fence(Ordering::SeqCst);
139004e86ffSlogin
140004e86ffSlogin // 返回初始化好的MountFSInode对象
1411496ba7bSLoGin return inode;
142004e86ffSlogin }
143004e86ffSlogin }
144004e86ffSlogin
145004e86ffSlogin /// @brief 判断当前inode是否为它所在的文件系统的root inode
is_mountpoint_root(&self) -> Result<bool, SystemError>146676b8ef6SMork fn is_mountpoint_root(&self) -> Result<bool, SystemError> {
147004e86ffSlogin return Ok(self.inner_inode.fs().root_inode().metadata()?.inode_id
148004e86ffSlogin == self.inner_inode.metadata()?.inode_id);
149004e86ffSlogin }
150004e86ffSlogin
151004e86ffSlogin /// @brief 在挂载树上进行inode替换。
152004e86ffSlogin /// 如果当前inode是父MountFS内的一个挂载点,那么,本函数将会返回挂载到这个挂载点下的文件系统的root inode.
153004e86ffSlogin /// 如果当前inode在父MountFS内,但不是挂载点,那么说明在这里不需要进行inode替换,因此直接返回当前inode。
154004e86ffSlogin ///
155004e86ffSlogin /// @return Arc<MountFSInode>
overlaid_inode(&self) -> Arc<MountFSInode>156004e86ffSlogin fn overlaid_inode(&self) -> Arc<MountFSInode> {
157004e86ffSlogin let inode_id = self.metadata().unwrap().inode_id;
158004e86ffSlogin
159004e86ffSlogin if let Some(sub_mountfs) = self.mount_fs.mountpoints.lock().get(&inode_id) {
160004e86ffSlogin return sub_mountfs.mountpoint_root_inode();
161004e86ffSlogin } else {
162004e86ffSlogin return self.self_ref.upgrade().unwrap();
163004e86ffSlogin }
164004e86ffSlogin }
165dfe53cf0SGnoCiYeH
do_find(&self, name: &str) -> Result<Arc<MountFSInode>, SystemError>1661074eb34SSamuel Dai fn do_find(&self, name: &str) -> Result<Arc<MountFSInode>, SystemError> {
1671074eb34SSamuel Dai // 直接调用当前inode所在的文件系统的find方法进行查找
1681074eb34SSamuel Dai // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode
1691074eb34SSamuel Dai let inner_inode = self.inner_inode.find(name)?;
1701074eb34SSamuel Dai return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
1711074eb34SSamuel Dai inner_inode,
1721074eb34SSamuel Dai mount_fs: self.mount_fs.clone(),
1731074eb34SSamuel Dai self_ref: self_ref.clone(),
1741074eb34SSamuel Dai })
1751074eb34SSamuel Dai .overlaid_inode());
1761074eb34SSamuel Dai }
1771074eb34SSamuel Dai
do_parent(&self) -> Result<Arc<MountFSInode>, SystemError>1781074eb34SSamuel Dai pub(super) fn do_parent(&self) -> Result<Arc<MountFSInode>, SystemError> {
1791074eb34SSamuel Dai if self.is_mountpoint_root()? {
1801074eb34SSamuel Dai // 当前inode是它所在的文件系统的root inode
1811074eb34SSamuel Dai match &self.mount_fs.self_mountpoint {
1821074eb34SSamuel Dai Some(inode) => {
1831074eb34SSamuel Dai let inner_inode = inode.parent()?;
1841074eb34SSamuel Dai return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
1851074eb34SSamuel Dai inner_inode,
1861074eb34SSamuel Dai mount_fs: self.mount_fs.clone(),
1871074eb34SSamuel Dai self_ref: self_ref.clone(),
1881074eb34SSamuel Dai }));
1891074eb34SSamuel Dai }
1901074eb34SSamuel Dai None => {
1911074eb34SSamuel Dai return Ok(self.self_ref.upgrade().unwrap());
1921074eb34SSamuel Dai }
1931074eb34SSamuel Dai }
1941074eb34SSamuel Dai } else {
1951074eb34SSamuel Dai let inner_inode = self.inner_inode.parent()?;
1961074eb34SSamuel Dai // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找
1971074eb34SSamuel Dai return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
1981074eb34SSamuel Dai inner_inode,
1991074eb34SSamuel Dai mount_fs: self.mount_fs.clone(),
2001074eb34SSamuel Dai self_ref: self_ref.clone(),
2011074eb34SSamuel Dai }));
2021074eb34SSamuel Dai }
2031074eb34SSamuel Dai }
2041074eb34SSamuel Dai
2051074eb34SSamuel Dai /// 移除挂载点下的文件系统
do_umount(&self) -> Result<Arc<MountFS>, SystemError>2061074eb34SSamuel Dai fn do_umount(&self) -> Result<Arc<MountFS>, SystemError> {
2071074eb34SSamuel Dai if self.metadata()?.file_type != FileType::Dir {
2081074eb34SSamuel Dai return Err(SystemError::ENOTDIR);
2091074eb34SSamuel Dai }
2101074eb34SSamuel Dai return self
2111074eb34SSamuel Dai .mount_fs
2121074eb34SSamuel Dai .mountpoints
2131074eb34SSamuel Dai .lock()
2141074eb34SSamuel Dai .remove(&self.inner_inode.metadata()?.inode_id)
2151074eb34SSamuel Dai .ok_or(SystemError::ENOENT);
2161074eb34SSamuel Dai }
2171074eb34SSamuel Dai
do_absolute_path(&self, len: usize) -> Result<String, SystemError>2181074eb34SSamuel Dai fn do_absolute_path(&self, len: usize) -> Result<String, SystemError> {
2191074eb34SSamuel Dai if self.metadata()?.inode_id == ROOT_INODE().metadata()?.inode_id {
2201074eb34SSamuel Dai return Ok(String::with_capacity(len));
2211074eb34SSamuel Dai }
2221074eb34SSamuel Dai let name = self.dname()?;
2231074eb34SSamuel Dai return Ok(self.do_parent()?.do_absolute_path(len + name.0.len() + 1)? + "/" + &name.0);
2241074eb34SSamuel Dai }
225004e86ffSlogin }
226004e86ffSlogin
227004e86ffSlogin impl IndexNode for MountFSInode {
open( &self, data: SpinLockGuard<FilePrivateData>, mode: &FileMode, ) -> Result<(), SystemError>228dfe53cf0SGnoCiYeH fn open(
229dfe53cf0SGnoCiYeH &self,
230dfe53cf0SGnoCiYeH data: SpinLockGuard<FilePrivateData>,
231dfe53cf0SGnoCiYeH mode: &FileMode,
232dfe53cf0SGnoCiYeH ) -> Result<(), SystemError> {
2330d48c3c9Slogin return self.inner_inode.open(data, mode);
234004e86ffSlogin }
235004e86ffSlogin
close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError>236dfe53cf0SGnoCiYeH fn close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
237004e86ffSlogin return self.inner_inode.close(data);
238004e86ffSlogin }
239004e86ffSlogin
create_with_data( &self, name: &str, file_type: FileType, mode: ModeType, data: usize, ) -> Result<Arc<dyn IndexNode>, SystemError>240004e86ffSlogin fn create_with_data(
241004e86ffSlogin &self,
242004e86ffSlogin name: &str,
243004e86ffSlogin file_type: FileType,
2446b4e7a29SLoGin mode: ModeType,
245004e86ffSlogin data: usize,
246676b8ef6SMork ) -> Result<Arc<dyn IndexNode>, SystemError> {
2471074eb34SSamuel Dai let inner_inode = self
248004e86ffSlogin .inner_inode
2491074eb34SSamuel Dai .create_with_data(name, file_type, mode, data)?;
2501074eb34SSamuel Dai return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
2511074eb34SSamuel Dai inner_inode,
2521496ba7bSLoGin mount_fs: self.mount_fs.clone(),
2531074eb34SSamuel Dai self_ref: self_ref.clone(),
2541074eb34SSamuel Dai }));
255004e86ffSlogin }
256004e86ffSlogin
truncate(&self, len: usize) -> Result<(), SystemError>257676b8ef6SMork fn truncate(&self, len: usize) -> Result<(), SystemError> {
258004e86ffSlogin return self.inner_inode.truncate(len);
259004e86ffSlogin }
260004e86ffSlogin
read_at( &self, offset: usize, len: usize, buf: &mut [u8], data: SpinLockGuard<FilePrivateData>, ) -> Result<usize, SystemError>261004e86ffSlogin fn read_at(
262004e86ffSlogin &self,
263004e86ffSlogin offset: usize,
264004e86ffSlogin len: usize,
265004e86ffSlogin buf: &mut [u8],
266dfe53cf0SGnoCiYeH data: SpinLockGuard<FilePrivateData>,
267676b8ef6SMork ) -> Result<usize, SystemError> {
26884407d36Slogin return self.inner_inode.read_at(offset, len, buf, data);
269004e86ffSlogin }
270004e86ffSlogin
write_at( &self, offset: usize, len: usize, buf: &[u8], data: SpinLockGuard<FilePrivateData>, ) -> Result<usize, SystemError>271004e86ffSlogin fn write_at(
272004e86ffSlogin &self,
273004e86ffSlogin offset: usize,
274004e86ffSlogin len: usize,
275004e86ffSlogin buf: &[u8],
276dfe53cf0SGnoCiYeH data: SpinLockGuard<FilePrivateData>,
277676b8ef6SMork ) -> Result<usize, SystemError> {
27878bf93f0SYJwu2023 return self.inner_inode.write_at(offset, len, buf, data);
279004e86ffSlogin }
280004e86ffSlogin
281004e86ffSlogin #[inline]
fs(&self) -> Arc<dyn FileSystem>282004e86ffSlogin fn fs(&self) -> Arc<dyn FileSystem> {
283004e86ffSlogin return self.mount_fs.clone();
284004e86ffSlogin }
285004e86ffSlogin
286004e86ffSlogin #[inline]
as_any_ref(&self) -> &dyn core::any::Any287004e86ffSlogin fn as_any_ref(&self) -> &dyn core::any::Any {
288004e86ffSlogin return self.inner_inode.as_any_ref();
289004e86ffSlogin }
290004e86ffSlogin
291004e86ffSlogin #[inline]
metadata(&self) -> Result<super::Metadata, SystemError>292676b8ef6SMork fn metadata(&self) -> Result<super::Metadata, SystemError> {
293004e86ffSlogin return self.inner_inode.metadata();
294004e86ffSlogin }
295004e86ffSlogin
296004e86ffSlogin #[inline]
set_metadata(&self, metadata: &super::Metadata) -> Result<(), SystemError>297676b8ef6SMork fn set_metadata(&self, metadata: &super::Metadata) -> Result<(), SystemError> {
298004e86ffSlogin return self.inner_inode.set_metadata(metadata);
299004e86ffSlogin }
300004e86ffSlogin
301004e86ffSlogin #[inline]
resize(&self, len: usize) -> Result<(), SystemError>302676b8ef6SMork fn resize(&self, len: usize) -> Result<(), SystemError> {
303004e86ffSlogin return self.inner_inode.resize(len);
304004e86ffSlogin }
305004e86ffSlogin
306004e86ffSlogin #[inline]
create( &self, name: &str, file_type: FileType, mode: ModeType, ) -> Result<Arc<dyn IndexNode>, SystemError>307004e86ffSlogin fn create(
308004e86ffSlogin &self,
309004e86ffSlogin name: &str,
310004e86ffSlogin file_type: FileType,
3116b4e7a29SLoGin mode: ModeType,
312676b8ef6SMork ) -> Result<Arc<dyn IndexNode>, SystemError> {
3131074eb34SSamuel Dai let inner_inode = self.inner_inode.create(name, file_type, mode)?;
3141074eb34SSamuel Dai return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
3151074eb34SSamuel Dai inner_inode,
316004e86ffSlogin mount_fs: self.mount_fs.clone(),
3171074eb34SSamuel Dai self_ref: self_ref.clone(),
3181074eb34SSamuel Dai }));
319004e86ffSlogin }
320004e86ffSlogin
link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError>321676b8ef6SMork fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
322004e86ffSlogin return self.inner_inode.link(name, other);
323004e86ffSlogin }
324004e86ffSlogin
325004e86ffSlogin /// @brief 在挂载文件系统中删除文件/文件夹
326004e86ffSlogin #[inline]
unlink(&self, name: &str) -> Result<(), SystemError>327676b8ef6SMork fn unlink(&self, name: &str) -> Result<(), SystemError> {
328004e86ffSlogin let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id;
329004e86ffSlogin
330004e86ffSlogin // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode
331004e86ffSlogin if self.mount_fs.mountpoints.lock().contains_key(&inode_id) {
332676b8ef6SMork return Err(SystemError::EBUSY);
333004e86ffSlogin }
334004e86ffSlogin // 调用内层的inode的方法来删除这个inode
335004e86ffSlogin return self.inner_inode.unlink(name);
336004e86ffSlogin }
337004e86ffSlogin
338004e86ffSlogin #[inline]
rmdir(&self, name: &str) -> Result<(), SystemError>339676b8ef6SMork fn rmdir(&self, name: &str) -> Result<(), SystemError> {
340004e86ffSlogin let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id;
34184407d36Slogin
342004e86ffSlogin // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode
343004e86ffSlogin if self.mount_fs.mountpoints.lock().contains_key(&inode_id) {
344676b8ef6SMork return Err(SystemError::EBUSY);
345004e86ffSlogin }
346004e86ffSlogin // 调用内层的rmdir的方法来删除这个inode
347004e86ffSlogin let r = self.inner_inode.rmdir(name);
34884407d36Slogin
349004e86ffSlogin return r;
350004e86ffSlogin }
351004e86ffSlogin
352004e86ffSlogin #[inline]
move_to( &self, old_name: &str, target: &Arc<dyn IndexNode>, new_name: &str, ) -> Result<(), SystemError>3539e481b3bSTTaq fn move_to(
354004e86ffSlogin &self,
355004e86ffSlogin old_name: &str,
356004e86ffSlogin target: &Arc<dyn IndexNode>,
357004e86ffSlogin new_name: &str,
358676b8ef6SMork ) -> Result<(), SystemError> {
3599e481b3bSTTaq return self.inner_inode.move_to(old_name, target, new_name);
360004e86ffSlogin }
361004e86ffSlogin
find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError>362676b8ef6SMork fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
363004e86ffSlogin match name {
364004e86ffSlogin // 查找的是当前目录
3651074eb34SSamuel Dai "" | "." => self
3661074eb34SSamuel Dai .self_ref
3671074eb34SSamuel Dai .upgrade()
3681074eb34SSamuel Dai .map(|inode| inode as Arc<dyn IndexNode>)
3691074eb34SSamuel Dai .ok_or(SystemError::ENOENT),
370004e86ffSlogin // 往父级查找
3711074eb34SSamuel Dai ".." => self.parent(),
372004e86ffSlogin // 在当前目录下查找
373004e86ffSlogin // 直接调用当前inode所在的文件系统的find方法进行查找
374004e86ffSlogin // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode
3751074eb34SSamuel Dai _ => self.do_find(name).map(|inode| inode as Arc<dyn IndexNode>),
376004e86ffSlogin }
377004e86ffSlogin }
378004e86ffSlogin
379004e86ffSlogin #[inline]
get_entry_name(&self, ino: InodeId) -> Result<alloc::string::String, SystemError>380676b8ef6SMork fn get_entry_name(&self, ino: InodeId) -> Result<alloc::string::String, SystemError> {
381004e86ffSlogin return self.inner_inode.get_entry_name(ino);
382004e86ffSlogin }
383004e86ffSlogin
384004e86ffSlogin #[inline]
get_entry_name_and_metadata( &self, ino: InodeId, ) -> Result<(alloc::string::String, super::Metadata), SystemError>385004e86ffSlogin fn get_entry_name_and_metadata(
386004e86ffSlogin &self,
387004e86ffSlogin ino: InodeId,
388676b8ef6SMork ) -> Result<(alloc::string::String, super::Metadata), SystemError> {
389004e86ffSlogin return self.inner_inode.get_entry_name_and_metadata(ino);
390004e86ffSlogin }
391004e86ffSlogin
392004e86ffSlogin #[inline]
ioctl( &self, cmd: u32, data: usize, private_data: &FilePrivateData, ) -> Result<usize, SystemError>39352da9a59SGnoCiYeH fn ioctl(
39452da9a59SGnoCiYeH &self,
39552da9a59SGnoCiYeH cmd: u32,
39652da9a59SGnoCiYeH data: usize,
39752da9a59SGnoCiYeH private_data: &FilePrivateData,
39852da9a59SGnoCiYeH ) -> Result<usize, SystemError> {
39952da9a59SGnoCiYeH return self.inner_inode.ioctl(cmd, data, private_data);
400004e86ffSlogin }
401004e86ffSlogin
402004e86ffSlogin #[inline]
list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError>403676b8ef6SMork fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
404004e86ffSlogin return self.inner_inode.list();
405004e86ffSlogin }
406004e86ffSlogin
mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError>407676b8ef6SMork fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> {
408004e86ffSlogin let metadata = self.inner_inode.metadata()?;
409004e86ffSlogin if metadata.file_type != FileType::Dir {
410676b8ef6SMork return Err(SystemError::ENOTDIR);
411004e86ffSlogin }
412004e86ffSlogin
4131074eb34SSamuel Dai if self.is_mountpoint_root()? {
4141074eb34SSamuel Dai return Err(SystemError::EBUSY);
4151074eb34SSamuel Dai }
4161074eb34SSamuel Dai
4171074eb34SSamuel Dai // 若已有挂载系统,保证MountFS只包一层
4181074eb34SSamuel Dai let to_mount_fs = fs
4191074eb34SSamuel Dai .clone()
4201074eb34SSamuel Dai .downcast_arc::<MountFS>()
4211074eb34SSamuel Dai .map(|it| it.inner_filesystem())
4221074eb34SSamuel Dai .unwrap_or(fs);
4231074eb34SSamuel Dai let new_mount_fs = MountFS::new(to_mount_fs, Some(self.self_ref.upgrade().unwrap()));
4241074eb34SSamuel Dai self.mount_fs
4251074eb34SSamuel Dai .mountpoints
4261074eb34SSamuel Dai .lock()
4271074eb34SSamuel Dai .insert(metadata.inode_id, new_mount_fs.clone());
4281074eb34SSamuel Dai
4291074eb34SSamuel Dai let mount_path = self.absolute_path();
4301074eb34SSamuel Dai
4311074eb34SSamuel Dai MOUNT_LIST().insert(mount_path?, new_mount_fs.clone());
432004e86ffSlogin return Ok(new_mount_fs);
433004e86ffSlogin }
4342dbef785SGnoCiYeH
mount_from(&self, from: Arc<dyn IndexNode>) -> Result<Arc<MountFS>, SystemError>4351074eb34SSamuel Dai fn mount_from(&self, from: Arc<dyn IndexNode>) -> Result<Arc<MountFS>, SystemError> {
4361074eb34SSamuel Dai let metadata = self.metadata()?;
4371074eb34SSamuel Dai if from.metadata()?.file_type != FileType::Dir || metadata.file_type != FileType::Dir {
4381074eb34SSamuel Dai return Err(SystemError::ENOTDIR);
4391074eb34SSamuel Dai }
4401074eb34SSamuel Dai if self.is_mountpoint_root()? {
4411074eb34SSamuel Dai return Err(SystemError::EBUSY);
4421074eb34SSamuel Dai }
4432eab6dd7S曾俊 // debug!("from {:?}, to {:?}", from, self);
4441074eb34SSamuel Dai let new_mount_fs = from.umount()?;
4451074eb34SSamuel Dai self.mount_fs
4461074eb34SSamuel Dai .mountpoints
4471074eb34SSamuel Dai .lock()
4481074eb34SSamuel Dai .insert(metadata.inode_id, new_mount_fs.clone());
4491074eb34SSamuel Dai
4501074eb34SSamuel Dai // MOUNT_LIST().remove(from.absolute_path()?);
4511074eb34SSamuel Dai // MOUNT_LIST().insert(self.absolute_path()?, new_mount_fs.clone());
4521074eb34SSamuel Dai return Ok(new_mount_fs);
4531074eb34SSamuel Dai }
4541074eb34SSamuel Dai
umount(&self) -> Result<Arc<MountFS>, SystemError>4551074eb34SSamuel Dai fn umount(&self) -> Result<Arc<MountFS>, SystemError> {
4561074eb34SSamuel Dai if !self.is_mountpoint_root()? {
4571074eb34SSamuel Dai return Err(SystemError::EINVAL);
4581074eb34SSamuel Dai }
4591074eb34SSamuel Dai return self.mount_fs.umount();
4601074eb34SSamuel Dai }
4611074eb34SSamuel Dai
absolute_path(&self) -> Result<String, SystemError>4621074eb34SSamuel Dai fn absolute_path(&self) -> Result<String, SystemError> {
4631074eb34SSamuel Dai self.do_absolute_path(0)
4641074eb34SSamuel Dai }
4651074eb34SSamuel Dai
4662dbef785SGnoCiYeH #[inline]
mknod( &self, filename: &str, mode: ModeType, dev_t: DeviceNumber, ) -> Result<Arc<dyn IndexNode>, SystemError>4672dbef785SGnoCiYeH fn mknod(
4682dbef785SGnoCiYeH &self,
4692dbef785SGnoCiYeH filename: &str,
4702dbef785SGnoCiYeH mode: ModeType,
4712dbef785SGnoCiYeH dev_t: DeviceNumber,
4722dbef785SGnoCiYeH ) -> Result<Arc<dyn IndexNode>, SystemError> {
4731074eb34SSamuel Dai let inner_inode = self.inner_inode.mknod(filename, mode, dev_t)?;
4741074eb34SSamuel Dai return Ok(Arc::new_cyclic(|self_ref| MountFSInode {
4751074eb34SSamuel Dai inner_inode,
4762dbef785SGnoCiYeH mount_fs: self.mount_fs.clone(),
4771074eb34SSamuel Dai self_ref: self_ref.clone(),
4781074eb34SSamuel Dai }));
4792dbef785SGnoCiYeH }
4802dbef785SGnoCiYeH
4812dbef785SGnoCiYeH #[inline]
special_node(&self) -> Option<super::SpecialNodeData>4822dbef785SGnoCiYeH fn special_node(&self) -> Option<super::SpecialNodeData> {
4832dbef785SGnoCiYeH self.inner_inode.special_node()
4842dbef785SGnoCiYeH }
48552bcb59eSGnoCiYeH
48652bcb59eSGnoCiYeH #[inline]
poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError>48752bcb59eSGnoCiYeH fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
48852bcb59eSGnoCiYeH self.inner_inode.poll(private_data)
48952bcb59eSGnoCiYeH }
4901074eb34SSamuel Dai
4911074eb34SSamuel Dai /// 若不支持,则调用第二种情况来从父目录获取文件名
4921074eb34SSamuel Dai /// # Performance
4931074eb34SSamuel Dai /// 应尽可能引入DName,
4941074eb34SSamuel Dai /// 在默认情况下,性能非常差!!!
dname(&self) -> Result<DName, SystemError>4951074eb34SSamuel Dai fn dname(&self) -> Result<DName, SystemError> {
4961074eb34SSamuel Dai if self.is_mountpoint_root()? {
4971074eb34SSamuel Dai if let Some(inode) = &self.mount_fs.self_mountpoint {
4981074eb34SSamuel Dai return inode.inner_inode.dname();
4991074eb34SSamuel Dai }
5001074eb34SSamuel Dai }
5011074eb34SSamuel Dai return self.inner_inode.dname();
5021074eb34SSamuel Dai }
5031074eb34SSamuel Dai
parent(&self) -> Result<Arc<dyn IndexNode>, SystemError>5041074eb34SSamuel Dai fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
5051074eb34SSamuel Dai return self.do_parent().map(|inode| inode as Arc<dyn IndexNode>);
5061074eb34SSamuel Dai }
507*cf7f801eSMemoryShore
page_cache(&self) -> Option<Arc<PageCache>>508*cf7f801eSMemoryShore fn page_cache(&self) -> Option<Arc<PageCache>> {
509*cf7f801eSMemoryShore self.inner_inode.page_cache()
510*cf7f801eSMemoryShore }
511004e86ffSlogin }
512004e86ffSlogin
513004e86ffSlogin impl FileSystem for MountFS {
root_inode(&self) -> Arc<dyn IndexNode>514004e86ffSlogin fn root_inode(&self) -> Arc<dyn IndexNode> {
515004e86ffSlogin match &self.self_mountpoint {
516004e86ffSlogin Some(inode) => return inode.mount_fs.root_inode(),
517004e86ffSlogin // 当前文件系统是rootfs
518004e86ffSlogin None => self.mountpoint_root_inode(),
519004e86ffSlogin }
520004e86ffSlogin }
521004e86ffSlogin
info(&self) -> super::FsInfo522004e86ffSlogin fn info(&self) -> super::FsInfo {
523004e86ffSlogin return self.inner_filesystem.info();
524004e86ffSlogin }
525004e86ffSlogin
526004e86ffSlogin /// @brief 本函数用于实现动态转换。
527004e86ffSlogin /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
as_any_ref(&self) -> &dyn Any528004e86ffSlogin fn as_any_ref(&self) -> &dyn Any {
529004e86ffSlogin self
530004e86ffSlogin }
5311d37ca6dSDonkey Kane
name(&self) -> &str5321d37ca6dSDonkey Kane fn name(&self) -> &str {
5331d37ca6dSDonkey Kane "mountfs"
5341d37ca6dSDonkey Kane }
super_block(&self) -> SuperBlock535597ecc08STTaq fn super_block(&self) -> SuperBlock {
536597ecc08STTaq SuperBlock::new(Magic::MOUNT_MAGIC, MOUNTFS_BLOCK_SIZE, MOUNTFS_MAX_NAMELEN)
537597ecc08STTaq }
538*cf7f801eSMemoryShore
fault(&self, pfm: &mut PageFaultMessage) -> VmFaultReason539*cf7f801eSMemoryShore unsafe fn fault(&self, pfm: &mut PageFaultMessage) -> VmFaultReason {
540*cf7f801eSMemoryShore self.inner_filesystem.fault(pfm)
541*cf7f801eSMemoryShore }
542*cf7f801eSMemoryShore
map_pages( &self, pfm: &mut PageFaultMessage, start_pgoff: usize, end_pgoff: usize, ) -> VmFaultReason543*cf7f801eSMemoryShore unsafe fn map_pages(
544*cf7f801eSMemoryShore &self,
545*cf7f801eSMemoryShore pfm: &mut PageFaultMessage,
546*cf7f801eSMemoryShore start_pgoff: usize,
547*cf7f801eSMemoryShore end_pgoff: usize,
548*cf7f801eSMemoryShore ) -> VmFaultReason {
549*cf7f801eSMemoryShore self.inner_filesystem.map_pages(pfm, start_pgoff, end_pgoff)
550*cf7f801eSMemoryShore }
551004e86ffSlogin }
5521074eb34SSamuel Dai
5531074eb34SSamuel Dai /// MountList
5541074eb34SSamuel Dai /// ```rust
5551074eb34SSamuel Dai /// use alloc::collection::BTreeSet;
5561074eb34SSamuel Dai /// let map = BTreeSet::from([
5571074eb34SSamuel Dai /// "/sys", "/dev", "/", "/bin", "/proc"
5581074eb34SSamuel Dai /// ]);
5591074eb34SSamuel Dai /// assert_eq!(format!("{:?}", map), "{\"/\", \"/bin\", \"/dev\", \"/proc\", \"/sys\"}");
5601074eb34SSamuel Dai /// // {"/", "/bin", "/dev", "/proc", "/sys"}
5611074eb34SSamuel Dai /// ```
5621074eb34SSamuel Dai #[derive(PartialEq, Eq, Debug)]
5631074eb34SSamuel Dai pub struct MountPath(String);
5641074eb34SSamuel Dai
5651074eb34SSamuel Dai impl From<&str> for MountPath {
from(value: &str) -> Self5661074eb34SSamuel Dai fn from(value: &str) -> Self {
5671074eb34SSamuel Dai Self(String::from(value))
5681074eb34SSamuel Dai }
5691074eb34SSamuel Dai }
5701074eb34SSamuel Dai
5711074eb34SSamuel Dai impl From<String> for MountPath {
from(value: String) -> Self5721074eb34SSamuel Dai fn from(value: String) -> Self {
5731074eb34SSamuel Dai Self(value)
5741074eb34SSamuel Dai }
5751074eb34SSamuel Dai }
5761074eb34SSamuel Dai
5771074eb34SSamuel Dai impl AsRef<str> for MountPath {
as_ref(&self) -> &str5781074eb34SSamuel Dai fn as_ref(&self) -> &str {
5791074eb34SSamuel Dai &self.0
5801074eb34SSamuel Dai }
5811074eb34SSamuel Dai }
5821074eb34SSamuel Dai
5831074eb34SSamuel Dai impl PartialOrd for MountPath {
partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering>5841074eb34SSamuel Dai fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
5851074eb34SSamuel Dai Some(self.cmp(other))
5861074eb34SSamuel Dai }
5871074eb34SSamuel Dai }
5881074eb34SSamuel Dai
5891074eb34SSamuel Dai impl Ord for MountPath {
cmp(&self, other: &Self) -> core::cmp::Ordering5901074eb34SSamuel Dai fn cmp(&self, other: &Self) -> core::cmp::Ordering {
5911074eb34SSamuel Dai let self_dep = self.0.chars().filter(|c| *c == '/').count();
5921074eb34SSamuel Dai let othe_dep = other.0.chars().filter(|c| *c == '/').count();
5931074eb34SSamuel Dai if self_dep == othe_dep {
5941074eb34SSamuel Dai // 深度一样时反序来排
5951074eb34SSamuel Dai // 根目录和根目录下的文件的绝对路径都只有一个'/'
5961074eb34SSamuel Dai other.0.cmp(&self.0)
5971074eb34SSamuel Dai } else {
5981074eb34SSamuel Dai // 根据深度,深度
5991074eb34SSamuel Dai othe_dep.cmp(&self_dep)
6001074eb34SSamuel Dai }
6011074eb34SSamuel Dai }
6021074eb34SSamuel Dai }
6031074eb34SSamuel Dai
6041074eb34SSamuel Dai // 维护一个挂载点的记录,以支持特定于文件系统的索引
6051074eb34SSamuel Dai pub struct MountList(RwLock<BTreeMap<MountPath, Arc<MountFS>>>);
6061074eb34SSamuel Dai // pub struct MountList(Option<Arc<MountListInner>>);
6071074eb34SSamuel Dai static mut __MOUNTS_LIST: Option<Arc<MountList>> = None;
6081074eb34SSamuel Dai
6091074eb34SSamuel Dai /// # init_mountlist - 初始化挂载列表
6101074eb34SSamuel Dai ///
6111074eb34SSamuel Dai /// 此函数用于初始化系统的挂载列表。挂载列表记录了系统中所有的文件系统挂载点及其属性。
6121074eb34SSamuel Dai ///
6131074eb34SSamuel Dai /// ## 参数
6141074eb34SSamuel Dai ///
6151074eb34SSamuel Dai /// - 无
6161074eb34SSamuel Dai ///
6171074eb34SSamuel Dai /// ## 返回值
6181074eb34SSamuel Dai ///
6191074eb34SSamuel Dai /// - 无
6201074eb34SSamuel Dai #[inline(always)]
init_mountlist()6211074eb34SSamuel Dai pub fn init_mountlist() {
6221074eb34SSamuel Dai unsafe {
6231074eb34SSamuel Dai __MOUNTS_LIST = Some(Arc::new(MountList(RwLock::new(BTreeMap::new()))));
6241074eb34SSamuel Dai }
6251074eb34SSamuel Dai }
6261074eb34SSamuel Dai
6271074eb34SSamuel Dai /// # MOUNT_LIST - 获取全局挂载列表
6281074eb34SSamuel Dai ///
6291074eb34SSamuel Dai /// 该函数用于获取一个对全局挂载列表的引用。全局挂载列表是系统中所有挂载点的集合。
6301074eb34SSamuel Dai ///
6311074eb34SSamuel Dai /// ## 返回值
6321074eb34SSamuel Dai /// - &'static Arc<MountList>: 返回全局挂载列表的引用。
6331074eb34SSamuel Dai #[inline(always)]
6341074eb34SSamuel Dai #[allow(non_snake_case)]
MOUNT_LIST() -> &'static Arc<MountList>6351074eb34SSamuel Dai pub fn MOUNT_LIST() -> &'static Arc<MountList> {
6361074eb34SSamuel Dai unsafe {
6371074eb34SSamuel Dai return __MOUNTS_LIST.as_ref().unwrap();
6381074eb34SSamuel Dai }
6391074eb34SSamuel Dai }
6401074eb34SSamuel Dai
6411074eb34SSamuel Dai impl MountList {
6421074eb34SSamuel Dai /// # insert - 将文件系统挂载点插入到挂载表中
6431074eb34SSamuel Dai ///
6441074eb34SSamuel Dai /// 将一个新的文件系统挂载点插入到挂载表中。如果挂载点已经存在,则会更新对应的文件系统。
6451074eb34SSamuel Dai ///
6461074eb34SSamuel Dai /// 此函数是线程安全的,因为它使用了RwLock来保证并发访问。
6471074eb34SSamuel Dai ///
6481074eb34SSamuel Dai /// ## 参数
6491074eb34SSamuel Dai ///
6501074eb34SSamuel Dai /// - `path`: &str, 挂载点的路径。这个路径会被转换成`MountPath`类型。
6511074eb34SSamuel Dai /// - `fs`: Arc<MountFS>, 共享的文件系统实例。
6521074eb34SSamuel Dai ///
6531074eb34SSamuel Dai /// ## 返回值
6541074eb34SSamuel Dai ///
6551074eb34SSamuel Dai /// - 无
6561074eb34SSamuel Dai #[inline]
insert<T: AsRef<str>>(&self, path: T, fs: Arc<MountFS>)6571074eb34SSamuel Dai pub fn insert<T: AsRef<str>>(&self, path: T, fs: Arc<MountFS>) {
6581074eb34SSamuel Dai self.0.write().insert(MountPath::from(path.as_ref()), fs);
6591074eb34SSamuel Dai }
6601074eb34SSamuel Dai
6611074eb34SSamuel Dai /// # get_mount_point - 获取挂载点的路径
6621074eb34SSamuel Dai ///
6631074eb34SSamuel Dai /// 这个函数用于查找给定路径的挂载点。它搜索一个内部映射,找到与路径匹配的挂载点。
6641074eb34SSamuel Dai ///
6651074eb34SSamuel Dai /// ## 参数
6661074eb34SSamuel Dai ///
6671074eb34SSamuel Dai /// - `path: T`: 这是一个可转换为字符串的引用,表示要查找其挂载点的路径。
6681074eb34SSamuel Dai ///
6691074eb34SSamuel Dai /// ## 返回值
6701074eb34SSamuel Dai ///
6711074eb34SSamuel Dai /// - `Option<(String, String, Arc<MountFS>)>`:
6721074eb34SSamuel Dai /// - `Some((mount_point, rest_path, fs))`: 如果找到了匹配的挂载点,返回一个包含挂载点路径、剩余路径和挂载文件系统的元组。
6731074eb34SSamuel Dai /// - `None`: 如果没有找到匹配的挂载点,返回 None。
6741074eb34SSamuel Dai #[inline]
6751074eb34SSamuel Dai #[allow(dead_code)]
get_mount_point<T: AsRef<str>>( &self, path: T, ) -> Option<(String, String, Arc<MountFS>)>6761074eb34SSamuel Dai pub fn get_mount_point<T: AsRef<str>>(
6771074eb34SSamuel Dai &self,
6781074eb34SSamuel Dai path: T,
6791074eb34SSamuel Dai ) -> Option<(String, String, Arc<MountFS>)> {
6801074eb34SSamuel Dai self.0
6811074eb34SSamuel Dai .upgradeable_read()
6821074eb34SSamuel Dai .iter()
6831074eb34SSamuel Dai .filter_map(|(key, fs)| {
6841074eb34SSamuel Dai let strkey = key.as_ref();
6851074eb34SSamuel Dai if let Some(rest) = path.as_ref().strip_prefix(strkey) {
6861074eb34SSamuel Dai return Some((strkey.to_string(), rest.to_string(), fs.clone()));
6871074eb34SSamuel Dai }
6881074eb34SSamuel Dai None
6891074eb34SSamuel Dai })
6901074eb34SSamuel Dai .next()
6911074eb34SSamuel Dai }
6921074eb34SSamuel Dai
6931074eb34SSamuel Dai /// # remove - 移除挂载点
6941074eb34SSamuel Dai ///
6951074eb34SSamuel Dai /// 从挂载点管理器中移除一个挂载点。
6961074eb34SSamuel Dai ///
6971074eb34SSamuel Dai /// 此函数用于从挂载点管理器中移除一个已经存在的挂载点。如果挂载点不存在,则不进行任何操作。
6981074eb34SSamuel Dai ///
6991074eb34SSamuel Dai /// ## 参数
7001074eb34SSamuel Dai ///
7011074eb34SSamuel Dai /// - `path: T`: `T` 实现了 `Into<MountPath>` trait,代表要移除的挂载点的路径。
7021074eb34SSamuel Dai ///
7031074eb34SSamuel Dai /// ## 返回值
7041074eb34SSamuel Dai ///
7051074eb34SSamuel Dai /// - `Option<Arc<MountFS>>`: 返回一个 `Arc<MountFS>` 类型的可选值,表示被移除的挂载点,如果挂载点不存在则返回 `None`。
7061074eb34SSamuel Dai #[inline]
remove<T: Into<MountPath>>(&self, path: T) -> Option<Arc<MountFS>>7071074eb34SSamuel Dai pub fn remove<T: Into<MountPath>>(&self, path: T) -> Option<Arc<MountFS>> {
7081074eb34SSamuel Dai self.0.write().remove(&path.into())
7091074eb34SSamuel Dai }
7101074eb34SSamuel Dai }
7111074eb34SSamuel Dai
7121074eb34SSamuel Dai impl Debug for MountList {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result7131074eb34SSamuel Dai fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7141074eb34SSamuel Dai f.debug_map().entries(MOUNT_LIST().0.read().iter()).finish()
7151074eb34SSamuel Dai }
7161074eb34SSamuel Dai }
717