Skip to content

Commit

Permalink
BlockCache-read cache支持 (#521)
Browse files Browse the repository at this point in the history
支持block cache的读缓存
  • Loading branch information
ZZJJWarth authored Apr 7, 2024
1 parent 06560af commit eb49bb9
Show file tree
Hide file tree
Showing 19 changed files with 797 additions and 26 deletions.
95 changes: 78 additions & 17 deletions kernel/src/driver/base/block/block_device.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
/// 引入Module
use crate::{
driver::base::{
device::{
device_number::{DeviceNumber, Major},
Device, DeviceError, IdTable, BLOCKDEVS,
},
map::{
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX,
driver::{
base::{
device::{
device_number::{DeviceNumber, Major},
Device, DeviceError, IdTable, BLOCKDEVS,
},
map::{
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX,
},
},
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
},
kerror,
};
Expand Down Expand Up @@ -195,7 +198,7 @@ pub trait BlockDevice: Device {
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
/// 否则返回Err(错误码),其中错误码为负数;
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
fn read_at(
fn read_at_sync(
&self,
lba_id_start: BlockId,
count: usize,
Expand All @@ -209,7 +212,7 @@ pub trait BlockDevice: Device {
/// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节;
/// 否则返回Err(错误码),其中错误码为负数;
/// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度)
fn write_at(
fn write_at_sync(
&self,
lba_id_start: BlockId,
count: usize,
Expand Down Expand Up @@ -240,8 +243,72 @@ pub trait BlockDevice: Device {
/// @brief 返回当前磁盘上的所有分区的Arc指针数组
fn partitions(&self) -> Vec<Arc<Partition>>;

/// # 函数的功能
/// 经由Cache对块设备的读操作
fn read_at(
&self,
lba_id_start: BlockId,
count: usize,
buf: &mut [u8],
) -> Result<usize, SystemError> {
self.cache_read(lba_id_start, count, buf)
}

/// # 函数的功能
/// 经由Cache对块设备的写操作
fn write_at(
&self,
lba_id_start: BlockId,
count: usize,
buf: &[u8],
) -> Result<usize, SystemError> {
self.cache_write(lba_id_start, count, buf)
}

/// # 函数的功能
/// 其功能对外而言和read_at函数完全一致,但是加入blockcache的功能
fn cache_read(
&self,
lba_id_start: BlockId,
count: usize,
buf: &mut [u8],
) -> Result<usize, SystemError> {
let cache_response = BlockCache::read(lba_id_start, count, buf);
if let Err(e) = cache_response {
match e {
BlockCacheError::StaticParameterError => {
BlockCache::init();
let ans = self.read_at_sync(lba_id_start, count, buf)?;
return Ok(ans);
}
BlockCacheError::BlockFaultError(fail_vec) => {
let ans = self.read_at_sync(lba_id_start, count, buf)?;
let _ = BlockCache::insert(fail_vec, buf);
return Ok(ans);
}
_ => {
let ans = self.read_at_sync(lba_id_start, count, buf)?;
return Ok(ans);
}
}
} else {
return Ok(count * BLOCK_SIZE);
}
}

/// # 函数功能
/// 其功能对外而言和write_at函数完全一致,但是加入blockcache的功能
fn cache_write(
&self,
lba_id_start: BlockId,
count: usize,
buf: &[u8],
) -> Result<usize, SystemError> {
let _cache_response = BlockCache::immediate_write(lba_id_start, count, buf);
self.write_at_sync(lba_id_start, count, buf)
}

fn write_at_bytes(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
// assert!(len <= buf.len());
if len > buf.len() {
return Err(SystemError::E2BIG);
}
Expand Down Expand Up @@ -272,7 +339,6 @@ pub trait BlockDevice: Device {
}
}
return Ok(len);
//self.0.lock().write_at(lba_id_start, count, buf)
}

fn read_at_bytes(
Expand Down Expand Up @@ -314,11 +380,6 @@ pub trait BlockDevice: Device {
}
}
return Ok(len);

// kdebug!(
// "ahci read at {lba_id_start}, count={count}, lock={:?}",
// self.0
// );
}
}

Expand Down
1 change: 0 additions & 1 deletion kernel/src/driver/base/block/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod block_device;
pub mod disk_info;

#[derive(Debug)]
#[allow(dead_code)]
pub enum SeekFrom {
Expand Down
54 changes: 54 additions & 0 deletions kernel/src/driver/block/cache/cache_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use alloc::{boxed::Box, vec::Vec};

use crate::driver::base::block::block_device::BlockId;

use super::{BlockCacheError, BLOCK_SIZE};

/// # 枚举功能
/// 该枚举设计来是用于实现回写法的,但是目前并未使用
#[allow(dead_code)]
pub enum CacheBlockFlag {
Unused,
Unwrited,
Writed,
}

pub type CacheBlockAddr = usize;

/// # 结构功能
/// 存储数据的最小单位
pub struct CacheBlock {
data: Box<[u8]>,
_flag: CacheBlockFlag,
lba_id: BlockId,
}

impl CacheBlock {
pub fn new(data: Box<[u8]>, flag: CacheBlockFlag, lba_id: BlockId) -> Self {
CacheBlock {
data,
_flag: flag,
lba_id,
}
}

pub fn from_data(lba_id: BlockId, data: Vec<u8>) -> Self {
let space_box = data.into_boxed_slice();
CacheBlock::new(space_box, CacheBlockFlag::Unwrited, lba_id)
}

pub fn _set_flag(&mut self, _flag: CacheBlockFlag) -> Option<()> {
todo!()
}
pub fn data(&self, buf: &mut [u8]) -> Result<usize, BlockCacheError> {
if buf.len() != BLOCK_SIZE {
return Err(BlockCacheError::BlockSizeError);
}
buf.copy_from_slice(&self.data);
return Ok(BLOCK_SIZE);
}

pub fn lba_id(&self) -> BlockId {
self.lba_id
}
}
102 changes: 102 additions & 0 deletions kernel/src/driver/block/cache/cache_iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use crate::driver::base::block::block_device::BlockId;

/// # 结构功能
/// 一个简单的结构体,是BlockIter的输出
#[derive(Debug)]
pub struct BlockData {
/// 表示单个块对应的lba_id
lba_id: BlockId,
/// 表示该块在buf中的起始地址,目前并没有作用(例如:若该块是第2个块,那么该数据成员值为2*BLOCK_SIZE)
_data_start_addr: BlockId,
/// 表示该块的大小
_block_size: usize,
}

impl BlockData {
pub fn new(lba_id: BlockId, data_start_addr: BlockId, block_size: usize) -> Self {
Self {
lba_id,
_data_start_addr: data_start_addr,
_block_size: block_size,
}
}
#[inline]
pub fn lba_id(&self) -> BlockId {
self.lba_id
}
#[inline]
pub fn _data_start_addr(&self) -> BlockId {
self._data_start_addr
}
#[inline]
pub fn _block_size(&self) -> usize {
self._block_size
}
}

/// # 结构功能
/// 块迭代器,它获取需求(起始块,连续块的个数),并将连续的块输出为单一的块(如你需要读取lba_id为10~20的连续块,它就可以输出10,11...,20的BlockData)
#[derive(Copy, Clone)]
pub struct BlockIter {
/// 表示起始块的lba_id
lba_id_start: BlockId,
/// 表示从起始块开始你需要读多少个块
count: usize,
/// 表示当前遍历到第几个块了
current: usize,
/// 规定块的大小
block_size: usize,
}

impl BlockIter {
pub fn new(lba_id_start: BlockId, count: usize, block_size: usize) -> Self {
Self {
lba_id_start,
count,
block_size,
current: 0,
}
}
}

impl Iterator for BlockIter {
type Item = BlockData;

fn next(&mut self) -> Option<Self::Item> {
if self.current < self.count {
let ans = BlockData::new(
self.lba_id_start + self.current,
self.current * self.block_size,
self.block_size,
);
self.current += 1;
Some(ans)
} else {
None
}
}
}

/// # 结构功能
/// 表示缺块信息的数据结构,往往在读取的时候发现缺块并产生FailData,在插入的时候使用FailData
pub struct FailData {
/// 表示缺块的lba_id
lba_id: BlockId,
/// 表示缺块在buf中的位置,用于在insert的时候定位缺块数据的位置
index: usize,
}

impl FailData {
pub fn new(lba_id: BlockId, index: usize) -> Self {
FailData { lba_id, index }
}
#[inline]
pub fn lba_id(&self) -> BlockId {
self.lba_id
}
/// # 函数的功能
/// 该函数返回的是缺块在buf中的位置,比如:index=1,那么我们就应该取buf\[512..1024\]
pub fn index(&self) -> usize {
self.index
}
}
Loading

0 comments on commit eb49bb9

Please sign in to comment.