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