parent
5b846fce6a
commit
f9fc2a538c
1 changed files with 44 additions and 10 deletions
|
@ -1,12 +1,40 @@
|
||||||
use super::{BlockDevice, BLOCK_SZ};
|
use super::{BlockDevice, BLOCK_SZ};
|
||||||
use alloc::collections::VecDeque;
|
use alloc::collections::VecDeque;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
use core::slice;
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
|
/// use `Vec<u64>` to ensure the alignment of addr is `8`
|
||||||
|
struct CacheData(Vec<u64>);
|
||||||
|
|
||||||
|
impl CacheData {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self(vec![0u64; BLOCK_SZ / 8])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[u8]> for CacheData {
|
||||||
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
let ptr = self.0.as_ptr() as *const u8;
|
||||||
|
unsafe { slice::from_raw_parts(ptr, BLOCK_SZ) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<[u8]> for CacheData {
|
||||||
|
fn as_mut(&mut self) -> &mut [u8] {
|
||||||
|
let ptr = self.0.as_mut_ptr() as *mut u8;
|
||||||
|
unsafe { slice::from_raw_parts_mut(ptr, BLOCK_SZ) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Cached block inside memory
|
/// Cached block inside memory
|
||||||
pub struct BlockCache {
|
pub struct BlockCache {
|
||||||
/// cached block data
|
/// cached block data
|
||||||
cache: [u8; BLOCK_SZ],
|
cache: CacheData,
|
||||||
/// underlying block id
|
/// underlying block id
|
||||||
block_id: usize,
|
block_id: usize,
|
||||||
/// underlying block device
|
/// underlying block device
|
||||||
|
@ -18,8 +46,9 @@ pub struct BlockCache {
|
||||||
impl BlockCache {
|
impl BlockCache {
|
||||||
/// Load a new BlockCache from disk.
|
/// Load a new BlockCache from disk.
|
||||||
pub fn new(block_id: usize, block_device: Arc<dyn BlockDevice>) -> Self {
|
pub fn new(block_id: usize, block_device: Arc<dyn BlockDevice>) -> Self {
|
||||||
let mut cache = [0u8; BLOCK_SZ];
|
// for alignment and move effciency
|
||||||
block_device.read_block(block_id, &mut cache);
|
let mut cache = CacheData::new();
|
||||||
|
block_device.read_block(block_id, cache.as_mut());
|
||||||
Self {
|
Self {
|
||||||
cache,
|
cache,
|
||||||
block_id,
|
block_id,
|
||||||
|
@ -28,8 +57,12 @@ impl BlockCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the address of an offset inside the cached block data
|
/// Get the address of an offset inside the cached block data
|
||||||
fn addr_of_offset(&self, offset: usize) -> usize {
|
fn addr_of_offset(&self, offset: usize) -> *const u8 {
|
||||||
&self.cache[offset] as *const _ as usize
|
addr_of!(self.cache.as_ref()[offset])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addr_of_offset_mut(&mut self, offset: usize) -> *mut u8 {
|
||||||
|
addr_of_mut!(self.cache.as_mut()[offset])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ref<T>(&self, offset: usize) -> &T
|
pub fn get_ref<T>(&self, offset: usize) -> &T
|
||||||
|
@ -38,8 +71,8 @@ impl BlockCache {
|
||||||
{
|
{
|
||||||
let type_size = core::mem::size_of::<T>();
|
let type_size = core::mem::size_of::<T>();
|
||||||
assert!(offset + type_size <= BLOCK_SZ);
|
assert!(offset + type_size <= BLOCK_SZ);
|
||||||
let addr = self.addr_of_offset(offset);
|
let addr = self.addr_of_offset(offset) as *const T;
|
||||||
unsafe { &*(addr as *const T) }
|
unsafe { &*addr }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut<T>(&mut self, offset: usize) -> &mut T
|
pub fn get_mut<T>(&mut self, offset: usize) -> &mut T
|
||||||
|
@ -49,8 +82,8 @@ impl BlockCache {
|
||||||
let type_size = core::mem::size_of::<T>();
|
let type_size = core::mem::size_of::<T>();
|
||||||
assert!(offset + type_size <= BLOCK_SZ);
|
assert!(offset + type_size <= BLOCK_SZ);
|
||||||
self.modified = true;
|
self.modified = true;
|
||||||
let addr = self.addr_of_offset(offset);
|
let addr = self.addr_of_offset_mut(offset) as *mut T;
|
||||||
unsafe { &mut *(addr as *mut T) }
|
unsafe { &mut *addr }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<T, V>(&self, offset: usize, f: impl FnOnce(&T) -> V) -> V {
|
pub fn read<T, V>(&self, offset: usize, f: impl FnOnce(&T) -> V) -> V {
|
||||||
|
@ -64,7 +97,8 @@ impl BlockCache {
|
||||||
pub fn sync(&mut self) {
|
pub fn sync(&mut self) {
|
||||||
if self.modified {
|
if self.modified {
|
||||||
self.modified = false;
|
self.modified = false;
|
||||||
self.block_device.write_block(self.block_id, &self.cache);
|
self.block_device
|
||||||
|
.write_block(self.block_id, self.cache.as_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue