From 9d1368b0ea380a9446b4697af668d1685464b6c7 Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Sun, 26 Nov 2023 02:33:01 -0800 Subject: more code idk what they are im so tired ohno --- src/memory/cached_block.rs | 53 ++++++++++++++++++++-------- src/memory/cached_inode.rs | 87 ++++++++++++++++++++++++++++++---------------- src/memory/dir_entry.rs | 40 ++++++++++++++------- 3 files changed, 124 insertions(+), 56 deletions(-) (limited to 'src/memory') diff --git a/src/memory/cached_block.rs b/src/memory/cached_block.rs index 783e987..002a75b 100644 --- a/src/memory/cached_block.rs +++ b/src/memory/cached_block.rs @@ -75,7 +75,7 @@ impl BlockCache { if !self.cache.contains(&index) { self.load_block(index); } - self.cache.get(&index).map(convert::) + self.cache.get(&index).map(convert::) } /// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载. @@ -90,6 +90,24 @@ impl BlockCache { }) } + /// 向 LRU cache 中插入一个全新初始化的 block + /// 这个 block 全 0, 而且是 dirty 的, 即使被挤出去也会触发一次落盘 + pub(crate) fn init_block(&mut self, index: usize) { + let allocated_block = CachedBlock { + block: T::default(), + index, + dirty: true, + }; + if let Some((old_index, old_block)) = self.cache.push(index, allocated_block) { + if old_block.dirty { + let old_block_ptr = &old_block.block as *const T as *mut u8; + let old_block_buffer = + unsafe { std::slice::from_raw_parts(old_block_ptr, BLOCK_SIZE) }; + self.device.write(old_index, old_block_buffer); + } + } + } + /// 从 LRU cache 中读取一个 block 的引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载. pub(crate) fn peek_block(&self, index: usize) -> Option<&CachedBlock> { self.cache.peek(&index).map(convert::) @@ -117,26 +135,33 @@ impl BlockCache { } impl AyaFS { - pub(crate) fn load_block(&mut self, index: usize) -> bool { - if !self.data_bitmap.query(index) { - self.cached_blocks.pop(&index); - // deallocate 时只更新 bitmap 没有动 cache, lazy 地驱逐 cache 中的无效 entry. - return false; - } - self.cached_blocks.load_block(index) + pub(crate) fn init_block(&mut self, index: usize) { + self.cached_blocks.init_block(index); } pub(crate) fn get_block(&mut self, index: usize) -> Option<&CachedBlock> { - self.data_bitmap - .query(index) - .then(|| self.cached_blocks.get_block::(index).unwrap()) + if self.data_bitmap.query(index) { + Some(self.cached_blocks.get_block::(index).unwrap()) + } else { + self.cached_blocks.pop(&index); + None + } + // self.data_bitmap + // .query(index) + // .then(|| self.cached_blocks.get_block::(index).unwrap()) // 返回 None 当且仅当 data_bitmap 中这个 block 为 invalid } pub(crate) fn get_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { - self.data_bitmap - .query(index) - .then(|| self.cached_blocks.get_block_mut::(index).unwrap()) + if self.data_bitmap.query(index) { + Some(self.cached_blocks.get_block_mut::(index).unwrap()) + } else { + self.cached_blocks.pop(&index); + None + } + // self.data_bitmap + // .query(index) + // .then(|| self.cached_blocks.get_block_mut::(index).unwrap()) // 返回 None 当且仅当 data_bitmap 中这个 block 为 invalid } diff --git a/src/memory/cached_inode.rs b/src/memory/cached_inode.rs index b1be2de..aa4f5e3 100644 --- a/src/memory/cached_inode.rs +++ b/src/memory/cached_inode.rs @@ -1,10 +1,8 @@ use crate::disk::block::{DirectoryBlock, DirectoryEntry, InodeBlock}; -use crate::disk::inode::{Inode, InodeMode, INODE_SIZE}; -use crate::utils::from_filetype; +use crate::disk::inode::{Inode, INODE_SIZE}; use crate::{utils, AyaFS}; use and_then_some::BoolExt; -use fuser::FileType; -use log::debug; +use libc::{c_int, EISDIR, ENOENT, ENOTDIR}; impl AyaFS { pub(crate) fn create_file( @@ -22,12 +20,14 @@ impl AyaFS { }) } + /// 根目录的 parent_inode_number 传入 None, 会直接以自己作为 .. 的 inode number pub(crate) fn create_directory( &mut self, permissions: u16, uid: u32, gid: u32, flags: u32, + parent_inode_number: Option, ) -> Option<(usize, &Inode)> { self.inode_bitmap.allocate().map(|inode_index| { // 创建 Inode @@ -53,7 +53,7 @@ impl AyaFS { // add dot dot entry directory_block.block.entries[1] = DirectoryEntry { - inode: 0, // TODO set this as parent inode number + inode: parent_inode_number.unwrap_or(inode_index as u32), record_len: 264, name_len: 2, file_type: 0x2, @@ -70,31 +70,60 @@ impl AyaFS { (inode_index, self.get_inode(inode_index).unwrap()) }) } + + pub(crate) fn remove_file(&mut self, inode_index: usize) -> Result { + if self.inode_bitmap.query(inode_index) { + self.inode_bitmap.deallocate(inode_index); + let (block_index, offset) = self.locate_inode(inode_index); + if let Some(cached_block) = self.cached_inodes.get_block::(block_index) { + let inode = cached_block.block.inodes[offset / INODE_SIZE].clone(); + if !inode.is_file() { + return Err(EISDIR); + } + self.deallocate_all_blocks_for(&inode).unwrap(); + } + Ok(true) + } else { + Err(ENOENT) + } + } + + pub(crate) fn remove_dir(&mut self, inode_index: usize) -> Result { + if self.inode_bitmap.query(inode_index) { + self.inode_bitmap.deallocate(inode_index); + let (block_index, offset) = self.locate_inode(inode_index); + if let Some(cached_block) = self.cached_inodes.get_block::(block_index) { + let inode = cached_block.block.inodes[offset / INODE_SIZE].clone(); + if !inode.is_dir() { + return Err(ENOTDIR); + } + // TODO 递归删除所有下面的 direntry 里的 inode, 注意排除 . 和 .. + } + Ok(true) + } else { + Err(ENOENT) + } + } - pub(crate) fn create_inode( - &mut self, - permissions: u16, - mode: InodeMode, - uid: u32, - gid: u32, - flags: u32, - ) -> Option { - self.inode_bitmap.allocate().map(|inode_index| { - self.get_inode_mut(inode_index).map(|inode| { - *inode = Inode::make_inode( - permissions, - mode, - uid, - gid, - utils::time_now(), - flags, - 0, - 0, - 0, - ); - }); - inode_index - }) + pub(crate) fn remove_inode(&mut self, inode_index: usize) -> bool { + if self.inode_bitmap.query(inode_index) { + self.inode_bitmap.deallocate(inode_index); + let (block_index, offset) = self.locate_inode(inode_index); + if let Some(cached_block) = self.cached_inodes.get_block::(block_index) { + let inode = &cached_block.block.inodes[offset / INODE_SIZE].clone(); + + if inode.is_file() { + self.deallocate_all_blocks_for(inode).unwrap(); + } else if inode.is_dir() { + // TODO 把 dir 下所有子目录 remove 掉 + } else { + unimplemented!("only file and dir are implemented!"); + } + } + true + } else { + false + } } pub(crate) fn update_inode(&mut self, inode_index: usize, inode: Inode) -> bool { diff --git a/src/memory/dir_entry.rs b/src/memory/dir_entry.rs index 0ade23f..2d961db 100644 --- a/src/memory/dir_entry.rs +++ b/src/memory/dir_entry.rs @@ -1,15 +1,21 @@ -use std::ffi::OsStr; -use std::os::unix::ffi::OsStrExt; -use libc::{c_int, ENOENT, ENOSPC}; use crate::disk::block::{DirectoryBlock, DirectoryEntry}; -use crate::disk::inode::{Inode}; +use crate::disk::inode::Inode; use crate::AyaFS; +use libc::{c_int, ENOENT, ENOSPC}; +use std::ffi::OsStr; +use std::os::unix::ffi::OsStrExt; impl AyaFS { + /// 删除所有的 dir entry, 递归 + pub(crate) fn clear_direntry(&mut self, parent_inode: &mut Inode) -> Result<(), c_int> { + todo!() + } + + /// 删除第 entry_index 个 dir entry pub(crate) fn remove_direntry( &mut self, parent_inode: &mut Inode, - entry_index: u32 + entry_index: u32, ) -> Result<(), c_int> { let block_index_within_inode = (entry_index / 15) as usize; let entry_index_within_block = (entry_index % 15) as usize; @@ -18,7 +24,8 @@ impl AyaFS { Some(directory_block) => { if directory_block.block.query(entry_index_within_block) { directory_block.block.deallocate(entry_index_within_block); - directory_block.block.entries[entry_index_within_block] = DirectoryEntry::default(); + directory_block.block.entries[entry_index_within_block] = + DirectoryEntry::default(); Ok(()) } else { Err(ENOENT) @@ -31,7 +38,7 @@ impl AyaFS { pub(crate) fn add_direntry( &mut self, parent_inode: &mut Inode, - child_inode_index: u32, + child_inode_index: usize, child_inode_name: &OsStr, child_inode: &Inode, ) -> Result { @@ -45,7 +52,9 @@ impl AyaFS { } } // 寻找当前块里有没有空闲空间 - if let Some(directory_block) = self.access_block_mut::(parent_inode, block_index_within_inode) { + if let Some(directory_block) = + self.access_block_mut::(parent_inode, block_index_within_inode) + { if let Some(entry_index_within_block) = directory_block.block.allocate() { // 如果有空闲空间, 可以分配一个块 let name_len = child_inode_name.len() as u8; @@ -54,7 +63,7 @@ impl AyaFS { name.copy_from_slice(child_inode_name.as_bytes()); let dir_entry = DirectoryEntry { - inode: child_inode_index, + inode: child_inode_index as u32, record_len: 264, name_len, file_type, @@ -66,12 +75,12 @@ impl AyaFS { } } block_index_within_inode += 1; - }; + } } pub(crate) fn get_direntry( &mut self, parent_inode: &Inode, - entry_index: u32 + entry_index: u32, ) -> Option { let block_index_within_inode = (entry_index / 15) as usize; let entry_index_within_block = (entry_index % 15) as usize; @@ -87,13 +96,18 @@ impl AyaFS { } // TODO 实现一个带 cache 的版本 - pub fn lookup_name(&mut self, parent_inode: &Inode, name: &OsStr) -> Result<(u32, u32, Inode), c_int> { + /// 返回 inode_index, inode 在 parent 里的 index, inode 本身 + pub fn lookup_name( + &mut self, + parent_inode: &Inode, + name: &OsStr, + ) -> Result<(u32, u32, Inode), c_int> { let mut entry_index = 0; while entry_index < parent_inode.size { if let Some(entry) = self.get_direntry(parent_inode, entry_index) { if entry.name() == name { let inode = self.get_inode(entry.inode as usize).unwrap().clone(); - return Ok((entry.inode, entry_index, inode)) + return Ok((entry.inode, entry_index, inode)); } } entry_index += 1; -- cgit v1.2.3-70-g09d2