From 886df6daf6bb6b922276157dba1cc099e897a9ea Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Sat, 18 Nov 2023 02:43:01 -0800 Subject: Major refactor of file hierarchy --- src/memory/cached_block.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++ src/memory/cached_inode.rs | 51 ++++++++++++++++++++++++++++ src/memory/mod.rs | 5 +++ 3 files changed, 140 insertions(+) create mode 100644 src/memory/cached_block.rs create mode 100644 src/memory/cached_inode.rs create mode 100644 src/memory/mod.rs (limited to 'src/memory') diff --git a/src/memory/cached_block.rs b/src/memory/cached_block.rs new file mode 100644 index 0000000..0c401ff --- /dev/null +++ b/src/memory/cached_block.rs @@ -0,0 +1,84 @@ +use and_then_some::BoolExt; +use crate::AyaFS; +use crate::block_device::BLOCK_SIZE; +use crate::disk::data_block::{Block, DataBlock}; + +#[derive(Clone)] +pub struct CachedBlock { + pub block: T, + pub index: usize, + pub dirty: bool, +} + +impl CachedBlock { + fn cast(&self) -> CachedBlock { + unsafe { std::mem::transmute_copy(&self) } + } +} + +pub fn convert_mut(input_block: &mut CachedBlock) -> &mut CachedBlock { + let ptr = input_block as *const CachedBlock as *mut u8; + let block = ptr.cast::>(); + unsafe { &mut *block } +} + +pub fn convert(input_block: &CachedBlock) -> &CachedBlock { + let ptr = input_block as *const CachedBlock as *mut u8; + let block = ptr.cast::>(); + unsafe { &*block } +} + +impl AyaFS { + pub(crate) fn update_block(&mut self, block: CachedBlock) -> bool { + if self.cached_blocks.contains(&block.index) { + let data_block = convert::(&block).clone(); + self.cached_blocks.push(block.index, data_block); + true + } else { + false + } + } + pub(crate) fn get_block(&mut self, index: usize) -> Option<&CachedBlock> { + self.load_block(index) + .and_then(|| self.cached_blocks.get(&index).map(convert::)) + } + + pub(crate) fn get_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { + self.load_block(index).and_then(|| { + self.cached_blocks + .get_mut(&index) + .map(convert_mut::) + }) + } + + pub(crate) fn load_block(&mut self, index: usize) -> bool { + // 反正我自己保证所有实现了 Block trait 的数据结构都是 4K bytes 长, 来回 cast 没问题 + // 如果 block cache 里没有这个 block + if self.cached_blocks.contains(&index) == false { + if self.data_bitmap.query(index) == false { + return false; + } // 先看这个 block 是不是 valid, 不 valid 直接返回 None + let block = DataBlock::default(); + let buffer = unsafe { + std::slice::from_raw_parts_mut(&block as *const DataBlock as *mut u8, BLOCK_SIZE) + }; + self.device.read(index, buffer); + let cached_block = CachedBlock { + block, + index, + dirty: false, + }; + if let Some((old_index, old_block)) = self.cached_blocks.push(index, cached_block) { + assert_ne!(old_index, index); // 只有 block 不在 cache 里的时候才会插入 + if old_block.dirty { + let old_block_ptr = &old_block.block as *const DataBlock 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); + } + } // 如果 valid 就放到 block cache 里, 同时将(可能)被驱逐的 block 依据其是否为脏块进行写回 + } + + true + } +} diff --git a/src/memory/cached_inode.rs b/src/memory/cached_inode.rs new file mode 100644 index 0000000..b51d279 --- /dev/null +++ b/src/memory/cached_inode.rs @@ -0,0 +1,51 @@ +use and_then_some::BoolExt; +use crate::AyaFS; +use crate::disk::data_block::InodeBlock; +use crate::disk::inode::{Inode, INODE_SIZE, InodeMode}; + +impl AyaFS { + 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, + Self::time_now(), + flags, + 0, + 0, + 0, + ); + }); + inode_index + }) + } + + pub(crate) fn get_inode(&mut self, inode_index: usize) -> Option<&Inode> { + self.inode_bitmap.query(inode_index).and_then(|| { + let (block_index, offset) = self.locate_inode(inode_index); + self.get_block::(block_index) + .map(|cached_block| &cached_block.block.inodes[offset / INODE_SIZE]) + }) + } + + pub(crate) fn get_inode_mut(&mut self, inode_index: usize) -> Option<&mut Inode> { + self.inode_bitmap.query(inode_index).and_then(|| { + let (block_index, offset) = self.locate_inode(inode_index); + self.get_block_mut::(block_index) + .map(|cached_block| { + cached_block.dirty = true; // 保守一些, 只要返回了 &mut Inode 这个页一定标记为脏 + &mut cached_block.block.inodes[offset / INODE_SIZE] + }) + }) + } +} \ No newline at end of file diff --git a/src/memory/mod.rs b/src/memory/mod.rs new file mode 100644 index 0000000..ffdf04c --- /dev/null +++ b/src/memory/mod.rs @@ -0,0 +1,5 @@ +/// In-memory data structures and logic. +/// This is where the crucial block and inode methods presented to upper calls implemented. + +pub mod cached_block; +pub mod cached_inode; -- cgit v1.2.3-70-g09d2