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 ++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 16 deletions(-) (limited to 'ayafs-core/src/memory/cached_block.rs') 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 -- cgit v1.2.3-70-g09d2