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