xref: /DragonOS/kernel/src/filesystem/vfs/mount.rs (revision 1496ba7b24a5e6954291ca9643b9f3cec567479a)
1 use core::{
2     any::Any,
3     sync::atomic::{compiler_fence, Ordering},
4 };
5 
6 use alloc::{
7     collections::BTreeMap,
8     sync::{Arc, Weak},
9 };
10 
11 use crate::{libs::spinlock::SpinLock, syscall::SystemError};
12 
13 use super::{file::FileMode, FilePrivateData, FileSystem, FileType, IndexNode, InodeId};
14 
15 /// @brief 挂载文件系统
16 /// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载
17 #[derive(Debug)]
18 pub struct MountFS {
19     // MountFS内部的文件系统
20     inner_filesystem: Arc<dyn FileSystem>,
21     /// 用来存储InodeID->挂载点的MountFS的B树
22     mountpoints: SpinLock<BTreeMap<InodeId, Arc<MountFS>>>,
23     /// 当前文件系统挂载到的那个挂载点的Inode
24     self_mountpoint: Option<Arc<MountFSInode>>,
25     /// 指向当前MountFS的弱引用
26     self_ref: Weak<MountFS>,
27 }
28 
29 /// @brief MountFS的Index Node 注意,这个IndexNode只是一个中间层。它的目的是将具体文件系统的Inode与挂载机制连接在一起。
30 #[derive(Debug)]
31 pub struct MountFSInode {
32     /// 当前挂载点对应到具体的文件系统的Inode
33     inner_inode: Arc<dyn IndexNode>,
34     /// 当前Inode对应的MountFS
35     mount_fs: Arc<MountFS>,
36     /// 指向自身的弱引用
37     self_ref: Weak<MountFSInode>,
38 }
39 
40 impl MountFS {
41     pub fn new(
42         inner_fs: Arc<dyn FileSystem>,
43         self_mountpoint: Option<Arc<MountFSInode>>,
44     ) -> Arc<Self> {
45         return MountFS {
46             inner_filesystem: inner_fs,
47             mountpoints: SpinLock::new(BTreeMap::new()),
48             self_mountpoint: self_mountpoint,
49             self_ref: Weak::default(),
50         }
51         .wrap();
52     }
53 
54     /// @brief 用Arc指针包裹MountFS对象。
55     /// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针
56     /// 本函数只应在构造器中被调用
57     fn wrap(self) -> Arc<Self> {
58         // 创建Arc指针
59         let mount_fs: Arc<MountFS> = Arc::new(self);
60         // 创建weak指针
61         let weak: Weak<MountFS> = Arc::downgrade(&mount_fs);
62 
63         // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值
64         let ptr: *mut MountFS = Arc::into_raw(mount_fs) as *mut Self;
65         unsafe {
66             (*ptr).self_ref = weak;
67             // 返回初始化好的MountFS对象
68             return Arc::from_raw(ptr);
69         }
70     }
71 
72     /// @brief 获取挂载点的文件系统的root inode
73     pub fn mountpoint_root_inode(&self) -> Arc<MountFSInode> {
74         return MountFSInode {
75             inner_inode: self.inner_filesystem.root_inode(),
76             mount_fs: self.self_ref.upgrade().unwrap(),
77             self_ref: Weak::default(),
78         }
79         .wrap();
80     }
81 
82     pub fn inner_filesystem(&self) -> Arc<dyn FileSystem> {
83         return self.inner_filesystem.clone();
84     }
85 }
86 
87 impl MountFSInode {
88     /// @brief 用Arc指针包裹MountFSInode对象。
89     /// 本函数的主要功能为,初始化MountFSInode对象中的自引用Weak指针
90     /// 本函数只应在构造器中被调用
91     fn wrap(self) -> Arc<Self> {
92         // 创建Arc指针
93         let inode: Arc<MountFSInode> = Arc::new(self);
94         // 创建Weak指针
95         let weak: Weak<MountFSInode> = Arc::downgrade(&inode);
96         // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值
97         compiler_fence(Ordering::SeqCst);
98         let ptr: *mut MountFSInode = Arc::into_raw(inode.clone()) as *mut Self;
99         compiler_fence(Ordering::SeqCst);
100         unsafe {
101             (*ptr).self_ref = weak;
102             compiler_fence(Ordering::SeqCst);
103 
104             // 返回初始化好的MountFSInode对象
105             return inode;
106         }
107     }
108 
109     /// @brief 判断当前inode是否为它所在的文件系统的root inode
110     fn is_mountpoint_root(&self) -> Result<bool, SystemError> {
111         return Ok(self.inner_inode.fs().root_inode().metadata()?.inode_id
112             == self.inner_inode.metadata()?.inode_id);
113     }
114 
115     /// @brief 在挂载树上进行inode替换。
116     /// 如果当前inode是父MountFS内的一个挂载点,那么,本函数将会返回挂载到这个挂载点下的文件系统的root inode.
117     /// 如果当前inode在父MountFS内,但不是挂载点,那么说明在这里不需要进行inode替换,因此直接返回当前inode。
118     ///
119     /// @return Arc<MountFSInode>
120     fn overlaid_inode(&self) -> Arc<MountFSInode> {
121         let inode_id = self.metadata().unwrap().inode_id;
122 
123         if let Some(sub_mountfs) = self.mount_fs.mountpoints.lock().get(&inode_id) {
124             return sub_mountfs.mountpoint_root_inode();
125         } else {
126             return self.self_ref.upgrade().unwrap();
127         }
128     }
129 }
130 
131 impl IndexNode for MountFSInode {
132     fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), SystemError> {
133         return self.inner_inode.open(data, mode);
134     }
135 
136     fn close(&self, data: &mut FilePrivateData) -> Result<(), SystemError> {
137         return self.inner_inode.close(data);
138     }
139 
140     fn create_with_data(
141         &self,
142         name: &str,
143         file_type: FileType,
144         mode: u32,
145         data: usize,
146     ) -> Result<Arc<dyn IndexNode>, SystemError> {
147         return Ok(MountFSInode {
148             inner_inode: self
149                 .inner_inode
150                 .create_with_data(name, file_type, mode, data)?,
151             mount_fs: self.mount_fs.clone(),
152             self_ref: Weak::default(),
153         }
154         .wrap());
155     }
156 
157     fn truncate(&self, len: usize) -> Result<(), SystemError> {
158         return self.inner_inode.truncate(len);
159     }
160 
161     fn read_at(
162         &self,
163         offset: usize,
164         len: usize,
165         buf: &mut [u8],
166         data: &mut FilePrivateData,
167     ) -> Result<usize, SystemError> {
168         return self.inner_inode.read_at(offset, len, buf, data);
169     }
170 
171     fn write_at(
172         &self,
173         offset: usize,
174         len: usize,
175         buf: &[u8],
176         data: &mut FilePrivateData,
177     ) -> Result<usize, SystemError> {
178         return self.inner_inode.write_at(offset, len, buf, data);
179     }
180 
181     #[inline]
182     fn poll(&self) -> Result<super::PollStatus, SystemError> {
183         return self.inner_inode.poll();
184     }
185 
186     #[inline]
187     fn fs(&self) -> Arc<dyn FileSystem> {
188         return self.mount_fs.clone();
189     }
190 
191     #[inline]
192     fn as_any_ref(&self) -> &dyn core::any::Any {
193         return self.inner_inode.as_any_ref();
194     }
195 
196     #[inline]
197     fn metadata(&self) -> Result<super::Metadata, SystemError> {
198         return self.inner_inode.metadata();
199     }
200 
201     #[inline]
202     fn set_metadata(&self, metadata: &super::Metadata) -> Result<(), SystemError> {
203         return self.inner_inode.set_metadata(metadata);
204     }
205 
206     #[inline]
207     fn resize(&self, len: usize) -> Result<(), SystemError> {
208         return self.inner_inode.resize(len);
209     }
210 
211     #[inline]
212     fn create(
213         &self,
214         name: &str,
215         file_type: FileType,
216         mode: u32,
217     ) -> Result<Arc<dyn IndexNode>, SystemError> {
218         return Ok(MountFSInode {
219             inner_inode: self.inner_inode.create(name, file_type, mode)?,
220             mount_fs: self.mount_fs.clone(),
221             self_ref: Weak::default(),
222         }
223         .wrap());
224     }
225 
226     fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
227         return self.inner_inode.link(name, other);
228     }
229 
230     /// @brief 在挂载文件系统中删除文件/文件夹
231     #[inline]
232     fn unlink(&self, name: &str) -> Result<(), SystemError> {
233         let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id;
234 
235         // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode
236         if self.mount_fs.mountpoints.lock().contains_key(&inode_id) {
237             return Err(SystemError::EBUSY);
238         }
239         // 调用内层的inode的方法来删除这个inode
240         return self.inner_inode.unlink(name);
241     }
242 
243     #[inline]
244     fn rmdir(&self, name: &str) -> Result<(), SystemError> {
245         let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id;
246 
247         // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode
248         if self.mount_fs.mountpoints.lock().contains_key(&inode_id) {
249             return Err(SystemError::EBUSY);
250         }
251         // 调用内层的rmdir的方法来删除这个inode
252         let r = self.inner_inode.rmdir(name);
253 
254         return r;
255     }
256 
257     #[inline]
258     fn move_(
259         &self,
260         old_name: &str,
261         target: &Arc<dyn IndexNode>,
262         new_name: &str,
263     ) -> Result<(), SystemError> {
264         return self.inner_inode.move_(old_name, target, new_name);
265     }
266 
267     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
268         match name {
269             // 查找的是当前目录
270             "" | "." => return Ok(self.self_ref.upgrade().unwrap()),
271             // 往父级查找
272             ".." => {
273                 if self.is_mountpoint_root()? {
274                     // 当前inode是它所在的文件系统的root inode
275                     match &self.mount_fs.self_mountpoint {
276                         Some(inode) => {
277                             return inode.find(name);
278                         }
279                         None => {
280                             return Ok(self.self_ref.upgrade().unwrap());
281                         }
282                     }
283                 } else {
284                     // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找
285                     return Ok(MountFSInode {
286                         inner_inode: self.inner_inode.find(name)?,
287                         mount_fs: self.mount_fs.clone(),
288                         self_ref: Weak::default(),
289                     }
290                     .wrap());
291                 }
292             }
293             // 在当前目录下查找
294             _ => {
295                 // 直接调用当前inode所在的文件系统的find方法进行查找
296                 // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode
297                 return Ok(MountFSInode {
298                     inner_inode: self.inner_inode.find(name)?,
299                     mount_fs: self.mount_fs.clone(),
300                     self_ref: Weak::default(),
301                 }
302                 .wrap()
303                 .overlaid_inode());
304             }
305         }
306     }
307 
308     #[inline]
309     fn get_entry_name(&self, ino: InodeId) -> Result<alloc::string::String, SystemError> {
310         return self.inner_inode.get_entry_name(ino);
311     }
312 
313     #[inline]
314     fn get_entry_name_and_metadata(
315         &self,
316         ino: InodeId,
317     ) -> Result<(alloc::string::String, super::Metadata), SystemError> {
318         return self.inner_inode.get_entry_name_and_metadata(ino);
319     }
320 
321     #[inline]
322     fn ioctl(&self, cmd: u32, data: usize) -> Result<usize, SystemError> {
323         return self.inner_inode.ioctl(cmd, data);
324     }
325 
326     #[inline]
327     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
328         return self.inner_inode.list();
329     }
330 
331     /// @brief 在当前inode下,挂载一个文件系统
332     ///
333     /// @return Ok(Arc<MountFS>) 挂载成功,返回指向MountFS的指针
334     fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> {
335         let metadata = self.inner_inode.metadata()?;
336         if metadata.file_type != FileType::Dir {
337             return Err(SystemError::ENOTDIR);
338         }
339 
340         // 为新的挂载点创建挂载文件系统
341         let new_mount_fs: Arc<MountFS> = MountFS::new(fs, Some(self.self_ref.upgrade().unwrap()));
342         // 将新的挂载点-挂载文件系统添加到父级的挂载树
343         self.mount_fs
344             .mountpoints
345             .lock()
346             .insert(metadata.inode_id, new_mount_fs.clone());
347         return Ok(new_mount_fs);
348     }
349 }
350 
351 impl FileSystem for MountFS {
352     fn root_inode(&self) -> Arc<dyn IndexNode> {
353         match &self.self_mountpoint {
354             Some(inode) => return inode.mount_fs.root_inode(),
355             // 当前文件系统是rootfs
356             None => self.mountpoint_root_inode(),
357         }
358     }
359 
360     fn info(&self) -> super::FsInfo {
361         return self.inner_filesystem.info();
362     }
363 
364     /// @brief 本函数用于实现动态转换。
365     /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
366     fn as_any_ref(&self) -> &dyn Any {
367         self
368     }
369 }
370