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