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