xref: /DragonOS/kernel/src/filesystem/vfs/mount.rs (revision 45b8371173b070028457f7ee64be33f68b4f9ada)
1 use core::any::Any;
2 
3 use alloc::{
4     collections::BTreeMap,
5     sync::{Arc, Weak},
6 };
7 
8 use crate::{
9     include::bindings::bindings::{EBUSY, ENOTDIR},
10     libs::spinlock::SpinLock,
11 };
12 
13 use super::{FilePrivateData, FileSystem, FileType, IndexNode, InodeId, file::FileMode};
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         let ptr: *mut MountFSInode = Arc::into_raw(inode) as *mut Self;
98         unsafe {
99             (*ptr).self_ref = weak;
100 
101             // 返回初始化好的MountFSInode对象
102             return Arc::from_raw(ptr);
103         }
104     }
105 
106     /// @brief 判断当前inode是否为它所在的文件系统的root inode
107     fn is_mountpoint_root(&self) -> Result<bool, i32> {
108         return Ok(self.inner_inode.fs().root_inode().metadata()?.inode_id
109             == self.inner_inode.metadata()?.inode_id);
110     }
111 
112     /// @brief 在挂载树上进行inode替换。
113     /// 如果当前inode是父MountFS内的一个挂载点,那么,本函数将会返回挂载到这个挂载点下的文件系统的root inode.
114     /// 如果当前inode在父MountFS内,但不是挂载点,那么说明在这里不需要进行inode替换,因此直接返回当前inode。
115     ///
116     /// @return Arc<MountFSInode>
117     fn overlaid_inode(&self) -> Arc<MountFSInode> {
118         let inode_id = self.metadata().unwrap().inode_id;
119 
120         if let Some(sub_mountfs) = self.mount_fs.mountpoints.lock().get(&inode_id) {
121             return sub_mountfs.mountpoint_root_inode();
122         } else {
123             return self.self_ref.upgrade().unwrap();
124         }
125     }
126 }
127 
128 impl IndexNode for MountFSInode {
129     fn open(&self, data: &mut FilePrivateData, mode: &FileMode) -> Result<(), i32> {
130         return self.inner_inode.open(data, mode);
131     }
132 
133     fn close(&self, data: &mut FilePrivateData) -> Result<(), i32> {
134         return self.inner_inode.close(data);
135     }
136 
137     fn create_with_data(
138         &self,
139         name: &str,
140         file_type: FileType,
141         mode: u32,
142         data: usize,
143     ) -> Result<Arc<dyn IndexNode>, i32> {
144         return self
145             .inner_inode
146             .create_with_data(name, file_type, mode, data);
147     }
148 
149     fn truncate(&self, len: usize) -> Result<(), i32> {
150         return self.inner_inode.truncate(len);
151     }
152 
153     fn read_at(
154         &self,
155         offset: usize,
156         len: usize,
157         buf: &mut [u8],
158         data: &mut FilePrivateData,
159     ) -> Result<usize, i32> {
160         return self.inner_inode.read_at(offset, len, buf, data);
161     }
162 
163     fn write_at(
164         &self,
165         offset: usize,
166         len: usize,
167         buf: &[u8],
168         _data: &mut FilePrivateData,
169     ) -> Result<usize, i32> {
170         return self
171             .inner_inode
172             .write_at(offset, len, buf, &mut FilePrivateData::Unused);
173     }
174 
175     #[inline]
176     fn poll(&self) -> Result<super::PollStatus, i32> {
177         return self.inner_inode.poll();
178     }
179 
180     #[inline]
181     fn fs(&self) -> Arc<dyn FileSystem> {
182         return self.mount_fs.clone();
183     }
184 
185     #[inline]
186     fn as_any_ref(&self) -> &dyn core::any::Any {
187         return self.inner_inode.as_any_ref();
188     }
189 
190     #[inline]
191     fn metadata(&self) -> Result<super::Metadata, i32> {
192         return self.inner_inode.metadata();
193     }
194 
195     #[inline]
196     fn set_metadata(&self, metadata: &super::Metadata) -> Result<(), i32> {
197         return self.inner_inode.set_metadata(metadata);
198     }
199 
200     #[inline]
201     fn resize(&self, len: usize) -> Result<(), i32> {
202         return self.inner_inode.resize(len);
203     }
204 
205     #[inline]
206     fn create(
207         &self,
208         name: &str,
209         file_type: FileType,
210         mode: u32,
211     ) -> Result<Arc<dyn IndexNode>, i32> {
212         return Ok(MountFSInode {
213             inner_inode: self.inner_inode.create(name, file_type, mode)?,
214             mount_fs: self.mount_fs.clone(),
215             self_ref: Weak::default(),
216         }
217         .wrap());
218     }
219 
220     fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), i32> {
221         return self.inner_inode.link(name, other);
222     }
223 
224     /// @brief 在挂载文件系统中删除文件/文件夹
225     #[inline]
226     fn unlink(&self, name: &str) -> Result<(), i32> {
227         let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id;
228 
229         // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode
230         if self.mount_fs.mountpoints.lock().contains_key(&inode_id) {
231             return Err(-(EBUSY as i32));
232         }
233         // 调用内层的inode的方法来删除这个inode
234         return self.inner_inode.unlink(name);
235     }
236 
237     #[inline]
238     fn rmdir(&self, name: &str) -> Result<(), i32> {
239         let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id;
240 
241         // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode
242         if self.mount_fs.mountpoints.lock().contains_key(&inode_id) {
243             return Err(-(EBUSY as i32));
244         }
245         // 调用内层的rmdir的方法来删除这个inode
246         let r = self.inner_inode.rmdir(name);
247 
248         return r;
249     }
250 
251     #[inline]
252     fn move_(
253         &self,
254         old_name: &str,
255         target: &Arc<dyn IndexNode>,
256         new_name: &str,
257     ) -> Result<(), i32> {
258         return self.inner_inode.move_(old_name, target, new_name);
259     }
260 
261     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, i32> {
262         match name {
263             // 查找的是当前目录
264             "" | "." => return Ok(self.self_ref.upgrade().unwrap()),
265             // 往父级查找
266             ".." => {
267                 if self.is_mountpoint_root()? {
268                     // 当前inode是它所在的文件系统的root inode
269                     match &self.mount_fs.self_mountpoint {
270                         Some(inode) => {
271                             return inode.find(name);
272                         }
273                         None => {
274                             return Ok(self.self_ref.upgrade().unwrap());
275                         }
276                     }
277                 } else {
278                     // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找
279                     return Ok(MountFSInode {
280                         inner_inode: self.inner_inode.find(name)?,
281                         mount_fs: self.mount_fs.clone(),
282                         self_ref: Weak::default(),
283                     }
284                     .wrap());
285                 }
286             }
287             // 在当前目录下查找
288             _ => {
289                 // 直接调用当前inode所在的文件系统的find方法进行查找
290                 // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode
291                 return Ok(MountFSInode {
292                     inner_inode: self.inner_inode.find(name)?,
293                     mount_fs: self.mount_fs.clone(),
294                     self_ref: Weak::default(),
295                 }
296                 .wrap()
297                 .overlaid_inode());
298             }
299         }
300     }
301 
302     #[inline]
303     fn get_entry_name(&self, ino: InodeId) -> Result<alloc::string::String, i32> {
304         return self.inner_inode.get_entry_name(ino);
305     }
306 
307     #[inline]
308     fn get_entry_name_and_metadata(
309         &self,
310         ino: InodeId,
311     ) -> Result<(alloc::string::String, super::Metadata), i32> {
312         return self.inner_inode.get_entry_name_and_metadata(ino);
313     }
314 
315     #[inline]
316     fn ioctl(&self, cmd: u32, data: usize) -> Result<usize, i32> {
317         return self.inner_inode.ioctl(cmd, data);
318     }
319 
320     #[inline]
321     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, i32> {
322         return self.inner_inode.list();
323     }
324 
325     /// @brief 在当前inode下,挂载一个文件系统
326     ///
327     /// @return Ok(Arc<MountFS>) 挂载成功,返回指向MountFS的指针
328     fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, i32> {
329         let metadata = self.inner_inode.metadata()?;
330         if metadata.file_type != FileType::Dir {
331             return Err(-(ENOTDIR as i32));
332         }
333 
334         // 为新的挂载点创建挂载文件系统
335         let new_mount_fs: Arc<MountFS> = MountFS::new(fs, Some(self.self_ref.upgrade().unwrap()));
336         // 将新的挂载点-挂载文件系统添加到父级的挂载树
337         self.mount_fs
338             .mountpoints
339             .lock()
340             .insert(metadata.inode_id, new_mount_fs.clone());
341         return Ok(new_mount_fs);
342     }
343 }
344 
345 impl FileSystem for MountFS {
346     fn root_inode(&self) -> Arc<dyn IndexNode> {
347         match &self.self_mountpoint {
348             Some(inode) => return inode.mount_fs.root_inode(),
349             // 当前文件系统是rootfs
350             None => self.mountpoint_root_inode(),
351         }
352     }
353 
354     fn info(&self) -> super::FsInfo {
355         return self.inner_filesystem.info();
356     }
357 
358     /// @brief 本函数用于实现动态转换。
359     /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self
360     fn as_any_ref(&self) -> &dyn Any {
361         self
362     }
363 }
364