From 4c34414b26bf71e747ea3ecb2586645bab4aba52 Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Fri, 1 Dec 2023 19:42:13 -0800 Subject: Multiple bugfix, it works! --- ayafs-core/src/memory/cached_block.rs | 79 ++++++++++++++++++++++++++++------- ayafs-core/src/memory/cached_inode.rs | 8 ++-- ayafs-core/src/memory/dir_entry.rs | 14 +++++-- 3 files changed, 79 insertions(+), 22 deletions(-) (limited to 'ayafs-core/src/memory') diff --git a/ayafs-core/src/memory/cached_block.rs b/ayafs-core/src/memory/cached_block.rs index c3d0338..24f08c0 100644 --- a/ayafs-core/src/memory/cached_block.rs +++ b/ayafs-core/src/memory/cached_block.rs @@ -4,6 +4,7 @@ use crate::AyaFS; use lru::LruCache; use std::num::NonZeroUsize; use std::sync::Arc; +use log::debug; #[derive(Clone)] pub struct CachedBlock { @@ -27,20 +28,37 @@ pub fn convert(input_block: &CachedBlock) -> &CachedBlock pub(crate) struct BlockCache { device: Arc, cache: LruCache>, + pub global_offset: usize, } impl BlockCache { - pub(crate) fn new(device: Arc, cache_size: usize) -> Self { + pub(crate) fn new(device: Arc, cache_size: usize, global_offset: usize) -> Self { Self { device, cache: LruCache::new(NonZeroUsize::new(cache_size).unwrap()), + global_offset, + } + } + + pub(crate) fn write_back(&self) { + for (_, cached_block) in self.cache.iter() { + if cached_block.dirty { + debug!("write_back: dirty block {}", self.global_offset + cached_block.index); + let block_buffer = unsafe { + let block_ptr = &cached_block.block as *const T as *const u8; + std::slice::from_raw_parts(block_ptr, std::mem::size_of::()) + }; + self.device.write(self.global_offset + cached_block.index, block_buffer); + } else { + debug!("write_back: clean block {}", self.global_offset + cached_block.index); + } } } pub(crate) fn load_block(&mut self, index: usize) -> bool { if self.cache.contains(&index) == false { let mut buffer = [0u8; BLOCK_SIZE]; - self.device.read(index, &mut buffer); + self.device.read(self.global_offset + index, &mut buffer); let block: T = unsafe { std::mem::transmute_copy(&buffer) }; let cached_block = CachedBlock { block, @@ -50,10 +68,12 @@ impl BlockCache { if let Some((old_index, old_block)) = self.cache.push(index, cached_block) { assert_ne!(old_index, index); // 只有 block 不在 cache 里的时候才会插入 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); + debug!("write_back: evicted dirty block {} while loading {}", self.global_offset + old_block.index, self.global_offset + index); + let old_block_buffer = unsafe { + let old_block_ptr = &old_block.block as *const T as *mut u8; + std::slice::from_raw_parts(old_block_ptr, BLOCK_SIZE) + }; + self.device.write(self.global_offset + old_block.index, old_block_buffer); } } } @@ -64,21 +84,43 @@ impl BlockCache { /// 这个函数不应该返回 None pub(crate) fn get_block(&mut self, index: usize) -> Option<&CachedBlock> { if !self.cache.contains(&index) { + debug!("get_block(global_block_id: {}) loading from disk", index + self.global_offset); self.load_block(index); } - self.cache.get(&index).map(convert::) + + if let Some(block) = self.cache.get(&index) { + debug!("get_block(global_block_id: {}) found", index + self.global_offset); + Some(convert::(block)) + } else { + debug!("get_block(global_block_id: {}) not found", index + self.global_offset); + None + } + // debug!("get_block(global_block_id: {}) found", index + self.global_offset); + // self.cache.get(&index).map(convert::) } /// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载. /// 这个函数不应该返回 None pub(crate) fn get_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { if !self.cache.contains(&index) { + debug!("get_block_mut(global_block_id: {}) loading from disk", index + self.global_offset); self.load_block(index); } - self.cache.get_mut(&index).map(|block| { + + if let Some(block) = self.cache.get_mut(&index) { + debug!("get_block_mut(global_block_id: {}) found", index + self.global_offset); block.dirty = true; - convert_mut::(block) - }) + Some(convert_mut::(block)) + } else { + debug!("get_block_mut(global_block_id: {}) not found", index + self.global_offset); + None + } + + // self.cache.get_mut(&index).map(|block| { + // debug!("get_block_mut(global_block_id: {}) found", index + self.global_offset); + // block.dirty = true; + // convert_mut::(block) + // }) } /// 向 LRU cache 中插入一个全新初始化的 block @@ -94,7 +136,7 @@ impl BlockCache { 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); + self.device.write(self.global_offset + old_index, old_block_buffer); } } } @@ -115,15 +157,18 @@ impl BlockCache { if self.cache.contains(&block.index) { let mut data_block = convert::(&block).clone(); data_block.dirty = true; // TODO 需要把显式写回的都标记为 dirty 吗 - self.cache.push(block.index, data_block); + let (entry, _value) = self.cache.push(block.index, data_block).unwrap(); + assert_eq!(entry, block.index); + debug!("update_block(global_block_id: {})", block.index + self.global_offset); true } else { false } } - fn pop(&mut self, entry: &usize) -> Option> { - self.cache.pop(entry) + fn pop(&mut self, entry: usize) -> Option> { + debug!("pop_block(global_block_id: {})", entry + self.global_offset); + self.cache.pop(&entry) } } @@ -134,9 +179,11 @@ impl AyaFS { pub(crate) fn get_block(&mut self, index: usize) -> Option<&CachedBlock> { if self.data_bitmap.query(index) { + debug!("get_block(block_id: {}) found", index); Some(self.cached_blocks.get_block::(index).unwrap()) } else { - self.cached_blocks.pop(&index); + debug!("get_block(block_id: {}) not exist", index); + self.cached_blocks.pop(index); None } // self.data_bitmap @@ -149,7 +196,7 @@ impl AyaFS { if self.data_bitmap.query(index) { Some(self.cached_blocks.get_block_mut::(index).unwrap()) } else { - self.cached_blocks.pop(&index); + self.cached_blocks.pop(index); None } // self.data_bitmap diff --git a/ayafs-core/src/memory/cached_inode.rs b/ayafs-core/src/memory/cached_inode.rs index 2f26dde..70579c7 100644 --- a/ayafs-core/src/memory/cached_inode.rs +++ b/ayafs-core/src/memory/cached_inode.rs @@ -15,7 +15,7 @@ impl AyaFS { ) -> Option<(usize, &Inode)> { self.inode_bitmap.allocate().map(|inode_index| { self.get_inode_mut(inode_index).map(|inode| { - *inode = Inode::file(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0); + *inode = Inode::file(permissions, uid, gid, utils::time_now(), flags, 0, 0); }); (inode_index, self.get_inode(inode_index).unwrap()) }) @@ -30,7 +30,7 @@ impl AyaFS { ) -> Option<(usize, &Inode)> { self.inode_bitmap.allocate().map(|inode_index| { self.get_inode_mut(inode_index).map(|inode| { - *inode = Inode::symlink(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0); + *inode = Inode::symlink(permissions, uid, gid, utils::time_now(), flags, 0, 0); }); (inode_index, self.get_inode(inode_index).unwrap()) }) @@ -48,7 +48,7 @@ impl AyaFS { self.inode_bitmap.allocate().map(|inode_index| { // 创建 Inode let mut new_inode = - Inode::directory(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0); + Inode::directory(permissions, uid, gid, utils::time_now(), flags, 0, 0); self.init_direntry_map(inode_index); self.add_direntry(inode_index, &mut new_inode, inode_index, ".", 0x2) .unwrap(); @@ -85,6 +85,7 @@ impl AyaFS { _ => return Err(EIO), } } + // self.update_inode(inode_index, Inode::empty()); self.inode_bitmap.deallocate(inode_index); Ok(true) } else { @@ -123,6 +124,7 @@ impl AyaFS { if let Some(cached_block) = self.cached_inodes.get_block_mut::(block_index) { cached_block.block.inodes[offset / INODE_SIZE] = inode; + cached_block.dirty = true; } true } else { diff --git a/ayafs-core/src/memory/dir_entry.rs b/ayafs-core/src/memory/dir_entry.rs index 55c67bd..3880f61 100644 --- a/ayafs-core/src/memory/dir_entry.rs +++ b/ayafs-core/src/memory/dir_entry.rs @@ -38,9 +38,11 @@ impl AyaFS { match self.access_block::(inode, block_index_within_inode) { Some(directory_block) => { + debug!("bitmap for block is {:#b} {:#b}", directory_block.block.occupancy[0], directory_block.block.occupancy[1]); if directory_block.block.query(entry_index_within_block) { let dir_entry = &directory_block.block.entries[entry_index_within_block]; let name = dir_entry.name(); + debug!("loaded entry({:?}) for inode {}", name.as_os_str(), index); dir_entry_map.insert(name, dir_entry.clone()); } else { break; @@ -70,7 +72,7 @@ impl AyaFS { parent_inode: &mut Inode, dir_entry_map: IndexMap, ) -> Result<(), c_int> { - for (entry_index, (_, dir_entry)) in dir_entry_map.into_iter().enumerate() { + for (entry_index, (name, dir_entry)) in dir_entry_map.into_iter().enumerate() { let block_index_within_inode = entry_index / 15; let entry_index_within_block = entry_index % 15; // 不够就新分配 @@ -89,7 +91,13 @@ impl AyaFS { } match self.access_block_mut::(parent_inode, block_index_within_inode) { Some(directory_block) => { + if entry_index_within_block == 0 { + directory_block.block.reset(); + } + directory_block.dirty = true; + debug!("entry {} (block {} offset {}) for inode {}, name {:?}", entry_index, block_index_within_inode, entry_index_within_block, _parent_index, name); directory_block.block.allocate(entry_index_within_block); + debug!("bitmap for block is {:#b} {:#b}", directory_block.block.occupancy[0], directory_block.block.occupancy[1]); directory_block.block.entries[entry_index_within_block] = dir_entry; } None => { @@ -291,10 +299,10 @@ impl AyaFS { } else { let mut entry_index = 0; while entry_index < parent_inode.size { - if let Ok(entry) = self.get_direntry(parent_index, parent_inode, entry_index) { + if let Ok(entry) = self.get_direntry(parent_index, parent_inode, entry_index as u32) { 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 as u32, inode)); } } entry_index += 1; -- cgit v1.2.3-70-g09d2