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