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