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