Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions kernel/src/driver/block/cache/cache_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,25 @@ impl CacheBlock {
CacheBlock::new(space_box, CacheBlockFlag::Unwrited, lba_id)
}

/// 从 slice 创建一个 CacheBlock(避免先构造 Vec 再 into_boxed_slice 的额外分配/拷贝步骤)。
pub fn from_slice(lba_id: BlockId, data: &[u8]) -> Result<Self, BlockCacheError> {
if data.len() != BLOCK_SIZE {
return Err(BlockCacheError::BlockSizeError);
}
let mut v = Vec::with_capacity(BLOCK_SIZE);
v.extend_from_slice(data);
Ok(Self::from_data(lba_id, v))
}

/// 用新数据覆盖当前 cache block(用于 write-through 更新)。
pub fn write_data(&mut self, data: &[u8]) -> Result<(), BlockCacheError> {
if data.len() != BLOCK_SIZE {
return Err(BlockCacheError::BlockSizeError);
}
self.data.copy_from_slice(data);
Ok(())
}

pub fn _set_flag(&mut self, _flag: CacheBlockFlag) -> Option<()> {
todo!()
}
Expand Down
60 changes: 47 additions & 13 deletions kernel/src/driver/block/cache/cached_block_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,12 @@ impl BlockCache {
let count = f_data_vec.len();
for i in f_data_vec {
let index = i.index();
Self::insert_one_block(
i.lba_id(),
data[index * BLOCK_SIZE..(index + 1) * BLOCK_SIZE].to_vec(),
)?;
let start = index * BLOCK_SIZE;
let end = (index + 1) * BLOCK_SIZE;
if end > data.len() {
return Err(BlockCacheError::BlockSizeError);
}
Self::insert_one_block(i.lba_id(), &data[start..end])?;
}
Ok(count)
}
Expand All @@ -163,7 +165,7 @@ impl BlockCache {
/// ## 返回值:
/// Ok(()):表示插入成功
/// Err(BlockCacheError) :一般来说不会产生错误,这里产生错误的原因只有插入时还没有初始化(一般也很难发生)
fn insert_one_block(lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
fn insert_one_block(lba_id: BlockId, data: &[u8]) -> Result<(), BlockCacheError> {
let space = unsafe { space()? };
space.insert(lba_id, data)
}
Expand All @@ -181,12 +183,28 @@ impl BlockCache {
pub fn immediate_write(
lba_id_start: BlockId,
count: usize,
_data: &[u8],
data: &[u8],
) -> Result<usize, BlockCacheError> {
if data.len() < count * BLOCK_SIZE {
return Err(BlockCacheError::BlockSizeError);
}

let mapper = unsafe { mapper()? };
let space = unsafe { space()? };
let block_iter = BlockIter::new(lba_id_start, count, BLOCK_SIZE);
for i in block_iter {
mapper.remove(i.lba_id());
for (idx, i) in block_iter.enumerate() {
let lba_id = i.lba_id();
let start = idx * BLOCK_SIZE;
let end = (idx + 1) * BLOCK_SIZE;
let block_data = &data[start..end];

// write-through:如果 cache 中已有该块,更新其内容;否则插入以保持 cache 热度
if let Some(addr) = mapper.find(lba_id) {
space.write(addr, block_data)?;
} else {
// 不要 remove 映射(会导致 cache 空间和 slab 使用量单调增长)
space.insert(lba_id, block_data)?;
}
}
Ok(count)
}
Expand All @@ -212,9 +230,14 @@ impl LockedCacheSpace {
todo!()
}

pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
pub fn insert(&mut self, lba_id: BlockId, data: &[u8]) -> Result<(), BlockCacheError> {
unsafe { self.0.get_mut().insert(lba_id, data) }
}

/// 写入已存在的 cache block(write-through 更新)
pub fn write(&mut self, addr: CacheBlockAddr, data: &[u8]) -> Result<(), BlockCacheError> {
unsafe { self.0.get_mut().write(addr, data) }
}
}

/// # 结构功能
Expand Down Expand Up @@ -273,9 +296,9 @@ impl CacheSpace {
///
/// ## 返回值:
/// Ok(())
pub fn insert(&mut self, lba_id: BlockId, data: Vec<u8>) -> Result<(), BlockCacheError> {
// CacheBlock是cached block的基本单位,这里使用data生成一个CacheBlock用于向Cache空间中插入块
let data_block = CacheBlock::from_data(lba_id, data);
pub fn insert(&mut self, lba_id: BlockId, data: &[u8]) -> Result<(), BlockCacheError> {
// CacheBlock是cached block的基本单位
let data_block = CacheBlock::from_slice(lba_id, data)?;
let mapper = unsafe { mapper()? };
// 这里我设计了cache的一个threshold,如果不超过阈值就可以append,否则只能替换
if self.frame_selector.can_append() {
Expand Down Expand Up @@ -303,6 +326,16 @@ impl CacheSpace {
Ok(())
}
}

pub fn write(&mut self, addr: CacheBlockAddr, data: &[u8]) -> Result<(), BlockCacheError> {
if addr > self.frame_selector.size() {
return Err(BlockCacheError::InsufficientCacheSpace);
}
if addr >= self.root.len() {
return Err(BlockCacheError::InsufficientCacheSpace);
}
self.root[addr].write_data(data)
}
}

struct LockedCacheMapper {
Expand Down Expand Up @@ -345,7 +378,8 @@ impl CacheMapper {
/// # 函数的功能
/// 插入操作
pub fn insert(&mut self, lba_id: BlockId, caddr: CacheBlockAddr) -> Option<()> {
self.map.insert(lba_id, caddr)?;
// HashMap::insert 返回的是旧值(新 key 时为 None),不能用 `?` 否则新插入永远失败
self.map.insert(lba_id, caddr);
Some(())
}
/// # 函数的功能
Expand Down
5 changes: 1 addition & 4 deletions kernel/src/filesystem/page_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ impl InnerPageCache {

let page = page_manager_guard.create_one_page(
PageType::File(FileMapInfo {
page_cache: self
.page_cache_ref
.upgrade()
.expect("failed to get self_arc of pagecache"),
page_cache: self.page_cache_ref.clone(),
index: page_index,
}),
PageFlags::PG_LRU,
Expand Down
23 changes: 17 additions & 6 deletions kernel/src/mm/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::{
use system_error::SystemError;
use unified_init::macros::unified_init;

use alloc::sync::Arc;
use alloc::sync::{Arc, Weak};
use hashbrown::{HashMap, HashSet};
use log::{error, info};
use lru::LruCache;
Expand Down Expand Up @@ -332,7 +332,6 @@ impl PageReclaimer {
for page in victims {
let mut guard = page.write_irqsave();
if let PageType::File(info) = guard.page_type().clone() {
let page_cache = info.page_cache;
let page_index = info.index;
let paddr = guard.phys_address();

Expand All @@ -342,7 +341,12 @@ impl PageReclaimer {
}

// 删除页面:顺序为 page_cache -> page_manager,避免原有的 reclaimer 锁参与死锁
page_cache.lock_irqsave().remove_page(page_index);
//
// FileMapInfo 内保存 Weak<PageCache> 以避免 PageCache <-> Page 的强引用环。
// 如果此时 PageCache 已被释放(upgrade 失败),说明其 pages 映射也已销毁,无需再 remove。
if let Some(page_cache) = info.page_cache.upgrade() {
page_cache.lock_irqsave().remove_page(page_index);
}
page_manager_lock_irqsave().remove_page(&paddr);
}
}
Expand All @@ -366,7 +370,13 @@ impl PageReclaimer {
// log::debug!("page writeback: {:?}", guard.phys_addr);

let (page_cache, page_index) = match guard.page_type() {
PageType::File(info) => (info.page_cache.clone(), info.index),
PageType::File(info) => match info.page_cache.upgrade() {
Some(page_cache) => (page_cache, info.index),
None => {
log::warn!("try to writeback a file page but page_cache already dropped");
return;
}
},
_ => {
log::warn!("try to writeback a non-file page");
return;
Expand Down Expand Up @@ -584,7 +594,7 @@ impl InnerPage {

pub fn page_cache(&self) -> Option<Arc<PageCache>> {
match &self.page_type {
PageType::File(info) => Some(info.page_cache.clone()),
PageType::File(info) => info.page_cache.upgrade(),
_ => None,
}
}
Expand Down Expand Up @@ -702,7 +712,8 @@ pub enum PageType {

#[derive(Debug, Clone)]
pub struct FileMapInfo {
pub page_cache: Arc<PageCache>,
/// 指向页缓存的弱引用,避免 PageCache -> Page -> PageCache 的强引用环导致页面无法释放。
pub page_cache: Weak<PageCache>,
/// 在pagecache中的偏移
pub index: usize,
}
Expand Down
Loading