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