diff options
Diffstat (limited to 'ayafs-core/src/memory/cached_block.rs')
-rw-r--r-- | ayafs-core/src/memory/cached_block.rs | 79 |
1 files changed, 63 insertions, 16 deletions
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<T: Block> { @@ -27,20 +28,37 @@ pub fn convert<U: Block, T: Block>(input_block: &CachedBlock<U>) -> &CachedBlock pub(crate) struct BlockCache<T: Block> { device: Arc<dyn BlockDevice>, cache: LruCache<usize, CachedBlock<T>>, + pub global_offset: usize, } impl<T: Block> BlockCache<T> { - pub(crate) fn new(device: Arc<dyn BlockDevice>, cache_size: usize) -> Self { + pub(crate) fn new(device: Arc<dyn BlockDevice>, 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::<T>()) + }; + 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<T: Block> BlockCache<T> { 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<T: Block> BlockCache<T> { /// 这个函数不应该返回 None pub(crate) fn get_block<U: Block>(&mut self, index: usize) -> Option<&CachedBlock<U>> { 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::<T, U>) + + if let Some(block) = self.cache.get(&index) { + debug!("get_block(global_block_id: {}) found", index + self.global_offset); + Some(convert::<T, U>(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::<T, U>) } /// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载. /// 这个函数不应该返回 None pub(crate) fn get_block_mut<U: Block>(&mut self, index: usize) -> Option<&mut CachedBlock<U>> { 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::<T, U>(block) - }) + Some(convert_mut::<T, U>(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::<T, U>(block) + // }) } /// 向 LRU cache 中插入一个全新初始化的 block @@ -94,7 +136,7 @@ impl<T: Block> BlockCache<T> { 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<T: Block> BlockCache<T> { if self.cache.contains(&block.index) { let mut data_block = convert::<U, T>(&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<CachedBlock<T>> { - self.cache.pop(entry) + fn pop(&mut self, entry: usize) -> Option<CachedBlock<T>> { + 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<T: Block>(&mut self, index: usize) -> Option<&CachedBlock<T>> { if self.data_bitmap.query(index) { + debug!("get_block(block_id: {}) found", index); Some(self.cached_blocks.get_block::<T>(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::<T>(index).unwrap()) } else { - self.cached_blocks.pop(&index); + self.cached_blocks.pop(index); None } // self.data_bitmap |