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