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