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