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 fn root_partition() -> Arc<Partition> { 117 #[cfg(target_arch = "x86_64")] 118 { 119 return ahci::get_disks_by_name("ahci_disk_0".to_string()) 120 .unwrap() 121 .0 122 .lock() 123 .partitions[0] 124 .clone(); 125 } 126 127 #[cfg(target_arch = "riscv64")] 128 { 129 use crate::driver::base::block::block_device::BlockDevice; 130 131 let virtio0 = crate::driver::block::virtio_blk::virtio_blk_0(); 132 if virtio0.is_none() { 133 kerror!("Failed to get virtio_blk_0"); 134 loop { 135 spin_loop(); 136 } 137 } 138 139 let virtio0 = virtio0.unwrap(); 140 return virtio0.partitions()[0].clone(); 141 } 142 } 143 pub fn mount_root_fs() -> Result<(), SystemError> { 144 kinfo!("Try to mount FAT32 as root fs..."); 145 let partiton: Arc<Partition> = root_partition(); 146 147 let fatfs: Result<Arc<FATFileSystem>, SystemError> = FATFileSystem::new(partiton); 148 if fatfs.is_err() { 149 kerror!( 150 "Failed to initialize fatfs, code={:?}", 151 fatfs.as_ref().err() 152 ); 153 loop { 154 spin_loop(); 155 } 156 } 157 let fatfs: Arc<FATFileSystem> = fatfs.unwrap(); 158 let r = migrate_virtual_filesystem(fatfs); 159 if r.is_err() { 160 kerror!("Failed to migrate virtual filesystem to FAT32!"); 161 loop { 162 spin_loop(); 163 } 164 } 165 kinfo!("Successfully migrate rootfs to FAT32!"); 166 167 return Ok(()); 168 } 169 170 /// @brief 创建文件/文件夹 171 pub fn do_mkdir_at( 172 dirfd: i32, 173 path: &str, 174 mode: FileMode, 175 ) -> Result<Arc<dyn IndexNode>, SystemError> { 176 // kdebug!("Call do mkdir at"); 177 let (mut current_inode, path) = 178 user_path_at(&ProcessManager::current_pcb(), dirfd, path.trim())?; 179 let (name, parent) = rsplit_path(&path); 180 if let Some(parent) = parent { 181 current_inode = current_inode.lookup(parent)?; 182 } 183 // kdebug!("mkdir at {:?}", current_inode.metadata()?.inode_id); 184 return current_inode.mkdir(name, ModeType::from_bits_truncate(mode.bits())); 185 } 186 187 /// @brief 删除文件夹 188 pub fn do_remove_dir(dirfd: i32, path: &str) -> Result<u64, SystemError> { 189 let path = path.trim(); 190 191 let pcb = ProcessManager::current_pcb(); 192 let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?; 193 let (filename, parent_path) = rsplit_path(&remain_path); 194 195 // 最后一项文件项为.时返回EINVAL 196 if filename == "." { 197 return Err(SystemError::EINVAL); 198 } 199 200 // 查找父目录 201 let parent_inode: Arc<dyn IndexNode> = inode_begin 202 .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 203 204 if parent_inode.metadata()?.file_type != FileType::Dir { 205 return Err(SystemError::ENOTDIR); 206 } 207 208 // 在目标点为symlink时也返回ENOTDIR 209 let target_inode = parent_inode.find(filename)?; 210 if target_inode.metadata()?.file_type != FileType::Dir { 211 return Err(SystemError::ENOTDIR); 212 } 213 214 // 删除文件夹 215 parent_inode.rmdir(filename)?; 216 217 return Ok(0); 218 } 219 220 /// @brief 删除文件 221 pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> { 222 let path = path.trim(); 223 224 let pcb = ProcessManager::current_pcb(); 225 let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?; 226 let inode: Result<Arc<dyn IndexNode>, SystemError> = 227 inode_begin.lookup_follow_symlink(&remain_path, VFS_MAX_FOLLOW_SYMLINK_TIMES); 228 229 if inode.is_err() { 230 let errno = inode.clone().unwrap_err(); 231 // 文件不存在,且需要创建 232 if errno == SystemError::ENOENT { 233 return Err(SystemError::ENOENT); 234 } 235 } 236 // 禁止在目录上unlink 237 if inode.unwrap().metadata()?.file_type == FileType::Dir { 238 return Err(SystemError::EPERM); 239 } 240 241 let (filename, parent_path) = rsplit_path(path); 242 // 查找父目录 243 let parent_inode: Arc<dyn IndexNode> = inode_begin 244 .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 245 246 if parent_inode.metadata()?.file_type != FileType::Dir { 247 return Err(SystemError::ENOTDIR); 248 } 249 250 // 删除文件 251 parent_inode.unlink(filename)?; 252 253 return Ok(0); 254 } 255 256 /// # do_mount - 挂载文件系统 257 /// 258 /// 将给定的文件系统挂载到指定的挂载点。 259 /// 260 /// 此函数会检查是否已经挂载了相同的文件系统,如果已经挂载,则返回错误。 261 /// 它还会处理符号链接,并确保挂载点是有效的。 262 /// 263 /// ## 参数 264 /// 265 /// - `fs`: Arc<dyn FileSystem>,要挂载的文件系统。 266 /// - `mount_point`: &str,挂载点路径。 267 /// 268 /// ## 返回值 269 /// 270 /// - `Ok(Arc<MountFS>)`: 挂载成功后返回挂载的文件系统。 271 /// - `Err(SystemError)`: 挂载失败时返回错误。 272 pub fn do_mount(fs: Arc<dyn FileSystem>, mount_point: &str) -> Result<Arc<MountFS>, SystemError> { 273 let (current_node, rest_path) = user_path_at( 274 &ProcessManager::current_pcb(), 275 AtFlags::AT_FDCWD.bits(), 276 mount_point, 277 )?; 278 let inode = current_node.lookup_follow_symlink(&rest_path, VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 279 if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { 280 if rest.is_empty() { 281 return Err(SystemError::EBUSY); 282 } 283 } 284 // 移至IndexNode.mount()来记录 285 return inode.mount(fs); 286 } 287 288 /// # do_mount_mkdir - 在指定挂载点创建目录并挂载文件系统 289 /// 290 /// 在指定的挂载点创建一个目录,并将其挂载到文件系统中。如果挂载点已经存在,并且不是空的, 291 /// 则会返回错误。成功时,会返回一个新的挂载文件系统的引用。 292 /// 293 /// ## 参数 294 /// 295 /// - `fs`: FileSystem - 文件系统的引用,用于创建和挂载目录。 296 /// - `mount_point`: &str - 挂载点路径,用于创建和挂载目录。 297 /// 298 /// ## 返回值 299 /// 300 /// - `Ok(Arc<MountFS>)`: 成功挂载文件系统后,返回挂载文件系统的共享引用。 301 /// - `Err(SystemError)`: 挂载失败时,返回系统错误。 302 pub fn do_mount_mkdir( 303 fs: Arc<dyn FileSystem>, 304 mount_point: &str, 305 ) -> Result<Arc<MountFS>, SystemError> { 306 let inode = do_mkdir_at( 307 AtFlags::AT_FDCWD.bits(), 308 mount_point, 309 FileMode::from_bits_truncate(0o755), 310 )?; 311 if let Some((_, rest, _fs)) = MOUNT_LIST().get_mount_point(mount_point) { 312 if rest.is_empty() { 313 return Err(SystemError::EBUSY); 314 } 315 } 316 return inode.mount(fs); 317 } 318 319 /// # do_umount2 - 执行卸载文件系统的函数 320 /// 321 /// 这个函数用于卸载指定的文件系统。 322 /// 323 /// ## 参数 324 /// 325 /// - dirfd: i32 - 目录文件描述符,用于指定要卸载的文件系统的根目录。 326 /// - target: &str - 要卸载的文件系统的目标路径。 327 /// - _flag: UmountFlag - 卸载标志,目前未使用。 328 /// 329 /// ## 返回值 330 /// 331 /// - Ok(Arc<MountFS>): 成功时返回文件系统的 Arc 引用。 332 /// - Err(SystemError): 出错时返回系统错误。 333 /// 334 /// ## 错误处理 335 /// 336 /// 如果指定的路径没有对应的文件系统,或者在尝试卸载时发生错误,将返回错误。 337 pub fn do_umount2( 338 dirfd: i32, 339 target: &str, 340 _flag: UmountFlag, 341 ) -> Result<Arc<MountFS>, SystemError> { 342 let (work, rest) = user_path_at(&ProcessManager::current_pcb(), dirfd, target)?; 343 let path = work.absolute_path()? + &rest; 344 let do_umount = || -> Result<Arc<MountFS>, SystemError> { 345 if let Some(fs) = MOUNT_LIST().remove(path) { 346 // Todo: 占用检测 347 fs.umount()?; 348 return Ok(fs); 349 } 350 return Err(SystemError::EINVAL); 351 }; 352 return do_umount(); 353 } 354