use crate::block_device::{BlockDevice, BLOCK_SIZE}; use crate::disk::block::Block; use crate::AyaFS; use and_then_some::BoolExt; use log::debug; use lru::LruCache; use std::num::NonZeroUsize; use std::sync::Arc; #[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 } } pub(crate) struct BlockCache { device: Arc, cache: LruCache>, } impl BlockCache { pub(crate) fn new(device: Arc, cache_size: usize) -> Self { Self { device, cache: LruCache::new(NonZeroUsize::new(cache_size).unwrap()), } } 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); let block: T = unsafe { std::mem::transmute_copy(&buffer) }; let cached_block = CachedBlock { block, index, dirty: false, }; 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); } } } true } /// 从 LRU cache 里获取一个 block 的引用, 如果没有在 cache 中会加载. pub(crate) fn get_block(&mut self, index: usize) -> Option<&CachedBlock> { self.load_block(index) .and_then(|| self.cache.get(&index).map(convert::)) } /// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载. pub(crate) fn get_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { debug!("Blockcache get block mut"); self.load_block(index).and_then(|| { debug!("block loaded"); self.cache.get_mut(&index).map(convert_mut::) }) } /// 从 LRU cache 中读取一个 block 的引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载. pub(crate) fn peek_block(&self, index: usize) -> Option<&CachedBlock> { self.cache.peek(&index).map(convert::) } /// 从 LRU cache 中读取一个 block 的可变引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载. pub(crate) fn peek_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { self.cache.peek_mut(&index).map(convert_mut::) } pub(crate) fn update_block(&mut self, block: CachedBlock) -> bool { if self.cache.contains(&block.index) { let data_block = convert::(&block).clone(); self.cache.push(block.index, data_block); true } else { false } } fn pop(&mut self, entry: &usize) -> Option> { self.cache.pop(entry) } } 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 get_block(&mut self, index: usize) -> Option<&CachedBlock> { self.data_bitmap .query(index) .and_then(|| self.cached_blocks.get_block::(index)) } pub(crate) fn get_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { self.data_bitmap .query(index) .and_then(|| self.cached_blocks.get_block_mut::(index)) } pub(crate) fn peek_block(&self, index: usize) -> Option<&CachedBlock> { self.data_bitmap .query(index) .and_then(|| self.cached_blocks.peek_block::(index)) } pub(crate) fn peek_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { self.data_bitmap .query(index) .and_then(|| self.cached_blocks.peek_block_mut::(index)) } pub(crate) fn update_block(&mut self, block: CachedBlock) -> bool { self.cached_blocks.update_block(block) } // 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 // } // } // // /// 从 LRU cache 里获取一个 block 的引用, 如果没有在 cache 中会加载. // pub(crate) fn get_block(&mut self, index: usize) -> Option<&CachedBlock> { // self.load_block(index) // .and_then(|| self.cached_blocks.get(&index).map(convert::)) // } // // /// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载. // 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::) // }) // } // // /// 从 LRU cache 中读取一个 block 的引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载. // pub(crate) fn peek_block(&self, index: usize) -> Option<&CachedBlock> { // self.cached_blocks.peek(&index).map(convert::) // } // // /// 从 LRU cache 中读取一个 block 的可变引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载. // pub(crate) fn peek_block_mut(&mut self, index: usize) -> Option<&mut CachedBlock> { // self.cached_blocks.peek_mut(&index).map(convert_mut::) // } // // pub(crate) fn load_block(&mut self, index: usize) -> bool { // // 先看这个 block 是不是 valid, 不 valid 直接返回 false. // if !self.data_bitmap.query(index) { // self.cached_blocks.pop(&index); // // deallocate 时只更新 bitmap 没有动 cache, lazy 地驱逐 cache 中的无效 entry. // return false; // } // // // 接下来这个 block 一定 valid. 如果 cache 里没有这个 block 就把它 load 到 cache 里 // if self.cached_blocks.contains(&index) == false { // 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); // } // } // } // // true // } }