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::READ | PollStatus::WRITE); 190 } 191 192 fn fs(&self) -> Arc<dyn FileSystem> { 193 return self.0.lock().fs.upgrade().unwrap(); 194 } 195 196 fn as_any_ref(&self) -> &dyn core::any::Any { 197 self 198 } 199 200 fn metadata(&self) -> Result<Metadata, SystemError> { 201 let inode = self.0.lock(); 202 let mut metadata = inode.metadata.clone(); 203 metadata.size = inode.data.len() as i64; 204 205 return Ok(metadata); 206 } 207 208 fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> { 209 let mut inode = self.0.lock(); 210 inode.metadata.atime = metadata.atime; 211 inode.metadata.mtime = metadata.mtime; 212 inode.metadata.ctime = metadata.ctime; 213 inode.metadata.mode = metadata.mode; 214 inode.metadata.uid = metadata.uid; 215 inode.metadata.gid = metadata.gid; 216 217 return Ok(()); 218 } 219 220 fn resize(&self, len: usize) -> Result<(), SystemError> { 221 let mut inode = self.0.lock(); 222 if inode.metadata.file_type == FileType::File { 223 inode.data.resize(len, 0); 224 return Ok(()); 225 } else { 226 return Err(SystemError::EINVAL); 227 } 228 } 229 230 fn create_with_data( 231 &self, 232 name: &str, 233 file_type: FileType, 234 mode: u32, 235 data: usize, 236 ) -> Result<Arc<dyn IndexNode>, SystemError> { 237 // 获取当前inode 238 let mut inode = self.0.lock(); 239 // 如果当前inode不是文件夹,则返回 240 if inode.metadata.file_type != FileType::Dir { 241 return Err(SystemError::ENOTDIR); 242 } 243 // 如果有重名的,则返回 244 if inode.children.contains_key(name) { 245 return Err(SystemError::EEXIST); 246 } 247 248 // 创建inode 249 let result: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { 250 parent: inode.self_ref.clone(), 251 self_ref: Weak::default(), 252 children: BTreeMap::new(), 253 data: Vec::new(), 254 metadata: Metadata { 255 dev_id: 0, 256 inode_id: generate_inode_id(), 257 size: 0, 258 blk_size: 0, 259 blocks: 0, 260 atime: TimeSpec::default(), 261 mtime: TimeSpec::default(), 262 ctime: TimeSpec::default(), 263 file_type: file_type, 264 mode: mode, 265 nlinks: 1, 266 uid: 0, 267 gid: 0, 268 raw_dev: data, 269 }, 270 fs: inode.fs.clone(), 271 }))); 272 273 // 初始化inode的自引用的weak指针 274 result.0.lock().self_ref = Arc::downgrade(&result); 275 276 // 将子inode插入父inode的B树中 277 inode.children.insert(String::from(name), result.clone()); 278 279 return Ok(result); 280 } 281 282 fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), SystemError> { 283 let other: &LockedRamFSInode = other 284 .downcast_ref::<LockedRamFSInode>() 285 .ok_or(SystemError::EPERM)?; 286 let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 287 let mut other_locked: SpinLockGuard<RamFSInode> = other.0.lock(); 288 289 // 如果当前inode不是文件夹,那么报错 290 if inode.metadata.file_type != FileType::Dir { 291 return Err(SystemError::ENOTDIR); 292 } 293 294 // 如果另一个inode是文件夹,那么也报错 295 if other_locked.metadata.file_type == FileType::Dir { 296 return Err(SystemError::EISDIR); 297 } 298 299 // 如果当前文件夹下已经有同名文件,也报错。 300 if inode.children.contains_key(name) { 301 return Err(SystemError::EEXIST); 302 } 303 304 inode 305 .children 306 .insert(String::from(name), other_locked.self_ref.upgrade().unwrap()); 307 308 // 增加硬链接计数 309 other_locked.metadata.nlinks += 1; 310 return Ok(()); 311 } 312 313 fn unlink(&self, name: &str) -> Result<(), SystemError> { 314 let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 315 // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录 316 if inode.metadata.file_type != FileType::Dir { 317 return Err(SystemError::ENOTDIR); 318 } 319 // 不允许删除当前文件夹,也不允许删除上一个目录 320 if name == "." || name == ".." { 321 return Err(SystemError::ENOTEMPTY); 322 } 323 324 // 获得要删除的文件的inode 325 let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?; 326 if to_delete.0.lock().metadata.file_type == FileType::Dir { 327 return Err(SystemError::EPERM); 328 } 329 // 减少硬链接计数 330 to_delete.0.lock().metadata.nlinks -= 1; 331 // 在当前目录中删除这个子目录项 332 inode.children.remove(name); 333 return Ok(()); 334 } 335 336 fn rmdir(&self, name: &str) -> Result<(), SystemError> { 337 let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 338 // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录 339 if inode.metadata.file_type != FileType::Dir { 340 return Err(SystemError::ENOTDIR); 341 } 342 // 获得要删除的文件夹的inode 343 let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?; 344 if to_delete.0.lock().metadata.file_type != FileType::Dir { 345 return Err(SystemError::ENOTDIR); 346 } 347 348 to_delete.0.lock().metadata.nlinks -= 1; 349 // 在当前目录中删除这个子目录项 350 inode.children.remove(name); 351 return Ok(()); 352 } 353 354 fn move_( 355 &self, 356 old_name: &str, 357 target: &Arc<dyn IndexNode>, 358 new_name: &str, 359 ) -> Result<(), SystemError> { 360 let old_inode: Arc<dyn IndexNode> = self.find(old_name)?; 361 362 // 在新的目录下创建一个硬链接 363 target.link(new_name, &old_inode)?; 364 // 取消现有的目录下的这个硬链接 365 if let Err(err) = self.unlink(old_name) { 366 // 如果取消失败,那就取消新的目录下的硬链接 367 target.unlink(new_name)?; 368 return Err(err); 369 } 370 return Ok(()); 371 } 372 373 fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> { 374 let inode = self.0.lock(); 375 376 if inode.metadata.file_type != FileType::Dir { 377 return Err(SystemError::ENOTDIR); 378 } 379 380 match name { 381 "" | "." => { 382 return Ok(inode.self_ref.upgrade().ok_or(SystemError::ENOENT)?); 383 } 384 385 ".." => { 386 return Ok(inode.parent.upgrade().ok_or(SystemError::ENOENT)?); 387 } 388 name => { 389 // 在子目录项中查找 390 return Ok(inode.children.get(name).ok_or(SystemError::ENOENT)?.clone()); 391 } 392 } 393 } 394 395 fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> { 396 let inode: SpinLockGuard<RamFSInode> = self.0.lock(); 397 if inode.metadata.file_type != FileType::Dir { 398 return Err(SystemError::ENOTDIR); 399 } 400 401 match ino { 402 0 => { 403 return Ok(String::from(".")); 404 } 405 1 => { 406 return Ok(String::from("..")); 407 } 408 ino => { 409 // 暴力遍历所有的children,判断inode id是否相同 410 // TODO: 优化这里,这个地方性能很差! 411 let mut key: Vec<String> = inode 412 .children 413 .keys() 414 .filter(|k| inode.children.get(*k).unwrap().0.lock().metadata.inode_id == ino) 415 .cloned() 416 .collect(); 417 418 match key.len() { 419 0=>{return Err(SystemError::ENOENT);} 420 1=>{return Ok(key.remove(0));} 421 _ => 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) 422 } 423 } 424 } 425 } 426 427 fn list(&self) -> Result<Vec<String>, SystemError> { 428 let info = self.metadata()?; 429 if info.file_type != FileType::Dir { 430 return Err(SystemError::ENOTDIR); 431 } 432 433 let mut keys: Vec<String> = Vec::new(); 434 keys.push(String::from(".")); 435 keys.push(String::from("..")); 436 keys.append(&mut self.0.lock().children.keys().cloned().collect()); 437 438 return Ok(keys); 439 } 440 } 441