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