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::device_number::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