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