1 use core::{hint::spin_loop, sync::atomic::Ordering}; 2 3 use alloc::{string::ToString, sync::Arc}; 4 use system_error::SystemError; 5 6 use crate::{ 7 driver::{base::block::disk_info::Partition, disk::ahci}, 8 filesystem::{ 9 devfs::devfs_init, 10 fat::fs::FATFileSystem, 11 procfs::procfs_init, 12 ramfs::RamFS, 13 sysfs::sysfs_init, 14 vfs::{mount::MountFS, syscall::ModeType, AtomicInodeId, FileSystem, FileType}, 15 }, 16 kerror, kinfo, 17 process::ProcessManager, 18 }; 19 20 use super::{ 21 fcntl::AtFlags, 22 file::FileMode, 23 mount::{init_mountlist, MOUNT_LIST}, 24 syscall::UmountFlag, 25 utils::{rsplit_path, user_path_at}, 26 IndexNode, InodeId, VFS_MAX_FOLLOW_SYMLINK_TIMES, 27 }; 28 29 /// @brief 原子地生成新的Inode号。 30 /// 请注意,所有的inode号都需要通过该函数来生成.全局的inode号,除了以下两个特殊的以外,都是唯一的 31 /// 特殊的两个inode号: 32 /// [0]: 对应'.'目录项 33 /// [1]: 对应'..'目录项 34 pub fn generate_inode_id() -> InodeId { 35 static INO: AtomicInodeId = AtomicInodeId::new(InodeId::new(1)); 36 return INO.fetch_add(InodeId::new(1), Ordering::SeqCst); 37 } 38 39 static mut __ROOT_INODE: Option<Arc<dyn IndexNode>> = None; 40 41 /// @brief 获取全局的根节点 42 #[inline(always)] 43 #[allow(non_snake_case)] 44 pub fn ROOT_INODE() -> Arc<dyn IndexNode> { 45 unsafe { 46 return __ROOT_INODE.as_ref().unwrap().clone(); 47 } 48 } 49 50 /// 初始化虚拟文件系统 51 #[inline(never)] 52 pub fn vfs_init() -> Result<(), SystemError> { 53 // 使用Ramfs作为默认的根文件系统 54 let ramfs = RamFS::new(); 55 let mount_fs = MountFS::new(ramfs, None); 56 let root_inode = mount_fs.root_inode(); 57 init_mountlist(); 58 unsafe { 59 __ROOT_INODE = Some(root_inode.clone()); 60 } 61 62 procfs_init().expect("Failed to initialize procfs"); 63 64 devfs_init().expect("Failed to initialize devfs"); 65 66 sysfs_init().expect("Failed to initialize sysfs"); 67 68 let root_entries = ROOT_INODE().list().expect("VFS init failed"); 69 if !root_entries.is_empty() { 70 kinfo!("Successfully initialized VFS!"); 71 } 72 return Ok(()); 73 } 74 75 /// @brief 迁移伪文件系统的inode 76 /// 请注意,为了避免删掉了伪文件系统内的信息,因此没有在原root inode那里调用unlink. 77 fn migrate_virtual_filesystem(new_fs: Arc<dyn FileSystem>) -> Result<(), SystemError> { 78 kinfo!("VFS: Migrating filesystems..."); 79 80 let new_fs = MountFS::new(new_fs, None); 81 // 获取新的根文件系统的根节点的引用 82 let new_root_inode = new_fs.root_inode(); 83 84 // ==== 在这里获取要被迁移的文件系统的inode并迁移 === 85 // 因为是换根所以路径没有变化 86 // 不需要重新注册挂载目录 87 new_root_inode 88 .mkdir("proc", ModeType::from_bits_truncate(0o755)) 89 .expect("Unable to create /proc") 90 .mount_from(ROOT_INODE().find("proc").expect("proc not mounted!")) 91 .expect("Failed to migrate filesystem of proc"); 92 new_root_inode 93 .mkdir("dev", ModeType::from_bits_truncate(0o755)) 94 .expect("Unable to create /dev") 95 .mount_from(ROOT_INODE().find("dev").expect("dev not mounted!")) 96 .expect("Failed to migrate filesystem of dev"); 97 new_root_inode 98 .mkdir("sys", ModeType::from_bits_truncate(0o755)) 99 .expect("Unable to create /sys") 100 .mount_from(ROOT_INODE().find("sys").expect("sys not mounted!")) 101 .expect("Failed to migrate filesystem of sys"); 102 103 unsafe { 104 // drop旧的Root inode 105 let old_root_inode = __ROOT_INODE.take().unwrap(); 106 // 设置全局的新的ROOT Inode 107 __ROOT_INODE = Some(new_root_inode.clone()); 108 drop(old_root_inode); 109 } 110 111 kinfo!("VFS: Migrate filesystems done!"); 112 113 return Ok(()); 114 } 115 116 pub fn mount_root_fs() -> Result<(), SystemError> { 117 kinfo!("Try to mount FAT32 as root fs..."); 118 let partiton: Arc<Partition> = ahci::get_disks_by_name("ahci_disk_0".to_string()) 119 .unwrap() 120 .0 121 .lock() 122 .partitions[0] 123 .clone(); 124 125 let fatfs: Result<Arc<FATFileSystem>, SystemError> = FATFileSystem::new(partiton); 126 if fatfs.is_err() { 127 kerror!( 128 "Failed to initialize fatfs, code={:?}", 129 fatfs.as_ref().err() 130 ); 131 loop { 132 spin_loop(); 133 } 134 } 135 let fatfs: Arc<FATFileSystem> = fatfs.unwrap(); 136 let r = migrate_virtual_filesystem(fatfs); 137 if r.is_err() { 138 kerror!("Failed to migrate virtual filesystem to FAT32!"); 139 loop { 140 spin_loop(); 141 } 142 } 143 kinfo!("Successfully migrate rootfs to FAT32!"); 144 145 return Ok(()); 146 } 147 148 /// @brief 创建文件/文件夹 149 pub fn do_mkdir_at( 150 dirfd: i32, 151 path: &str, 152 mode: FileMode, 153 ) -> Result<Arc<dyn IndexNode>, SystemError> { 154 // kdebug!("Call do mkdir at"); 155 let (mut current_inode, path) = 156 user_path_at(&ProcessManager::current_pcb(), dirfd, path.trim())?; 157 let (name, parent) = rsplit_path(&path); 158 if let Some(parent) = parent { 159 current_inode = current_inode.lookup(parent)?; 160 } 161 // kdebug!("mkdir at {:?}", current_inode.metadata()?.inode_id); 162 return current_inode.mkdir(name, ModeType::from_bits_truncate(mode.bits())); 163 } 164 165 /// @brief 删除文件夹 166 pub fn do_remove_dir(dirfd: i32, path: &str) -> Result<u64, SystemError> { 167 let path = path.trim(); 168 169 let pcb = ProcessManager::current_pcb(); 170 let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?; 171 let (filename, parent_path) = rsplit_path(&remain_path); 172 173 // 最后一项文件项为.时返回EINVAL 174 if filename == "." { 175 return Err(SystemError::EINVAL); 176 } 177 178 // 查找父目录 179 let parent_inode: Arc<dyn IndexNode> = inode_begin 180 .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 181 182 if parent_inode.metadata()?.file_type != FileType::Dir { 183 return Err(SystemError::ENOTDIR); 184 } 185 186 // 在目标点为symlink时也返回ENOTDIR 187 let target_inode = parent_inode.find(filename)?; 188 if target_inode.metadata()?.file_type != FileType::Dir { 189 return Err(SystemError::ENOTDIR); 190 } 191 192 // 删除文件夹 193 parent_inode.rmdir(filename)?; 194 195 return Ok(0); 196 } 197 198 /// @brief 删除文件 199 pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> { 200 let path = path.trim(); 201 202 let pcb = ProcessManager::current_pcb(); 203 let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?; 204 let inode: Result<Arc<dyn IndexNode>, SystemError> = 205 inode_begin.lookup_follow_symlink(&remain_path, VFS_MAX_FOLLOW_SYMLINK_TIMES); 206 207 if inode.is_err() { 208 let errno = inode.clone().unwrap_err(); 209 // 文件不存在,且需要创建 210 if errno == SystemError::ENOENT { 211 return Err(SystemError::ENOENT); 212 } 213 } 214 // 禁止在目录上unlink 215 if inode.unwrap().metadata()?.file_type == FileType::Dir { 216 return Err(SystemError::EPERM); 217 } 218 219 let (filename, parent_path) = rsplit_path(path); 220 // 查找父目录 221 let parent_inode: Arc<dyn IndexNode> = inode_begin 222 .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 223 224 if parent_inode.metadata()?.file_type != FileType::Dir { 225 return Err(SystemError::ENOTDIR); 226 } 227 228 // 删除文件 229 parent_inode.unlink(filename)?; 230 231 return Ok(0); 232 } 233 234 /// # do_mount - 挂载文件系统 235 /// 236 /// 将给定的文件系统挂载到指定的挂载点。 237 /// 238 /// 此函数会检查是否已经挂载了相同的文件系统,如果已经挂载,则返回错误。 239 /// 它还会处理符号链接,并确保挂载点是有效的。 240 /// 241 /// ## 参数 242 /// 243 /// - `fs`: Arc<dyn FileSystem>,要挂载的文件系统。 244 /// - `mount_point`: &str,挂载点路径。 245 /// 246 /// ## 返回值 247 /// 248 /// - `Ok(Arc<MountFS>)`: 挂载成功后返回挂载的文件系统。 249 /// - `Err(SystemError)`: 挂载失败时返回错误。 250 pub fn do_mount(fs: Arc<dyn FileSystem>, mount_point: &str) -> Result<Arc<MountFS>, SystemError> { 251 let (current_node, rest_path) = user_path_at( 252 &ProcessManager::current_pcb(), 253 AtFlags::AT_FDCWD.bits(), 254 mount_point, 255 )?; 256 let inode = current_node.lookup_follow_symlink(&rest_path, VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 257 if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { 258 if rest.is_empty() { 259 return Err(SystemError::EBUSY); 260 } 261 } 262 // 移至IndexNode.mount()来记录 263 return inode.mount(fs); 264 } 265 266 /// # do_mount_mkdir - 在指定挂载点创建目录并挂载文件系统 267 /// 268 /// 在指定的挂载点创建一个目录,并将其挂载到文件系统中。如果挂载点已经存在,并且不是空的, 269 /// 则会返回错误。成功时,会返回一个新的挂载文件系统的引用。 270 /// 271 /// ## 参数 272 /// 273 /// - `fs`: FileSystem - 文件系统的引用,用于创建和挂载目录。 274 /// - `mount_point`: &str - 挂载点路径,用于创建和挂载目录。 275 /// 276 /// ## 返回值 277 /// 278 /// - `Ok(Arc<MountFS>)`: 成功挂载文件系统后,返回挂载文件系统的共享引用。 279 /// - `Err(SystemError)`: 挂载失败时,返回系统错误。 280 pub fn do_mount_mkdir( 281 fs: Arc<dyn FileSystem>, 282 mount_point: &str, 283 ) -> Result<Arc<MountFS>, SystemError> { 284 let inode = do_mkdir_at( 285 AtFlags::AT_FDCWD.bits(), 286 mount_point, 287 FileMode::from_bits_truncate(0o755), 288 )?; 289 if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { 290 if rest.is_empty() { 291 return Err(SystemError::EBUSY); 292 } 293 } 294 return inode.mount(fs); 295 } 296 297 /// # do_umount2 - 执行卸载文件系统的函数 298 /// 299 /// 这个函数用于卸载指定的文件系统。 300 /// 301 /// ## 参数 302 /// 303 /// - dirfd: i32 - 目录文件描述符,用于指定要卸载的文件系统的根目录。 304 /// - target: &str - 要卸载的文件系统的目标路径。 305 /// - _flag: UmountFlag - 卸载标志,目前未使用。 306 /// 307 /// ## 返回值 308 /// 309 /// - Ok(Arc<MountFS>): 成功时返回文件系统的 Arc 引用。 310 /// - Err(SystemError): 出错时返回系统错误。 311 /// 312 /// ## 错误处理 313 /// 314 /// 如果指定的路径没有对应的文件系统,或者在尝试卸载时发生错误,将返回错误。 315 pub fn do_umount2( 316 dirfd: i32, 317 target: &str, 318 _flag: UmountFlag, 319 ) -> Result<Arc<MountFS>, SystemError> { 320 let (work, rest) = user_path_at(&ProcessManager::current_pcb(), dirfd, target)?; 321 let path = work.absolute_path()? + &rest; 322 let do_umount = || -> Result<Arc<MountFS>, SystemError> { 323 if let Some(fs) = MOUNT_LIST().remove(path) { 324 // Todo: 占用检测 325 fs.umount()?; 326 return Ok(fs); 327 } 328 return Err(SystemError::EINVAL); 329 }; 330 return do_umount(); 331 } 332