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