1 use core::any::Any; 2 use core::intrinsics::unlikely; 3 4 use alloc::{ 5 collections::BTreeMap, 6 string::String, 7 sync::{Arc, Weak}, 8 vec::Vec, 9 }; 10 11 use crate::{ 12 filesystem::vfs::{core::generate_inode_id, FileType}, 13 ipc::pipe::LockedPipeInode, 14 libs::spinlock::{SpinLock, SpinLockGuard}, 15 syscall::SystemError, 16 time::TimeSpec, 17 }; 18 19 use super::vfs::{ 20 file::FilePrivateData, syscall::ModeType, FileSystem, FsInfo, IndexNode, InodeId, Metadata, 21 PollStatus, SpecialNodeData, 22 }; 23 24 /// RamFS的inode名称的最大长度 25 const RAMFS_MAX_NAMELEN: usize = 64; 26 27 /// @brief 内存文件系统的Inode结构体 28 #[derive(Debug)] 29 struct LockedRamFSInode(SpinLock<RamFSInode>); 30 31 /// @brief 内存文件系统结构体 32 #[derive(Debug)] 33 pub struct RamFS { 34 /// RamFS的root inode 35 root_inode: Arc<LockedRamFSInode>, 36 } 37 38 /// @brief 内存文件系统的Inode结构体(不包含锁) 39 #[derive(Debug)] 40 pub struct RamFSInode { 41 // parent变量目前只在find函数中使用到 42 // 所以只有当inode是文件夹的时候,parent才会生效 43 // 对于文件来说,parent就没什么作用了 44 // 关于parent的说明: 目录不允许有硬链接 45 /// 指向父Inode的弱引用 46 parent: Weak<LockedRamFSInode>, 47 /// 指向自身的弱引用 48 self_ref: Weak<LockedRamFSInode>, 49 /// 子Inode的B树 50 children: BTreeMap<String, Arc<LockedRamFSInode>>, 51 /// 当前inode的数据部分 52 data: Vec<u8>, 53 /// 当前inode的元数据 54 metadata: Metadata, 55 /// 指向inode所在的文件系统对象的指针 56 fs: Weak<RamFS>, 57 /// 指向特殊节点 58 special_node: Option<SpecialNodeData>, 59 } 60 61 impl FileSystem for RamFS { 62 fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> { 63 return self.root_inode.clone(); 64 } 65 66 fn info(&self) -> FsInfo { 67 return FsInfo { 68 blk_dev_id: 0, 69 max_name_len: RAMFS_MAX_NAMELEN, 70 }; 71 } 72 73 /// @brief 本函数用于实现动态转换。 74 /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self 75 fn as_any_ref(&self) -> &dyn Any { 76 self 77 } 78 } 79 80 impl RamFS { 81 pub fn new() -> Arc<Self> { 82 // 初始化root inode 83 let root: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { 84 parent: Weak::default(), 85 self_ref: Weak::default(), 86 children: BTreeMap::new(), 87 data: Vec::new(), 88 metadata: Metadata { 89 dev_id: 0, 90 inode_id: generate_inode_id(), 91 size: 0, 92 blk_size: 0, 93 blocks: 0, 94 atime: TimeSpec::default(), 95 mtime: TimeSpec::default(), 96 ctime: TimeSpec::default(), 97 file_type: FileType::Dir, 98 mode: ModeType::from_bits_truncate(0o777), 99 nlinks: 1, 100 uid: 0, 101 gid: 0, 102 raw_dev: 0, 103 }, 104 fs: Weak::default(), 105 special_node: None, 106 }))); 107 108 let result: Arc<RamFS> = Arc::new(RamFS { root_inode: root }); 109 110 // 对root inode加锁,并继续完成初始化工作 111 let mut root_guard: SpinLockGuard<RamFSInode> = result.root_inode.0.lock(); 112 root_guard.parent = Arc::downgrade(&result.root_inode); 113 root_guard.self_ref = Arc::downgrade(&result.root_inode); 114 root_guard.fs = Arc::downgrade(&result); 115 // 释放锁 116 drop(root_guard); 117 118 return result; 119 } 120 } 121 122 impl IndexNode for LockedRamFSInode { 123 fn truncate(&self, len: usize) -> Result<(), SystemError> { 124 let mut inode = self.0.lock(); 125 126 //如果是文件夹,则报错 127 if inode.metadata.file_type == FileType::Dir { 128 return Err(SystemError::EINVAL); 129 } 130 131 //当前文件长度大于_len才进行截断,否则不操作 132 if inode.data.len() > len { 133 inode.data.resize(len, 0); 134 } 135 return Ok(()); 136 } 137 138 fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { 139 return Ok(()); 140 } 141 142 fn open( 143 &self, 144 _data: &mut FilePrivateData, 145 _mode: &super::vfs::file::FileMode, 146 ) -> Result<(), SystemError> { 147 return Ok(()); 148 } 149 150 fn read_at( 151 &self, 152 offset: usize, 153 len: usize, 154 buf: &mut [u8], 155 _data: &mut FilePrivateData, 156 ) -> Result<usize, SystemError> { 157 if buf.len() < len { 158 return Err(SystemError::EINVAL); 159 } 160 // 加锁 161 let inode: SpinLockGuard<RamFSInode> = self.0.lock(); 162 163 // 检查当前inode是否为一个文件夹,如果是的话,就返回错误 164 if inode.metadata.file_type == FileType::Dir { 165 return Err(SystemError::EISDIR); 166 } 167 168 let start = inode.data.len().min(offset); 169 let end = inode.data.len().min(offset + len); 170 171 // buffer空间不足 172 if buf.len() < (end - start) { 173 return Err(SystemError::ENOBUFS); 174 } 175 176 // 拷贝数据 177 let src = &inode.data[start..end]; 178 buf[0..src.len()].copy_from_slice(src); 179 return Ok(src.len()); 180 } 181 182 fn write_at( 183 &self, 184 offset: usize, 185 len: usize, 186 buf: &[u8], 187 _data: &mut FilePrivateData, 188 ) -> Result<usize, SystemError> { 189 if buf.len() < len { 190 return Err(SystemError::EINVAL); 191 } 192 193 // 加锁 194 let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 195 196 // 检查当前inode是否为一个文件夹,如果是的话,就返回错误 197 if inode.metadata.file_type == FileType::Dir { 198 return Err(SystemError::EISDIR); 199 } 200 201 let data: &mut Vec<u8> = &mut inode.data; 202 203 // 如果文件大小比原来的大,那就resize这个数组 204 if offset + len > data.len() { 205 data.resize(offset + len, 0); 206 } 207 208 let target = &mut data[offset..offset + len]; 209 target.copy_from_slice(&buf[0..len]); 210 return Ok(len); 211 } 212 213 fn poll(&self) -> Result<PollStatus, SystemError> { 214 // 加锁 215 let inode: SpinLockGuard<RamFSInode> = self.0.lock(); 216 217 // 检查当前inode是否为一个文件夹,如果是的话,就返回错误 218 if inode.metadata.file_type == FileType::Dir { 219 return Err(SystemError::EISDIR); 220 } 221 222 return Ok(PollStatus::READ | PollStatus::WRITE); 223 } 224 225 fn fs(&self) -> Arc<dyn FileSystem> { 226 return self.0.lock().fs.upgrade().unwrap(); 227 } 228 229 fn as_any_ref(&self) -> &dyn core::any::Any { 230 self 231 } 232 233 fn metadata(&self) -> Result<Metadata, SystemError> { 234 let inode = self.0.lock(); 235 let mut metadata = inode.metadata.clone(); 236 metadata.size = inode.data.len() as i64; 237 238 return Ok(metadata); 239 } 240 241 fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { 242 let mut inode = self.0.lock(); 243 inode.metadata.atime = metadata.atime; 244 inode.metadata.mtime = metadata.mtime; 245 inode.metadata.ctime = metadata.ctime; 246 inode.metadata.mode = metadata.mode; 247 inode.metadata.uid = metadata.uid; 248 inode.metadata.gid = metadata.gid; 249 250 return Ok(()); 251 } 252 253 fn resize(&self, len: usize) -> Result<(), SystemError> { 254 let mut inode = self.0.lock(); 255 if inode.metadata.file_type == FileType::File { 256 inode.data.resize(len, 0); 257 return Ok(()); 258 } else { 259 return Err(SystemError::EINVAL); 260 } 261 } 262 263 fn create_with_data( 264 &self, 265 name: &str, 266 file_type: FileType, 267 mode: ModeType, 268 data: usize, 269 ) -> Result<Arc<dyn IndexNode>, SystemError> { 270 // 获取当前inode 271 let mut inode = self.0.lock(); 272 // 如果当前inode不是文件夹,则返回 273 if inode.metadata.file_type != FileType::Dir { 274 return Err(SystemError::ENOTDIR); 275 } 276 // 如果有重名的,则返回 277 if inode.children.contains_key(name) { 278 return Err(SystemError::EEXIST); 279 } 280 281 // 创建inode 282 let result: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { 283 parent: inode.self_ref.clone(), 284 self_ref: Weak::default(), 285 children: BTreeMap::new(), 286 data: Vec::new(), 287 metadata: Metadata { 288 dev_id: 0, 289 inode_id: generate_inode_id(), 290 size: 0, 291 blk_size: 0, 292 blocks: 0, 293 atime: TimeSpec::default(), 294 mtime: TimeSpec::default(), 295 ctime: TimeSpec::default(), 296 file_type: file_type, 297 mode: mode, 298 nlinks: 1, 299 uid: 0, 300 gid: 0, 301 raw_dev: data, 302 }, 303 fs: inode.fs.clone(), 304 special_node: None, 305 }))); 306 307 // 初始化inode的自引用的weak指针 308 result.0.lock().self_ref = Arc::downgrade(&result); 309 310 // 将子inode插入父inode的B树中 311 inode.children.insert(String::from(name), result.clone()); 312 313 return Ok(result); 314 } 315 316 fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> { 317 let other: &LockedRamFSInode = other 318 .downcast_ref::<LockedRamFSInode>() 319 .ok_or(SystemError::EPERM)?; 320 let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 321 let mut other_locked: SpinLockGuard<RamFSInode> = other.0.lock(); 322 323 // 如果当前inode不是文件夹,那么报错 324 if inode.metadata.file_type != FileType::Dir { 325 return Err(SystemError::ENOTDIR); 326 } 327 328 // 如果另一个inode是文件夹,那么也报错 329 if other_locked.metadata.file_type == FileType::Dir { 330 return Err(SystemError::EISDIR); 331 } 332 333 // 如果当前文件夹下已经有同名文件,也报错。 334 if inode.children.contains_key(name) { 335 return Err(SystemError::EEXIST); 336 } 337 338 inode 339 .children 340 .insert(String::from(name), other_locked.self_ref.upgrade().unwrap()); 341 342 // 增加硬链接计数 343 other_locked.metadata.nlinks += 1; 344 return Ok(()); 345 } 346 347 fn unlink(&self, name: &str) -> Result<(), SystemError> { 348 let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 349 // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录 350 if inode.metadata.file_type != FileType::Dir { 351 return Err(SystemError::ENOTDIR); 352 } 353 // 不允许删除当前文件夹,也不允许删除上一个目录 354 if name == "." || name == ".." { 355 return Err(SystemError::ENOTEMPTY); 356 } 357 358 // 获得要删除的文件的inode 359 let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?; 360 if to_delete.0.lock().metadata.file_type == FileType::Dir { 361 return Err(SystemError::EPERM); 362 } 363 // 减少硬链接计数 364 to_delete.0.lock().metadata.nlinks -= 1; 365 // 在当前目录中删除这个子目录项 366 inode.children.remove(name); 367 return Ok(()); 368 } 369 370 fn rmdir(&self, name: &str) -> Result<(), SystemError> { 371 let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 372 // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录 373 if inode.metadata.file_type != FileType::Dir { 374 return Err(SystemError::ENOTDIR); 375 } 376 // 获得要删除的文件夹的inode 377 let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?; 378 if to_delete.0.lock().metadata.file_type != FileType::Dir { 379 return Err(SystemError::ENOTDIR); 380 } 381 382 to_delete.0.lock().metadata.nlinks -= 1; 383 // 在当前目录中删除这个子目录项 384 inode.children.remove(name); 385 return Ok(()); 386 } 387 388 fn move_( 389 &self, 390 old_name: &str, 391 target: &Arc<dyn IndexNode>, 392 new_name: &str, 393 ) -> Result<(), SystemError> { 394 let old_inode: Arc<dyn IndexNode> = self.find(old_name)?; 395 396 // 在新的目录下创建一个硬链接 397 target.link(new_name, &old_inode)?; 398 // 取消现有的目录下的这个硬链接 399 if let Err(err) = self.unlink(old_name) { 400 // 如果取消失败,那就取消新的目录下的硬链接 401 target.unlink(new_name)?; 402 return Err(err); 403 } 404 return Ok(()); 405 } 406 407 fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> { 408 let inode = self.0.lock(); 409 410 if inode.metadata.file_type != FileType::Dir { 411 return Err(SystemError::ENOTDIR); 412 } 413 414 match name { 415 "" | "." => { 416 return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?); 417 } 418 419 ".." => { 420 return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?); 421 } 422 name => { 423 // 在子目录项中查找 424 return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone()); 425 } 426 } 427 } 428 429 fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> { 430 let inode: SpinLockGuard<RamFSInode> = self.0.lock(); 431 if inode.metadata.file_type != FileType::Dir { 432 return Err(SystemError::ENOTDIR); 433 } 434 435 match ino.into() { 436 0 => { 437 return Ok(String::from(".")); 438 } 439 1 => { 440 return Ok(String::from("..")); 441 } 442 ino => { 443 // 暴力遍历所有的children,判断inode id是否相同 444 // TODO: 优化这里,这个地方性能很差! 445 let mut key: Vec<String> = inode 446 .children 447 .keys() 448 .filter(|k| { 449 inode 450 .children 451 .get(*k) 452 .unwrap() 453 .0 454 .lock() 455 .metadata 456 .inode_id 457 .into() 458 == ino 459 }) 460 .cloned() 461 .collect(); 462 463 match key.len() { 464 0=>{return Err(SystemError::ENOENT);} 465 1=>{return Ok(key.remove(0));} 466 _ => panic!("Ramfs get_entry_name: key.len()={key_len}>1, current inode_id={inode_id:?}, to find={to_find:?}", key_len=key.len(), inode_id = inode.metadata.inode_id, to_find=ino) 467 } 468 } 469 } 470 } 471 472 fn list(&self) -> Result<Vec<String>, SystemError> { 473 let info = self.metadata()?; 474 if info.file_type != FileType::Dir { 475 return Err(SystemError::ENOTDIR); 476 } 477 478 let mut keys: Vec<String> = Vec::new(); 479 keys.push(String::from(".")); 480 keys.push(String::from("..")); 481 keys.append(&mut self.0.lock().children.keys().cloned().collect()); 482 483 return Ok(keys); 484 } 485 486 fn mknod( 487 &self, 488 filename: &str, 489 mode: ModeType, 490 _dev_t: crate::driver::base::device::DeviceNumber, 491 ) -> Result<Arc<dyn IndexNode>, SystemError> { 492 let mut inode = self.0.lock(); 493 if inode.metadata.file_type != FileType::Dir { 494 return Err(SystemError::ENOTDIR); 495 } 496 497 // 判断需要创建的类型 498 if unlikely(mode.contains(ModeType::S_IFREG)) { 499 // 普通文件 500 return Ok(self.create(filename, FileType::File, mode)?); 501 } 502 503 let nod = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { 504 parent: inode.self_ref.clone(), 505 self_ref: Weak::default(), 506 children: BTreeMap::new(), 507 data: Vec::new(), 508 metadata: Metadata { 509 dev_id: 0, 510 inode_id: generate_inode_id(), 511 size: 0, 512 blk_size: 0, 513 blocks: 0, 514 atime: TimeSpec::default(), 515 mtime: TimeSpec::default(), 516 ctime: TimeSpec::default(), 517 file_type: FileType::Pipe, 518 mode: mode, 519 nlinks: 1, 520 uid: 0, 521 gid: 0, 522 raw_dev: 0, 523 }, 524 fs: inode.fs.clone(), 525 special_node: None, 526 }))); 527 528 nod.0.lock().self_ref = Arc::downgrade(&nod); 529 530 if mode.contains(ModeType::S_IFIFO) { 531 nod.0.lock().metadata.file_type = FileType::Pipe; 532 // 创建pipe文件 533 let pipe_inode = LockedPipeInode::new(); 534 // 设置special_node 535 nod.0.lock().special_node = Some(SpecialNodeData::Pipe(pipe_inode)); 536 } else if mode.contains(ModeType::S_IFBLK) { 537 nod.0.lock().metadata.file_type = FileType::BlockDevice; 538 unimplemented!() 539 } else if mode.contains(ModeType::S_IFCHR) { 540 nod.0.lock().metadata.file_type = FileType::CharDevice; 541 unimplemented!() 542 } 543 544 inode 545 .children 546 .insert(String::from(filename).to_uppercase(), nod.clone()); 547 Ok(nod) 548 } 549 550 fn special_node(&self) -> Option<super::vfs::SpecialNodeData> { 551 return self.0.lock().special_node.clone(); 552 } 553 } 554