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