16b4e7a29SLoGin use core::{hint::spin_loop, sync::atomic::Ordering}; 2004e86ffSlogin 3b5b571e0SLoGin use alloc::{string::ToString, sync::Arc}; 491e9d4abSLoGin use system_error::SystemError; 5004e86ffSlogin 6004e86ffSlogin use crate::{ 782df0a13Shmt driver::{base::block::disk_info::Partition, disk::ahci}, 8004e86ffSlogin filesystem::{ 9b087521eSChiichen devfs::devfs_init, 10004e86ffSlogin fat::fs::FATFileSystem, 11b087521eSChiichen procfs::procfs_init, 12004e86ffSlogin ramfs::RamFS, 13b087521eSChiichen sysfs::sysfs_init, 146b4e7a29SLoGin vfs::{mount::MountFS, syscall::ModeType, AtomicInodeId, FileSystem, FileType}, 15004e86ffSlogin }, 161074eb34SSamuel Dai kerror, kinfo, 17bf4a4899SLoGin process::ProcessManager, 18004e86ffSlogin }; 19004e86ffSlogin 20bf4a4899SLoGin use super::{ 211074eb34SSamuel Dai fcntl::AtFlags, 22bf4a4899SLoGin file::FileMode, 231074eb34SSamuel Dai mount::{init_mountlist, MOUNT_LIST}, 241074eb34SSamuel Dai syscall::UmountFlag, 25bf4a4899SLoGin utils::{rsplit_path, user_path_at}, 2682df0a13Shmt IndexNode, InodeId, VFS_MAX_FOLLOW_SYMLINK_TIMES, 27bf4a4899SLoGin }; 28004e86ffSlogin 29004e86ffSlogin /// @brief 原子地生成新的Inode号。 30004e86ffSlogin /// 请注意,所有的inode号都需要通过该函数来生成.全局的inode号,除了以下两个特殊的以外,都是唯一的 31004e86ffSlogin /// 特殊的两个inode号: 32004e86ffSlogin /// [0]: 对应'.'目录项 33004e86ffSlogin /// [1]: 对应'..'目录项 34004e86ffSlogin pub fn generate_inode_id() -> InodeId { 356b4e7a29SLoGin static INO: AtomicInodeId = AtomicInodeId::new(InodeId::new(1)); 366b4e7a29SLoGin return INO.fetch_add(InodeId::new(1), Ordering::SeqCst); 37004e86ffSlogin } 38004e86ffSlogin 397ae679ddSLoGin static mut __ROOT_INODE: Option<Arc<dyn IndexNode>> = None; 40004e86ffSlogin 41004e86ffSlogin /// @brief 获取全局的根节点 42004e86ffSlogin #[inline(always)] 43004e86ffSlogin #[allow(non_snake_case)] 44004e86ffSlogin pub fn ROOT_INODE() -> Arc<dyn IndexNode> { 45004e86ffSlogin unsafe { 46004e86ffSlogin return __ROOT_INODE.as_ref().unwrap().clone(); 47004e86ffSlogin } 48004e86ffSlogin } 49004e86ffSlogin 505b59005fSLoGin /// 初始化虚拟文件系统 515b59005fSLoGin #[inline(never)] 525b59005fSLoGin pub fn vfs_init() -> Result<(), SystemError> { 53004e86ffSlogin // 使用Ramfs作为默认的根文件系统 54004e86ffSlogin let ramfs = RamFS::new(); 55004e86ffSlogin let mount_fs = MountFS::new(ramfs, None); 567ae679ddSLoGin let root_inode = mount_fs.root_inode(); 571074eb34SSamuel Dai init_mountlist(); 58004e86ffSlogin unsafe { 597ae679ddSLoGin __ROOT_INODE = Some(root_inode.clone()); 60004e86ffSlogin } 61004e86ffSlogin 62b087521eSChiichen procfs_init().expect("Failed to initialize procfs"); 63004e86ffSlogin 64b087521eSChiichen devfs_init().expect("Failed to initialize devfs"); 65004e86ffSlogin 66b087521eSChiichen sysfs_init().expect("Failed to initialize sysfs"); 67dd9f1fc1STingHuang 687ae679ddSLoGin let root_entries = ROOT_INODE().list().expect("VFS init failed"); 69b5b571e0SLoGin if !root_entries.is_empty() { 70004e86ffSlogin kinfo!("Successfully initialized VFS!"); 71004e86ffSlogin } 725b59005fSLoGin return Ok(()); 73004e86ffSlogin } 74004e86ffSlogin 75004e86ffSlogin /// @brief 迁移伪文件系统的inode 76004e86ffSlogin /// 请注意,为了避免删掉了伪文件系统内的信息,因此没有在原root inode那里调用unlink. 77676b8ef6SMork fn migrate_virtual_filesystem(new_fs: Arc<dyn FileSystem>) -> Result<(), SystemError> { 78004e86ffSlogin kinfo!("VFS: Migrating filesystems..."); 79004e86ffSlogin 80004e86ffSlogin let new_fs = MountFS::new(new_fs, None); 81004e86ffSlogin // 获取新的根文件系统的根节点的引用 827ae679ddSLoGin let new_root_inode = new_fs.root_inode(); 83004e86ffSlogin 841074eb34SSamuel Dai // ==== 在这里获取要被迁移的文件系统的inode并迁移 === 851074eb34SSamuel Dai // 因为是换根所以路径没有变化 861074eb34SSamuel Dai // 不需要重新注册挂载目录 871074eb34SSamuel Dai new_root_inode 881074eb34SSamuel Dai .mkdir("proc", ModeType::from_bits_truncate(0o755)) 891074eb34SSamuel Dai .expect("Unable to create /proc") 901074eb34SSamuel Dai .mount_from(ROOT_INODE().find("proc").expect("proc not mounted!")) 911074eb34SSamuel Dai .expect("Failed to migrate filesystem of proc"); 921074eb34SSamuel Dai new_root_inode 931074eb34SSamuel Dai .mkdir("dev", ModeType::from_bits_truncate(0o755)) 941074eb34SSamuel Dai .expect("Unable to create /dev") 951074eb34SSamuel Dai .mount_from(ROOT_INODE().find("dev").expect("dev not mounted!")) 961074eb34SSamuel Dai .expect("Failed to migrate filesystem of dev"); 971074eb34SSamuel Dai new_root_inode 981074eb34SSamuel Dai .mkdir("sys", ModeType::from_bits_truncate(0o755)) 991074eb34SSamuel Dai .expect("Unable to create /sys") 1001074eb34SSamuel Dai .mount_from(ROOT_INODE().find("sys").expect("sys not mounted!")) 1011074eb34SSamuel Dai .expect("Failed to migrate filesystem of sys"); 102c719ddc6SSaga1718 103004e86ffSlogin unsafe { 104004e86ffSlogin // drop旧的Root inode 1057ae679ddSLoGin let old_root_inode = __ROOT_INODE.take().unwrap(); 106004e86ffSlogin // 设置全局的新的ROOT Inode 1071074eb34SSamuel Dai __ROOT_INODE = Some(new_root_inode.clone()); 1081074eb34SSamuel Dai drop(old_root_inode); 109004e86ffSlogin } 110004e86ffSlogin 111004e86ffSlogin kinfo!("VFS: Migrate filesystems done!"); 112004e86ffSlogin 113004e86ffSlogin return Ok(()); 114004e86ffSlogin } 115004e86ffSlogin 116*731bc2b3SLoGin fn root_partition() -> Arc<Partition> { 117*731bc2b3SLoGin #[cfg(target_arch = "x86_64")] 118*731bc2b3SLoGin { 119*731bc2b3SLoGin return ahci::get_disks_by_name("ahci_disk_0".to_string()) 120004e86ffSlogin .unwrap() 121004e86ffSlogin .0 122004e86ffSlogin .lock() 123004e86ffSlogin .partitions[0] 124004e86ffSlogin .clone(); 125*731bc2b3SLoGin } 126*731bc2b3SLoGin 127*731bc2b3SLoGin #[cfg(target_arch = "riscv64")] 128*731bc2b3SLoGin { 129*731bc2b3SLoGin use crate::driver::base::block::block_device::BlockDevice; 130*731bc2b3SLoGin 131*731bc2b3SLoGin let virtio0 = crate::driver::block::virtio_blk::virtio_blk_0(); 132*731bc2b3SLoGin if virtio0.is_none() { 133*731bc2b3SLoGin kerror!("Failed to get virtio_blk_0"); 134*731bc2b3SLoGin loop { 135*731bc2b3SLoGin spin_loop(); 136*731bc2b3SLoGin } 137*731bc2b3SLoGin } 138*731bc2b3SLoGin 139*731bc2b3SLoGin let virtio0 = virtio0.unwrap(); 140*731bc2b3SLoGin return virtio0.partitions()[0].clone(); 141*731bc2b3SLoGin } 142*731bc2b3SLoGin } 143*731bc2b3SLoGin pub fn mount_root_fs() -> Result<(), SystemError> { 144*731bc2b3SLoGin kinfo!("Try to mount FAT32 as root fs..."); 145*731bc2b3SLoGin let partiton: Arc<Partition> = root_partition(); 146004e86ffSlogin 147676b8ef6SMork let fatfs: Result<Arc<FATFileSystem>, SystemError> = FATFileSystem::new(partiton); 148004e86ffSlogin if fatfs.is_err() { 149004e86ffSlogin kerror!( 150004e86ffSlogin "Failed to initialize fatfs, code={:?}", 151004e86ffSlogin fatfs.as_ref().err() 152004e86ffSlogin ); 153004e86ffSlogin loop { 154004e86ffSlogin spin_loop(); 155004e86ffSlogin } 156004e86ffSlogin } 157004e86ffSlogin let fatfs: Arc<FATFileSystem> = fatfs.unwrap(); 158004e86ffSlogin let r = migrate_virtual_filesystem(fatfs); 159004e86ffSlogin if r.is_err() { 160004e86ffSlogin kerror!("Failed to migrate virtual filesystem to FAT32!"); 161004e86ffSlogin loop { 162004e86ffSlogin spin_loop(); 163004e86ffSlogin } 164004e86ffSlogin } 165004e86ffSlogin kinfo!("Successfully migrate rootfs to FAT32!"); 166004e86ffSlogin 1671496ba7bSLoGin return Ok(()); 168004e86ffSlogin } 169004e86ffSlogin 170004e86ffSlogin /// @brief 创建文件/文件夹 1711074eb34SSamuel Dai pub fn do_mkdir_at( 1721074eb34SSamuel Dai dirfd: i32, 1731074eb34SSamuel Dai path: &str, 1741074eb34SSamuel Dai mode: FileMode, 1751074eb34SSamuel Dai ) -> Result<Arc<dyn IndexNode>, SystemError> { 1761074eb34SSamuel Dai // kdebug!("Call do mkdir at"); 1771074eb34SSamuel Dai let (mut current_inode, path) = 1781074eb34SSamuel Dai user_path_at(&ProcessManager::current_pcb(), dirfd, path.trim())?; 1791074eb34SSamuel Dai let (name, parent) = rsplit_path(&path); 1801074eb34SSamuel Dai if let Some(parent) = parent { 1811074eb34SSamuel Dai current_inode = current_inode.lookup(parent)?; 182004e86ffSlogin } 1831074eb34SSamuel Dai // kdebug!("mkdir at {:?}", current_inode.metadata()?.inode_id); 1841074eb34SSamuel Dai return current_inode.mkdir(name, ModeType::from_bits_truncate(mode.bits())); 185004e86ffSlogin } 186004e86ffSlogin 187821bb9a2SXshine /// @brief 删除文件夹 188bf4a4899SLoGin pub fn do_remove_dir(dirfd: i32, path: &str) -> Result<u64, SystemError> { 18982df0a13Shmt let path = path.trim(); 190004e86ffSlogin 191bf4a4899SLoGin let pcb = ProcessManager::current_pcb(); 1920fb515b0SLoGin let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?; 193bf4a4899SLoGin let (filename, parent_path) = rsplit_path(&remain_path); 1945eeefb8cSChenzx 1955eeefb8cSChenzx // 最后一项文件项为.时返回EINVAL 1965eeefb8cSChenzx if filename == "." { 1975eeefb8cSChenzx return Err(SystemError::EINVAL); 1985eeefb8cSChenzx } 1995eeefb8cSChenzx 200004e86ffSlogin // 查找父目录 201bf4a4899SLoGin let parent_inode: Arc<dyn IndexNode> = inode_begin 202bf4a4899SLoGin .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 203004e86ffSlogin 204004e86ffSlogin if parent_inode.metadata()?.file_type != FileType::Dir { 205676b8ef6SMork return Err(SystemError::ENOTDIR); 206004e86ffSlogin } 207004e86ffSlogin 2085eeefb8cSChenzx // 在目标点为symlink时也返回ENOTDIR 2095eeefb8cSChenzx let target_inode = parent_inode.find(filename)?; 210004e86ffSlogin if target_inode.metadata()?.file_type != FileType::Dir { 211676b8ef6SMork return Err(SystemError::ENOTDIR); 212004e86ffSlogin } 213004e86ffSlogin 214004e86ffSlogin // 删除文件夹 215004e86ffSlogin parent_inode.rmdir(filename)?; 216004e86ffSlogin 217004e86ffSlogin return Ok(0); 218004e86ffSlogin } 219004e86ffSlogin 220004e86ffSlogin /// @brief 删除文件 221bf4a4899SLoGin pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> { 22282df0a13Shmt let path = path.trim(); 22382df0a13Shmt 224bf4a4899SLoGin let pcb = ProcessManager::current_pcb(); 2250fb515b0SLoGin let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?; 226bf4a4899SLoGin let inode: Result<Arc<dyn IndexNode>, SystemError> = 227bf4a4899SLoGin inode_begin.lookup_follow_symlink(&remain_path, VFS_MAX_FOLLOW_SYMLINK_TIMES); 228004e86ffSlogin 229004e86ffSlogin if inode.is_err() { 230004e86ffSlogin let errno = inode.clone().unwrap_err(); 231004e86ffSlogin // 文件不存在,且需要创建 232676b8ef6SMork if errno == SystemError::ENOENT { 233676b8ef6SMork return Err(SystemError::ENOENT); 234004e86ffSlogin } 235004e86ffSlogin } 236004e86ffSlogin // 禁止在目录上unlink 237004e86ffSlogin if inode.unwrap().metadata()?.file_type == FileType::Dir { 238676b8ef6SMork return Err(SystemError::EPERM); 239004e86ffSlogin } 240004e86ffSlogin 241004e86ffSlogin let (filename, parent_path) = rsplit_path(path); 242004e86ffSlogin // 查找父目录 243bf4a4899SLoGin let parent_inode: Arc<dyn IndexNode> = inode_begin 244bf4a4899SLoGin .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 245004e86ffSlogin 246004e86ffSlogin if parent_inode.metadata()?.file_type != FileType::Dir { 247676b8ef6SMork return Err(SystemError::ENOTDIR); 248004e86ffSlogin } 249004e86ffSlogin 250004e86ffSlogin // 删除文件 251004e86ffSlogin parent_inode.unlink(filename)?; 252004e86ffSlogin 253004e86ffSlogin return Ok(0); 254004e86ffSlogin } 2551d37ca6dSDonkey Kane 2561074eb34SSamuel Dai /// # do_mount - 挂载文件系统 2571074eb34SSamuel Dai /// 2581074eb34SSamuel Dai /// 将给定的文件系统挂载到指定的挂载点。 2591074eb34SSamuel Dai /// 2601074eb34SSamuel Dai /// 此函数会检查是否已经挂载了相同的文件系统,如果已经挂载,则返回错误。 2611074eb34SSamuel Dai /// 它还会处理符号链接,并确保挂载点是有效的。 2621074eb34SSamuel Dai /// 2631074eb34SSamuel Dai /// ## 参数 2641074eb34SSamuel Dai /// 2651074eb34SSamuel Dai /// - `fs`: Arc<dyn FileSystem>,要挂载的文件系统。 2661074eb34SSamuel Dai /// - `mount_point`: &str,挂载点路径。 2671074eb34SSamuel Dai /// 2681074eb34SSamuel Dai /// ## 返回值 2691074eb34SSamuel Dai /// 2701074eb34SSamuel Dai /// - `Ok(Arc<MountFS>)`: 挂载成功后返回挂载的文件系统。 2711074eb34SSamuel Dai /// - `Err(SystemError)`: 挂载失败时返回错误。 2721074eb34SSamuel Dai pub fn do_mount(fs: Arc<dyn FileSystem>, mount_point: &str) -> Result<Arc<MountFS>, SystemError> { 2731074eb34SSamuel Dai let (current_node, rest_path) = user_path_at( 2741074eb34SSamuel Dai &ProcessManager::current_pcb(), 2751074eb34SSamuel Dai AtFlags::AT_FDCWD.bits(), 2761074eb34SSamuel Dai mount_point, 2771074eb34SSamuel Dai )?; 2781074eb34SSamuel Dai let inode = current_node.lookup_follow_symlink(&rest_path, VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 2791074eb34SSamuel Dai if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { 2801074eb34SSamuel Dai if rest.is_empty() { 2811074eb34SSamuel Dai return Err(SystemError::EBUSY); 2821074eb34SSamuel Dai } 2831074eb34SSamuel Dai } 2841074eb34SSamuel Dai // 移至IndexNode.mount()来记录 2851074eb34SSamuel Dai return inode.mount(fs); 2861074eb34SSamuel Dai } 2871074eb34SSamuel Dai 2881074eb34SSamuel Dai /// # do_mount_mkdir - 在指定挂载点创建目录并挂载文件系统 2891074eb34SSamuel Dai /// 2901074eb34SSamuel Dai /// 在指定的挂载点创建一个目录,并将其挂载到文件系统中。如果挂载点已经存在,并且不是空的, 2911074eb34SSamuel Dai /// 则会返回错误。成功时,会返回一个新的挂载文件系统的引用。 2921074eb34SSamuel Dai /// 2931074eb34SSamuel Dai /// ## 参数 2941074eb34SSamuel Dai /// 2951074eb34SSamuel Dai /// - `fs`: FileSystem - 文件系统的引用,用于创建和挂载目录。 2961074eb34SSamuel Dai /// - `mount_point`: &str - 挂载点路径,用于创建和挂载目录。 2971074eb34SSamuel Dai /// 2981074eb34SSamuel Dai /// ## 返回值 2991074eb34SSamuel Dai /// 3001074eb34SSamuel Dai /// - `Ok(Arc<MountFS>)`: 成功挂载文件系统后,返回挂载文件系统的共享引用。 3011074eb34SSamuel Dai /// - `Err(SystemError)`: 挂载失败时,返回系统错误。 3021074eb34SSamuel Dai pub fn do_mount_mkdir( 3031074eb34SSamuel Dai fs: Arc<dyn FileSystem>, 3041074eb34SSamuel Dai mount_point: &str, 3051074eb34SSamuel Dai ) -> Result<Arc<MountFS>, SystemError> { 3061074eb34SSamuel Dai let inode = do_mkdir_at( 3071074eb34SSamuel Dai AtFlags::AT_FDCWD.bits(), 3081074eb34SSamuel Dai mount_point, 3091074eb34SSamuel Dai FileMode::from_bits_truncate(0o755), 3101074eb34SSamuel Dai )?; 3111074eb34SSamuel Dai if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { 3121074eb34SSamuel Dai if rest.is_empty() { 3131074eb34SSamuel Dai return Err(SystemError::EBUSY); 3141074eb34SSamuel Dai } 3151074eb34SSamuel Dai } 3161074eb34SSamuel Dai return inode.mount(fs); 3171074eb34SSamuel Dai } 3181074eb34SSamuel Dai 3191074eb34SSamuel Dai /// # do_umount2 - 执行卸载文件系统的函数 3201074eb34SSamuel Dai /// 3211074eb34SSamuel Dai /// 这个函数用于卸载指定的文件系统。 3221074eb34SSamuel Dai /// 3231074eb34SSamuel Dai /// ## 参数 3241074eb34SSamuel Dai /// 3251074eb34SSamuel Dai /// - dirfd: i32 - 目录文件描述符,用于指定要卸载的文件系统的根目录。 3261074eb34SSamuel Dai /// - target: &str - 要卸载的文件系统的目标路径。 3271074eb34SSamuel Dai /// - _flag: UmountFlag - 卸载标志,目前未使用。 3281074eb34SSamuel Dai /// 3291074eb34SSamuel Dai /// ## 返回值 3301074eb34SSamuel Dai /// 3311074eb34SSamuel Dai /// - Ok(Arc<MountFS>): 成功时返回文件系统的 Arc 引用。 3321074eb34SSamuel Dai /// - Err(SystemError): 出错时返回系统错误。 3331074eb34SSamuel Dai /// 3341074eb34SSamuel Dai /// ## 错误处理 3351074eb34SSamuel Dai /// 3361074eb34SSamuel Dai /// 如果指定的路径没有对应的文件系统,或者在尝试卸载时发生错误,将返回错误。 3371074eb34SSamuel Dai pub fn do_umount2( 3381074eb34SSamuel Dai dirfd: i32, 3391074eb34SSamuel Dai target: &str, 3401074eb34SSamuel Dai _flag: UmountFlag, 3411074eb34SSamuel Dai ) -> Result<Arc<MountFS>, SystemError> { 3421074eb34SSamuel Dai let (work, rest) = user_path_at(&ProcessManager::current_pcb(), dirfd, target)?; 3431074eb34SSamuel Dai let path = work.absolute_path()? + &rest; 3441074eb34SSamuel Dai let do_umount = || -> Result<Arc<MountFS>, SystemError> { 3451074eb34SSamuel Dai if let Some(fs) = MOUNT_LIST().remove(path) { 3461074eb34SSamuel Dai // Todo: 占用检测 3471074eb34SSamuel Dai fs.umount()?; 3481074eb34SSamuel Dai return Ok(fs); 3491074eb34SSamuel Dai } 3501074eb34SSamuel Dai return Err(SystemError::EINVAL); 3511074eb34SSamuel Dai }; 3521074eb34SSamuel Dai return do_umount(); 3531d37ca6dSDonkey Kane } 354