1 use core::{ 2 any::Any, 3 fmt::Debug, 4 sync::atomic::{compiler_fence, Ordering}, 5 }; 6 7 use alloc::{ 8 collections::BTreeMap, 9 string::{String, ToString}, 10 sync::{Arc, Weak}, 11 }; 12 use system_error::SystemError; 13 14 use crate::{ 15 driver::base::device::device_number::DeviceNumber, 16 filesystem::vfs::ROOT_INODE, 17 libs::{ 18 casting::DowncastArc, 19 rwlock::RwLock, 20 spinlock::{SpinLock, SpinLockGuard}, 21 }, 22 }; 23 24 use super::{ 25 file::FileMode, syscall::ModeType, utils::DName, FilePrivateData, FileSystem, FileType, 26 IndexNode, InodeId, Magic, SuperBlock, 27 }; 28 29 const MOUNTFS_BLOCK_SIZE: u64 = 512; 30 const MOUNTFS_MAX_NAMELEN: u64 = 64; 31 /// @brief 挂载文件系统 32 /// 挂载文件系统的时候,套了MountFS这一层,以实现文件系统的递归挂载 33 #[derive(Debug)] 34 pub struct MountFS { 35 // MountFS内部的文件系统 36 inner_filesystem: Arc<dyn FileSystem>, 37 /// 用来存储InodeID->挂载点的MountFS的B树 38 mountpoints: SpinLock<BTreeMap<InodeId, Arc<MountFS>>>, 39 /// 当前文件系统挂载到的那个挂载点的Inode 40 self_mountpoint: Option<Arc<MountFSInode>>, 41 /// 指向当前MountFS的弱引用 42 self_ref: Weak<MountFS>, 43 } 44 45 /// @brief MountFS的Index Node 注意,这个IndexNode只是一个中间层。它的目的是将具体文件系统的Inode与挂载机制连接在一起。 46 #[derive(Debug)] 47 #[cast_to([sync] IndexNode)] 48 pub struct MountFSInode { 49 /// 当前挂载点对应到具体的文件系统的Inode 50 inner_inode: Arc<dyn IndexNode>, 51 /// 当前Inode对应的MountFS 52 mount_fs: Arc<MountFS>, 53 /// 指向自身的弱引用 54 self_ref: Weak<MountFSInode>, 55 } 56 57 impl MountFS { 58 pub fn new( 59 inner_filesystem: Arc<dyn FileSystem>, 60 self_mountpoint: Option<Arc<MountFSInode>>, 61 ) -> Arc<Self> { 62 return Arc::new_cyclic(|self_ref| MountFS { 63 inner_filesystem, 64 mountpoints: SpinLock::new(BTreeMap::new()), 65 self_mountpoint, 66 self_ref: self_ref.clone(), 67 }); 68 } 69 70 /// @brief 用Arc指针包裹MountFS对象。 71 /// 本函数的主要功能为,初始化MountFS对象中的自引用Weak指针 72 /// 本函数只应在构造器中被调用 73 #[allow(dead_code)] 74 #[deprecated] 75 fn wrap(self) -> Arc<Self> { 76 // 创建Arc指针 77 let mount_fs: Arc<MountFS> = Arc::new(self); 78 // 创建weak指针 79 let weak: Weak<MountFS> = Arc::downgrade(&mount_fs); 80 81 // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值 82 let ptr: *mut MountFS = mount_fs.as_ref() as *const Self as *mut Self; 83 unsafe { 84 (*ptr).self_ref = weak; 85 // 返回初始化好的MountFS对象 86 return mount_fs; 87 } 88 } 89 90 /// @brief 获取挂载点的文件系统的root inode 91 pub fn mountpoint_root_inode(&self) -> Arc<MountFSInode> { 92 return Arc::new_cyclic(|self_ref| MountFSInode { 93 inner_inode: self.inner_filesystem.root_inode(), 94 mount_fs: self.self_ref.upgrade().unwrap(), 95 self_ref: self_ref.clone(), 96 }); 97 } 98 99 pub fn inner_filesystem(&self) -> Arc<dyn FileSystem> { 100 return self.inner_filesystem.clone(); 101 } 102 103 pub fn self_ref(&self) -> Arc<Self> { 104 self.self_ref.upgrade().unwrap() 105 } 106 107 /// 卸载文件系统 108 /// # Errors 109 /// 如果当前文件系统是根文件系统,那么将会返回`EINVAL` 110 pub fn umount(&self) -> Result<Arc<MountFS>, SystemError> { 111 self.self_mountpoint 112 .as_ref() 113 .ok_or(SystemError::EINVAL)? 114 .do_umount() 115 } 116 } 117 118 impl MountFSInode { 119 /// @brief 用Arc指针包裹MountFSInode对象。 120 /// 本函数的主要功能为,初始化MountFSInode对象中的自引用Weak指针 121 /// 本函数只应在构造器中被调用 122 #[allow(dead_code)] 123 #[deprecated] 124 fn wrap(self) -> Arc<Self> { 125 // 创建Arc指针 126 let inode: Arc<MountFSInode> = Arc::new(self); 127 // 创建Weak指针 128 let weak: Weak<MountFSInode> = Arc::downgrade(&inode); 129 // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值 130 compiler_fence(Ordering::SeqCst); 131 let ptr: *mut MountFSInode = inode.as_ref() as *const Self as *mut Self; 132 compiler_fence(Ordering::SeqCst); 133 unsafe { 134 (*ptr).self_ref = weak; 135 compiler_fence(Ordering::SeqCst); 136 137 // 返回初始化好的MountFSInode对象 138 return inode; 139 } 140 } 141 142 /// @brief 判断当前inode是否为它所在的文件系统的root inode 143 fn is_mountpoint_root(&self) -> Result<bool, SystemError> { 144 return Ok(self.inner_inode.fs().root_inode().metadata()?.inode_id 145 == self.inner_inode.metadata()?.inode_id); 146 } 147 148 /// @brief 在挂载树上进行inode替换。 149 /// 如果当前inode是父MountFS内的一个挂载点,那么,本函数将会返回挂载到这个挂载点下的文件系统的root inode. 150 /// 如果当前inode在父MountFS内,但不是挂载点,那么说明在这里不需要进行inode替换,因此直接返回当前inode。 151 /// 152 /// @return Arc<MountFSInode> 153 fn overlaid_inode(&self) -> Arc<MountFSInode> { 154 let inode_id = self.metadata().unwrap().inode_id; 155 156 if let Some(sub_mountfs) = self.mount_fs.mountpoints.lock().get(&inode_id) { 157 return sub_mountfs.mountpoint_root_inode(); 158 } else { 159 return self.self_ref.upgrade().unwrap(); 160 } 161 } 162 163 fn do_find(&self, name: &str) -> Result<Arc<MountFSInode>, SystemError> { 164 // 直接调用当前inode所在的文件系统的find方法进行查找 165 // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode 166 let inner_inode = self.inner_inode.find(name)?; 167 return Ok(Arc::new_cyclic(|self_ref| MountFSInode { 168 inner_inode, 169 mount_fs: self.mount_fs.clone(), 170 self_ref: self_ref.clone(), 171 }) 172 .overlaid_inode()); 173 } 174 175 pub(super) fn do_parent(&self) -> Result<Arc<MountFSInode>, SystemError> { 176 if self.is_mountpoint_root()? { 177 // 当前inode是它所在的文件系统的root inode 178 match &self.mount_fs.self_mountpoint { 179 Some(inode) => { 180 let inner_inode = inode.parent()?; 181 return Ok(Arc::new_cyclic(|self_ref| MountFSInode { 182 inner_inode, 183 mount_fs: self.mount_fs.clone(), 184 self_ref: self_ref.clone(), 185 })); 186 } 187 None => { 188 return Ok(self.self_ref.upgrade().unwrap()); 189 } 190 } 191 } else { 192 let inner_inode = self.inner_inode.parent()?; 193 // 向上查找时,不会跨过文件系统的边界,因此直接调用当前inode所在的文件系统的find方法进行查找 194 return Ok(Arc::new_cyclic(|self_ref| MountFSInode { 195 inner_inode, 196 mount_fs: self.mount_fs.clone(), 197 self_ref: self_ref.clone(), 198 })); 199 } 200 } 201 202 /// 移除挂载点下的文件系统 203 fn do_umount(&self) -> Result<Arc<MountFS>, SystemError> { 204 if self.metadata()?.file_type != FileType::Dir { 205 return Err(SystemError::ENOTDIR); 206 } 207 return self 208 .mount_fs 209 .mountpoints 210 .lock() 211 .remove(&self.inner_inode.metadata()?.inode_id) 212 .ok_or(SystemError::ENOENT); 213 } 214 215 fn do_absolute_path(&self, len: usize) -> Result<String, SystemError> { 216 if self.metadata()?.inode_id == ROOT_INODE().metadata()?.inode_id { 217 return Ok(String::with_capacity(len)); 218 } 219 let name = self.dname()?; 220 return Ok(self.do_parent()?.do_absolute_path(len + name.0.len() + 1)? + "/" + &name.0); 221 } 222 } 223 224 impl IndexNode for MountFSInode { 225 fn open( 226 &self, 227 data: SpinLockGuard<FilePrivateData>, 228 mode: &FileMode, 229 ) -> Result<(), SystemError> { 230 return self.inner_inode.open(data, mode); 231 } 232 233 fn close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> { 234 return self.inner_inode.close(data); 235 } 236 237 fn create_with_data( 238 &self, 239 name: &str, 240 file_type: FileType, 241 mode: ModeType, 242 data: usize, 243 ) -> Result<Arc<dyn IndexNode>, SystemError> { 244 let inner_inode = self 245 .inner_inode 246 .create_with_data(name, file_type, mode, data)?; 247 return Ok(Arc::new_cyclic(|self_ref| MountFSInode { 248 inner_inode, 249 mount_fs: self.mount_fs.clone(), 250 self_ref: self_ref.clone(), 251 })); 252 } 253 254 fn truncate(&self, len: usize) -> Result<(), SystemError> { 255 return self.inner_inode.truncate(len); 256 } 257 258 fn read_at( 259 &self, 260 offset: usize, 261 len: usize, 262 buf: &mut [u8], 263 data: SpinLockGuard<FilePrivateData>, 264 ) -> Result<usize, SystemError> { 265 return self.inner_inode.read_at(offset, len, buf, data); 266 } 267 268 fn write_at( 269 &self, 270 offset: usize, 271 len: usize, 272 buf: &[u8], 273 data: SpinLockGuard<FilePrivateData>, 274 ) -> Result<usize, SystemError> { 275 return self.inner_inode.write_at(offset, len, buf, data); 276 } 277 278 #[inline] 279 fn fs(&self) -> Arc<dyn FileSystem> { 280 return self.mount_fs.clone(); 281 } 282 283 #[inline] 284 fn as_any_ref(&self) -> &dyn core::any::Any { 285 return self.inner_inode.as_any_ref(); 286 } 287 288 #[inline] 289 fn metadata(&self) -> Result<super::Metadata, SystemError> { 290 return self.inner_inode.metadata(); 291 } 292 293 #[inline] 294 fn set_metadata(&self, metadata: &super::Metadata) -> Result<(), SystemError> { 295 return self.inner_inode.set_metadata(metadata); 296 } 297 298 #[inline] 299 fn resize(&self, len: usize) -> Result<(), SystemError> { 300 return self.inner_inode.resize(len); 301 } 302 303 #[inline] 304 fn create( 305 &self, 306 name: &str, 307 file_type: FileType, 308 mode: ModeType, 309 ) -> Result<Arc<dyn IndexNode>, SystemError> { 310 let inner_inode = self.inner_inode.create(name, file_type, mode)?; 311 return Ok(Arc::new_cyclic(|self_ref| MountFSInode { 312 inner_inode, 313 mount_fs: self.mount_fs.clone(), 314 self_ref: self_ref.clone(), 315 })); 316 } 317 318 fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> { 319 return self.inner_inode.link(name, other); 320 } 321 322 /// @brief 在挂载文件系统中删除文件/文件夹 323 #[inline] 324 fn unlink(&self, name: &str) -> Result<(), SystemError> { 325 let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id; 326 327 // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode 328 if self.mount_fs.mountpoints.lock().contains_key(&inode_id) { 329 return Err(SystemError::EBUSY); 330 } 331 // 调用内层的inode的方法来删除这个inode 332 return self.inner_inode.unlink(name); 333 } 334 335 #[inline] 336 fn rmdir(&self, name: &str) -> Result<(), SystemError> { 337 let inode_id = self.inner_inode.find(name)?.metadata()?.inode_id; 338 339 // 先检查这个inode是否为一个挂载点,如果当前inode是一个挂载点,那么就不能删除这个inode 340 if self.mount_fs.mountpoints.lock().contains_key(&inode_id) { 341 return Err(SystemError::EBUSY); 342 } 343 // 调用内层的rmdir的方法来删除这个inode 344 let r = self.inner_inode.rmdir(name); 345 346 return r; 347 } 348 349 #[inline] 350 fn move_to( 351 &self, 352 old_name: &str, 353 target: &Arc<dyn IndexNode>, 354 new_name: &str, 355 ) -> Result<(), SystemError> { 356 return self.inner_inode.move_to(old_name, target, new_name); 357 } 358 359 fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> { 360 match name { 361 // 查找的是当前目录 362 "" | "." => self 363 .self_ref 364 .upgrade() 365 .map(|inode| inode as Arc<dyn IndexNode>) 366 .ok_or(SystemError::ENOENT), 367 // 往父级查找 368 ".." => self.parent(), 369 // 在当前目录下查找 370 // 直接调用当前inode所在的文件系统的find方法进行查找 371 // 由于向下查找可能会跨越文件系统的边界,因此需要尝试替换inode 372 _ => self.do_find(name).map(|inode| inode as Arc<dyn IndexNode>), 373 } 374 } 375 376 #[inline] 377 fn get_entry_name(&self, ino: InodeId) -> Result<alloc::string::String, SystemError> { 378 return self.inner_inode.get_entry_name(ino); 379 } 380 381 #[inline] 382 fn get_entry_name_and_metadata( 383 &self, 384 ino: InodeId, 385 ) -> Result<(alloc::string::String, super::Metadata), SystemError> { 386 return self.inner_inode.get_entry_name_and_metadata(ino); 387 } 388 389 #[inline] 390 fn ioctl( 391 &self, 392 cmd: u32, 393 data: usize, 394 private_data: &FilePrivateData, 395 ) -> Result<usize, SystemError> { 396 return self.inner_inode.ioctl(cmd, data, private_data); 397 } 398 399 #[inline] 400 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> { 401 return self.inner_inode.list(); 402 } 403 404 fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> { 405 let metadata = self.inner_inode.metadata()?; 406 if metadata.file_type != FileType::Dir { 407 return Err(SystemError::ENOTDIR); 408 } 409 410 if self.is_mountpoint_root()? { 411 return Err(SystemError::EBUSY); 412 } 413 414 // 若已有挂载系统,保证MountFS只包一层 415 let to_mount_fs = fs 416 .clone() 417 .downcast_arc::<MountFS>() 418 .map(|it| it.inner_filesystem()) 419 .unwrap_or(fs); 420 let new_mount_fs = MountFS::new(to_mount_fs, Some(self.self_ref.upgrade().unwrap())); 421 self.mount_fs 422 .mountpoints 423 .lock() 424 .insert(metadata.inode_id, new_mount_fs.clone()); 425 426 let mount_path = self.absolute_path(); 427 428 MOUNT_LIST().insert(mount_path?, new_mount_fs.clone()); 429 return Ok(new_mount_fs); 430 } 431 432 fn mount_from(&self, from: Arc<dyn IndexNode>) -> Result<Arc<MountFS>, SystemError> { 433 let metadata = self.metadata()?; 434 if from.metadata()?.file_type != FileType::Dir || metadata.file_type != FileType::Dir { 435 return Err(SystemError::ENOTDIR); 436 } 437 if self.is_mountpoint_root()? { 438 return Err(SystemError::EBUSY); 439 } 440 // debug!("from {:?}, to {:?}", from, self); 441 let new_mount_fs = from.umount()?; 442 self.mount_fs 443 .mountpoints 444 .lock() 445 .insert(metadata.inode_id, new_mount_fs.clone()); 446 447 // MOUNT_LIST().remove(from.absolute_path()?); 448 // MOUNT_LIST().insert(self.absolute_path()?, new_mount_fs.clone()); 449 return Ok(new_mount_fs); 450 } 451 452 fn umount(&self) -> Result<Arc<MountFS>, SystemError> { 453 if !self.is_mountpoint_root()? { 454 return Err(SystemError::EINVAL); 455 } 456 return self.mount_fs.umount(); 457 } 458 459 fn absolute_path(&self) -> Result<String, SystemError> { 460 self.do_absolute_path(0) 461 } 462 463 #[inline] 464 fn mknod( 465 &self, 466 filename: &str, 467 mode: ModeType, 468 dev_t: DeviceNumber, 469 ) -> Result<Arc<dyn IndexNode>, SystemError> { 470 let inner_inode = self.inner_inode.mknod(filename, mode, dev_t)?; 471 return Ok(Arc::new_cyclic(|self_ref| MountFSInode { 472 inner_inode, 473 mount_fs: self.mount_fs.clone(), 474 self_ref: self_ref.clone(), 475 })); 476 } 477 478 #[inline] 479 fn special_node(&self) -> Option<super::SpecialNodeData> { 480 self.inner_inode.special_node() 481 } 482 483 #[inline] 484 fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> { 485 self.inner_inode.poll(private_data) 486 } 487 488 /// 若不支持,则调用第二种情况来从父目录获取文件名 489 /// # Performance 490 /// 应尽可能引入DName, 491 /// 在默认情况下,性能非常差!!! 492 fn dname(&self) -> Result<DName, SystemError> { 493 if self.is_mountpoint_root()? { 494 if let Some(inode) = &self.mount_fs.self_mountpoint { 495 return inode.inner_inode.dname(); 496 } 497 } 498 return self.inner_inode.dname(); 499 } 500 501 fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> { 502 return self.do_parent().map(|inode| inode as Arc<dyn IndexNode>); 503 } 504 } 505 506 impl FileSystem for MountFS { 507 fn root_inode(&self) -> Arc<dyn IndexNode> { 508 match &self.self_mountpoint { 509 Some(inode) => return inode.mount_fs.root_inode(), 510 // 当前文件系统是rootfs 511 None => self.mountpoint_root_inode(), 512 } 513 } 514 515 fn info(&self) -> super::FsInfo { 516 return self.inner_filesystem.info(); 517 } 518 519 /// @brief 本函数用于实现动态转换。 520 /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self 521 fn as_any_ref(&self) -> &dyn Any { 522 self 523 } 524 525 fn name(&self) -> &str { 526 "mountfs" 527 } 528 fn super_block(&self) -> SuperBlock { 529 SuperBlock::new(Magic::MOUNT_MAGIC, MOUNTFS_BLOCK_SIZE, MOUNTFS_MAX_NAMELEN) 530 } 531 } 532 533 /// MountList 534 /// ```rust 535 /// use alloc::collection::BTreeSet; 536 /// let map = BTreeSet::from([ 537 /// "/sys", "/dev", "/", "/bin", "/proc" 538 /// ]); 539 /// assert_eq!(format!("{:?}", map), "{\"/\", \"/bin\", \"/dev\", \"/proc\", \"/sys\"}"); 540 /// // {"/", "/bin", "/dev", "/proc", "/sys"} 541 /// ``` 542 #[derive(PartialEq, Eq, Debug)] 543 pub struct MountPath(String); 544 545 impl From<&str> for MountPath { 546 fn from(value: &str) -> Self { 547 Self(String::from(value)) 548 } 549 } 550 551 impl From<String> for MountPath { 552 fn from(value: String) -> Self { 553 Self(value) 554 } 555 } 556 557 impl AsRef<str> for MountPath { 558 fn as_ref(&self) -> &str { 559 &self.0 560 } 561 } 562 563 impl PartialOrd for MountPath { 564 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { 565 Some(self.cmp(other)) 566 } 567 } 568 569 impl Ord for MountPath { 570 fn cmp(&self, other: &Self) -> core::cmp::Ordering { 571 let self_dep = self.0.chars().filter(|c| *c == '/').count(); 572 let othe_dep = other.0.chars().filter(|c| *c == '/').count(); 573 if self_dep == othe_dep { 574 // 深度一样时反序来排 575 // 根目录和根目录下的文件的绝对路径都只有一个'/' 576 other.0.cmp(&self.0) 577 } else { 578 // 根据深度,深度 579 othe_dep.cmp(&self_dep) 580 } 581 } 582 } 583 584 // 维护一个挂载点的记录,以支持特定于文件系统的索引 585 pub struct MountList(RwLock<BTreeMap<MountPath, Arc<MountFS>>>); 586 // pub struct MountList(Option<Arc<MountListInner>>); 587 static mut __MOUNTS_LIST: Option<Arc<MountList>> = None; 588 589 /// # init_mountlist - 初始化挂载列表 590 /// 591 /// 此函数用于初始化系统的挂载列表。挂载列表记录了系统中所有的文件系统挂载点及其属性。 592 /// 593 /// ## 参数 594 /// 595 /// - 无 596 /// 597 /// ## 返回值 598 /// 599 /// - 无 600 #[inline(always)] 601 pub fn init_mountlist() { 602 unsafe { 603 __MOUNTS_LIST = Some(Arc::new(MountList(RwLock::new(BTreeMap::new())))); 604 } 605 } 606 607 /// # MOUNT_LIST - 获取全局挂载列表 608 /// 609 /// 该函数用于获取一个对全局挂载列表的引用。全局挂载列表是系统中所有挂载点的集合。 610 /// 611 /// ## 返回值 612 /// - &'static Arc<MountList>: 返回全局挂载列表的引用。 613 #[inline(always)] 614 #[allow(non_snake_case)] 615 pub fn MOUNT_LIST() -> &'static Arc<MountList> { 616 unsafe { 617 return __MOUNTS_LIST.as_ref().unwrap(); 618 } 619 } 620 621 impl MountList { 622 /// # insert - 将文件系统挂载点插入到挂载表中 623 /// 624 /// 将一个新的文件系统挂载点插入到挂载表中。如果挂载点已经存在,则会更新对应的文件系统。 625 /// 626 /// 此函数是线程安全的,因为它使用了RwLock来保证并发访问。 627 /// 628 /// ## 参数 629 /// 630 /// - `path`: &str, 挂载点的路径。这个路径会被转换成`MountPath`类型。 631 /// - `fs`: Arc<MountFS>, 共享的文件系统实例。 632 /// 633 /// ## 返回值 634 /// 635 /// - 无 636 #[inline] 637 pub fn insert<T: AsRef<str>>(&self, path: T, fs: Arc<MountFS>) { 638 self.0.write().insert(MountPath::from(path.as_ref()), fs); 639 } 640 641 /// # get_mount_point - 获取挂载点的路径 642 /// 643 /// 这个函数用于查找给定路径的挂载点。它搜索一个内部映射,找到与路径匹配的挂载点。 644 /// 645 /// ## 参数 646 /// 647 /// - `path: T`: 这是一个可转换为字符串的引用,表示要查找其挂载点的路径。 648 /// 649 /// ## 返回值 650 /// 651 /// - `Option<(String, String, Arc<MountFS>)>`: 652 /// - `Some((mount_point, rest_path, fs))`: 如果找到了匹配的挂载点,返回一个包含挂载点路径、剩余路径和挂载文件系统的元组。 653 /// - `None`: 如果没有找到匹配的挂载点,返回 None。 654 #[inline] 655 #[allow(dead_code)] 656 pub fn get_mount_point<T: AsRef<str>>( 657 &self, 658 path: T, 659 ) -> Option<(String, String, Arc<MountFS>)> { 660 self.0 661 .upgradeable_read() 662 .iter() 663 .filter_map(|(key, fs)| { 664 let strkey = key.as_ref(); 665 if let Some(rest) = path.as_ref().strip_prefix(strkey) { 666 return Some((strkey.to_string(), rest.to_string(), fs.clone())); 667 } 668 None 669 }) 670 .next() 671 } 672 673 /// # remove - 移除挂载点 674 /// 675 /// 从挂载点管理器中移除一个挂载点。 676 /// 677 /// 此函数用于从挂载点管理器中移除一个已经存在的挂载点。如果挂载点不存在,则不进行任何操作。 678 /// 679 /// ## 参数 680 /// 681 /// - `path: T`: `T` 实现了 `Into<MountPath>` trait,代表要移除的挂载点的路径。 682 /// 683 /// ## 返回值 684 /// 685 /// - `Option<Arc<MountFS>>`: 返回一个 `Arc<MountFS>` 类型的可选值,表示被移除的挂载点,如果挂载点不存在则返回 `None`。 686 #[inline] 687 pub fn remove<T: Into<MountPath>>(&self, path: T) -> Option<Arc<MountFS>> { 688 self.0.write().remove(&path.into()) 689 } 690 } 691 692 impl Debug for MountList { 693 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 694 f.debug_map().entries(MOUNT_LIST().0.read().iter()).finish() 695 } 696 } 697