Use CachePage in all related block functions

This commit is contained in:
Zhang Junyang
2024-12-27 11:55:56 +08:00
committed by Tate, Hongliang Tian
parent 983a6af3cc
commit ff453f5933
11 changed files with 72 additions and 67 deletions

View File

@ -12,7 +12,7 @@ use aster_block::{
}; };
use hashbrown::HashMap; use hashbrown::HashMap;
use lru::LruCache; use lru::LruCache;
use ostd::mm::UFrame; use ostd::mm::Segment;
pub(super) use ostd::mm::VmIo; pub(super) use ostd::mm::VmIo;
use super::{ use super::{
@ -25,7 +25,7 @@ use super::{
use crate::{ use crate::{
fs::{ fs::{
exfat::{constants::*, inode::Ino}, exfat::{constants::*, inode::Ino},
utils::{FileSystem, FsFlags, Inode, PageCache, PageCacheBackend, SuperBlock}, utils::{CachePage, FileSystem, FsFlags, Inode, PageCache, PageCacheBackend, SuperBlock},
}, },
prelude::*, prelude::*,
}; };
@ -368,24 +368,28 @@ impl ExfatFS {
} }
impl PageCacheBackend for ExfatFS { impl PageCacheBackend for ExfatFS {
fn read_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn read_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
if self.fs_size() < idx * PAGE_SIZE { if self.fs_size() < idx * PAGE_SIZE {
return_errno_with_message!(Errno::EINVAL, "invalid read size") return_errno_with_message!(Errno::EINVAL, "invalid read size")
} }
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::FromDevice); Segment::from(frame.clone()).into(),
BioDirection::FromDevice,
);
let waiter = self let waiter = self
.block_device .block_device
.read_blocks_async(BlockId::new(idx as u64), bio_segment)?; .read_blocks_async(BlockId::new(idx as u64), bio_segment)?;
Ok(waiter) Ok(waiter)
} }
fn write_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn write_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
if self.fs_size() < idx * PAGE_SIZE { if self.fs_size() < idx * PAGE_SIZE {
return_errno_with_message!(Errno::EINVAL, "invalid write size") return_errno_with_message!(Errno::EINVAL, "invalid write size")
} }
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::ToDevice); Segment::from(frame.clone()).into(),
BioDirection::ToDevice,
);
let waiter = self let waiter = self
.block_device .block_device
.write_blocks_async(BlockId::new(idx as u64), bio_segment)?; .write_blocks_async(BlockId::new(idx as u64), bio_segment)?;

View File

@ -13,7 +13,7 @@ use aster_block::{
BLOCK_SIZE, BLOCK_SIZE,
}; };
use aster_rights::Full; use aster_rights::Full;
use ostd::mm::{UFrame, VmIo}; use ostd::mm::{Segment, VmIo};
use super::{ use super::{
constants::*, constants::*,
@ -30,8 +30,8 @@ use crate::{
fs::{ fs::{
exfat::{dentry::ExfatDentryIterator, fat::ExfatChain, fs::ExfatFS}, exfat::{dentry::ExfatDentryIterator, fat::ExfatChain, fs::ExfatFS},
utils::{ utils::{
DirentVisitor, Extension, Inode, InodeMode, InodeType, IoctlCmd, Metadata, MknodType, CachePage, DirentVisitor, Extension, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
PageCache, PageCacheBackend, MknodType, PageCache, PageCacheBackend,
}, },
}, },
prelude::*, prelude::*,
@ -135,14 +135,16 @@ struct ExfatInodeInner {
} }
impl PageCacheBackend for ExfatInode { impl PageCacheBackend for ExfatInode {
fn read_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn read_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
let inner = self.inner.read(); let inner = self.inner.read();
if inner.size < idx * PAGE_SIZE { if inner.size < idx * PAGE_SIZE {
return_errno_with_message!(Errno::EINVAL, "Invalid read size") return_errno_with_message!(Errno::EINVAL, "Invalid read size")
} }
let sector_id = inner.get_sector_id(idx * PAGE_SIZE / inner.fs().sector_size())?; let sector_id = inner.get_sector_id(idx * PAGE_SIZE / inner.fs().sector_size())?;
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::FromDevice); Segment::from(frame.clone()).into(),
BioDirection::FromDevice,
);
let waiter = inner.fs().block_device().read_blocks_async( let waiter = inner.fs().block_device().read_blocks_async(
BlockId::from_offset(sector_id * inner.fs().sector_size()), BlockId::from_offset(sector_id * inner.fs().sector_size()),
bio_segment, bio_segment,
@ -150,7 +152,7 @@ impl PageCacheBackend for ExfatInode {
Ok(waiter) Ok(waiter)
} }
fn write_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn write_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
let inner = self.inner.read(); let inner = self.inner.read();
let sector_size = inner.fs().sector_size(); let sector_size = inner.fs().sector_size();
@ -158,8 +160,10 @@ impl PageCacheBackend for ExfatInode {
// FIXME: We may need to truncate the file if write_page fails. // FIXME: We may need to truncate the file if write_page fails.
// To fix this issue, we need to change the interface of the PageCacheBackend trait. // To fix this issue, we need to change the interface of the PageCacheBackend trait.
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::ToDevice); Segment::from(frame.clone()).into(),
BioDirection::ToDevice,
);
let waiter = inner.fs().block_device().write_blocks_async( let waiter = inner.fs().block_device().write_blocks_async(
BlockId::from_offset(sector_id * inner.fs().sector_size()), BlockId::from_offset(sector_id * inner.fs().sector_size()),
bio_segment, bio_segment,

View File

@ -318,20 +318,24 @@ impl Debug for BlockGroup {
} }
impl PageCacheBackend for BlockGroupImpl { impl PageCacheBackend for BlockGroupImpl {
fn read_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn read_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
let bid = self.inode_table_bid + idx as Ext2Bid; let bid = self.inode_table_bid + idx as Ext2Bid;
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::FromDevice); Segment::from(frame.clone()).into(),
BioDirection::FromDevice,
);
self.fs self.fs
.upgrade() .upgrade()
.unwrap() .unwrap()
.read_blocks_async(bid, bio_segment) .read_blocks_async(bid, bio_segment)
} }
fn write_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn write_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
let bid = self.inode_table_bid + idx as Ext2Bid; let bid = self.inode_table_bid + idx as Ext2Bid;
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::ToDevice); Segment::from(frame.clone()).into(),
BioDirection::ToDevice,
);
self.fs self.fs
.upgrade() .upgrade()
.unwrap() .unwrap()

View File

@ -42,7 +42,7 @@ impl Ext2 {
"currently only support 4096-byte block size" "currently only support 4096-byte block size"
); );
let group_descriptors_segment = { let group_descriptors_segment: USegment = {
let npages = ((super_block.block_groups_count() as usize) let npages = ((super_block.block_groups_count() as usize)
* core::mem::size_of::<RawGroupDescriptor>()) * core::mem::size_of::<RawGroupDescriptor>())
.div_ceil(BLOCK_SIZE); .div_ceil(BLOCK_SIZE);
@ -57,7 +57,7 @@ impl Ext2 {
return Err(Error::from(err_status)); return Err(Error::from(err_status));
} }
} }
segment segment.into()
}; };
// Load the block groups information // Load the block groups information
@ -88,12 +88,12 @@ impl Ext2 {
block_groups: load_block_groups( block_groups: load_block_groups(
weak_ref.clone(), weak_ref.clone(),
block_device.as_ref(), block_device.as_ref(),
(&group_descriptors_segment).into(), &group_descriptors_segment,
) )
.unwrap(), .unwrap(),
block_device, block_device,
super_block: RwMutex::new(Dirty::new(super_block)), super_block: RwMutex::new(Dirty::new(super_block)),
group_descriptors_segment: group_descriptors_segment.into(), group_descriptors_segment,
self_ref: weak_ref.clone(), self_ref: weak_ref.clone(),
}); });
Ok(ext2) Ok(ext2)

View File

@ -1733,7 +1733,7 @@ impl InodeImpl {
writer: &mut VmWriter, writer: &mut VmWriter,
) -> Result<BioWaiter>; ) -> Result<BioWaiter>;
pub fn read_blocks(&self, bid: Ext2Bid, nblocks: usize, writer: &mut VmWriter) -> Result<()>; pub fn read_blocks(&self, bid: Ext2Bid, nblocks: usize, writer: &mut VmWriter) -> Result<()>;
pub fn read_block_async(&self, bid: Ext2Bid, frame: &UFrame) -> Result<BioWaiter>; pub fn read_block_async(&self, bid: Ext2Bid, frame: &CachePage) -> Result<BioWaiter>;
pub fn write_blocks_async( pub fn write_blocks_async(
&self, &self,
bid: Ext2Bid, bid: Ext2Bid,
@ -1741,7 +1741,7 @@ impl InodeImpl {
reader: &mut VmReader, reader: &mut VmReader,
) -> Result<BioWaiter>; ) -> Result<BioWaiter>;
pub fn write_blocks(&self, bid: Ext2Bid, nblocks: usize, reader: &mut VmReader) -> Result<()>; pub fn write_blocks(&self, bid: Ext2Bid, nblocks: usize, reader: &mut VmReader) -> Result<()>;
pub fn write_block_async(&self, bid: Ext2Bid, frame: &UFrame) -> Result<BioWaiter>; pub fn write_block_async(&self, bid: Ext2Bid, frame: &CachePage) -> Result<BioWaiter>;
} }
/// Manages the inode blocks and block I/O operations. /// Manages the inode blocks and block I/O operations.
@ -1789,13 +1789,15 @@ impl InodeBlockManager {
} }
} }
pub fn read_block_async(&self, bid: Ext2Bid, frame: &UFrame) -> Result<BioWaiter> { pub fn read_block_async(&self, bid: Ext2Bid, frame: &CachePage) -> Result<BioWaiter> {
let mut bio_waiter = BioWaiter::new(); let mut bio_waiter = BioWaiter::new();
for dev_range in DeviceRangeReader::new(self, bid..bid + 1 as Ext2Bid)? { for dev_range in DeviceRangeReader::new(self, bid..bid + 1 as Ext2Bid)? {
let start_bid = dev_range.start as Ext2Bid; let start_bid = dev_range.start as Ext2Bid;
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::FromDevice); Segment::from(frame.clone()).into(),
BioDirection::FromDevice,
);
let waiter = self.fs().read_blocks_async(start_bid, bio_segment)?; let waiter = self.fs().read_blocks_async(start_bid, bio_segment)?;
bio_waiter.concat(waiter); bio_waiter.concat(waiter);
} }
@ -1834,13 +1836,15 @@ impl InodeBlockManager {
} }
} }
pub fn write_block_async(&self, bid: Ext2Bid, frame: &UFrame) -> Result<BioWaiter> { pub fn write_block_async(&self, bid: Ext2Bid, frame: &CachePage) -> Result<BioWaiter> {
let mut bio_waiter = BioWaiter::new(); let mut bio_waiter = BioWaiter::new();
for dev_range in DeviceRangeReader::new(self, bid..bid + 1 as Ext2Bid)? { for dev_range in DeviceRangeReader::new(self, bid..bid + 1 as Ext2Bid)? {
let start_bid = dev_range.start as Ext2Bid; let start_bid = dev_range.start as Ext2Bid;
let bio_segment = let bio_segment = BioSegment::new_from_segment(
BioSegment::new_from_segment(frame.clone().into(), BioDirection::ToDevice); Segment::from(frame.clone()).into(),
BioDirection::ToDevice,
);
let waiter = self.fs().write_blocks_async(start_bid, bio_segment)?; let waiter = self.fs().write_blocks_async(start_bid, bio_segment)?;
bio_waiter.concat(waiter); bio_waiter.concat(waiter);
} }
@ -1858,12 +1862,12 @@ impl InodeBlockManager {
} }
impl PageCacheBackend for InodeBlockManager { impl PageCacheBackend for InodeBlockManager {
fn read_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn read_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
let bid = idx as Ext2Bid; let bid = idx as Ext2Bid;
self.read_block_async(bid, frame) self.read_block_async(bid, frame)
} }
fn write_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn write_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter> {
let bid = idx as Ext2Bid; let bid = idx as Ext2Bid;
self.write_block_async(bid, frame) self.write_block_async(bid, frame)
} }

View File

@ -13,14 +13,16 @@ pub(super) use aster_block::{
}; };
pub(super) use aster_rights::Full; pub(super) use aster_rights::Full;
pub(super) use ostd::{ pub(super) use ostd::{
mm::{Frame, FrameAllocOptions, Segment, UFrame, USegment, VmIo}, mm::{Frame, FrameAllocOptions, Segment, USegment, VmIo},
sync::{RwMutex, RwMutexReadGuard, RwMutexWriteGuard}, sync::{RwMutex, RwMutexReadGuard, RwMutexWriteGuard},
}; };
pub(super) use static_assertions::const_assert; pub(super) use static_assertions::const_assert;
pub(super) use super::utils::{Dirty, IsPowerOf}; pub(super) use super::utils::{Dirty, IsPowerOf};
pub(super) use crate::{ pub(super) use crate::{
fs::utils::{CStr256, DirentVisitor, InodeType, PageCache, PageCacheBackend, Str16, Str64}, fs::utils::{
CStr256, CachePage, DirentVisitor, InodeType, PageCache, PageCacheBackend, Str16, Str64,
},
prelude::*, prelude::*,
time::UnixTime, time::UnixTime,
vm::vmo::Vmo, vm::vmo::Vmo,

View File

@ -11,7 +11,7 @@ use aster_rights::Full;
use aster_util::slot_vec::SlotVec; use aster_util::slot_vec::SlotVec;
use hashbrown::HashMap; use hashbrown::HashMap;
use ostd::{ use ostd::{
mm::{UFrame, UntypedMem, VmIo}, mm::{UntypedMem, VmIo},
sync::{PreemptDisabled, RwLockWriteGuard}, sync::{PreemptDisabled, RwLockWriteGuard},
}; };
@ -23,8 +23,9 @@ use crate::{
file_handle::FileLike, file_handle::FileLike,
named_pipe::NamedPipe, named_pipe::NamedPipe,
utils::{ utils::{
CStr256, DirentVisitor, Extension, FallocMode, FileSystem, FsFlags, Inode, InodeMode, CStr256, CachePage, DirentVisitor, Extension, FallocMode, FileSystem, FsFlags, Inode,
InodeType, IoctlCmd, Metadata, MknodType, PageCache, PageCacheBackend, SuperBlock, InodeMode, InodeType, IoctlCmd, Metadata, MknodType, PageCache, PageCacheBackend,
SuperBlock,
}, },
}, },
prelude::*, prelude::*,
@ -484,7 +485,7 @@ impl RamInode {
} }
impl PageCacheBackend for RamInode { impl PageCacheBackend for RamInode {
fn read_page_async(&self, _idx: usize, frame: &UFrame) -> Result<BioWaiter> { fn read_page_async(&self, _idx: usize, frame: &CachePage) -> Result<BioWaiter> {
// Initially, any block/page in a RamFs inode contains all zeros // Initially, any block/page in a RamFs inode contains all zeros
frame frame
.writer() .writer()
@ -494,7 +495,7 @@ impl PageCacheBackend for RamInode {
Ok(BioWaiter::new()) Ok(BioWaiter::new())
} }
fn write_page_async(&self, _idx: usize, _frame: &UFrame) -> Result<BioWaiter> { fn write_page_async(&self, _idx: usize, _frame: &CachePage) -> Result<BioWaiter> {
// do nothing // do nothing
Ok(BioWaiter::new()) Ok(BioWaiter::new())
} }

View File

@ -13,7 +13,7 @@ pub use flock::{FlockItem, FlockList, FlockType};
pub use fs::{FileSystem, FsFlags, SuperBlock}; pub use fs::{FileSystem, FsFlags, SuperBlock};
pub use inode::{Extension, Inode, InodeMode, InodeType, Metadata, MknodType, Permission}; pub use inode::{Extension, Inode, InodeMode, InodeType, Metadata, MknodType, Permission};
pub use ioctl::IoctlCmd; pub use ioctl::IoctlCmd;
pub use page_cache::{PageCache, PageCacheBackend}; pub use page_cache::{CachePage, PageCache, PageCacheBackend};
pub use random_test::{generate_random_operation, new_fs_in_memory}; pub use random_test::{generate_random_operation, new_fs_in_memory};
pub use range_lock::{ pub use range_lock::{
FileRange, RangeLockItem, RangeLockItemBuilder, RangeLockList, RangeLockType, OFFSET_MAX, FileRange, RangeLockItem, RangeLockItemBuilder, RangeLockList, RangeLockType, OFFSET_MAX,

View File

@ -312,7 +312,7 @@ impl ReadaheadState {
}; };
for async_idx in window.readahead_range() { for async_idx in window.readahead_range() {
let mut async_page = CachePage::alloc()?; let mut async_page = CachePage::alloc()?;
let pg_waiter = backend.read_page_async(async_idx, (&async_page).into())?; let pg_waiter = backend.read_page_async(async_idx, &async_page)?;
if pg_waiter.nreqs() > 0 { if pg_waiter.nreqs() > 0 {
self.waiter.concat(pg_waiter); self.waiter.concat(pg_waiter);
} else { } else {
@ -368,7 +368,7 @@ impl PageCacheManager {
for idx in page_idx_range.start..page_idx_range.end { for idx in page_idx_range.start..page_idx_range.end {
if let Some(page) = pages.peek(&idx) { if let Some(page) = pages.peek(&idx) {
if page.load_state() == PageState::Dirty && idx < backend_npages { if page.load_state() == PageState::Dirty && idx < backend_npages {
let waiter = backend.write_page_async(idx, page.into())?; let waiter = backend.write_page_async(idx, page)?;
bio_waiter.concat(waiter); bio_waiter.concat(waiter);
} }
} }
@ -417,7 +417,7 @@ impl PageCacheManager {
// Conducts the sync read operation. // Conducts the sync read operation.
let page = if idx < backend.npages() { let page = if idx < backend.npages() {
let mut page = CachePage::alloc()?; let mut page = CachePage::alloc()?;
backend.read_page(idx, (&page).into())?; backend.read_page(idx, &page)?;
page.store_state(PageState::UpToDate); page.store_state(PageState::UpToDate);
page page
} else { } else {
@ -468,7 +468,7 @@ impl Pager for PageCacheManager {
return Ok(()); return Ok(());
}; };
if idx < backend.npages() { if idx < backend.npages() {
backend.write_page(idx, (&page).into())?; backend.write_page(idx, &page)?;
} }
} }
} }
@ -573,16 +573,16 @@ impl AtomicPageState {
/// This trait represents the backend for the page cache. /// This trait represents the backend for the page cache.
pub trait PageCacheBackend: Sync + Send { pub trait PageCacheBackend: Sync + Send {
/// Reads a page from the backend asynchronously. /// Reads a page from the backend asynchronously.
fn read_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter>; fn read_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter>;
/// Writes a page to the backend asynchronously. /// Writes a page to the backend asynchronously.
fn write_page_async(&self, idx: usize, frame: &UFrame) -> Result<BioWaiter>; fn write_page_async(&self, idx: usize, frame: &CachePage) -> Result<BioWaiter>;
/// Returns the number of pages in the backend. /// Returns the number of pages in the backend.
fn npages(&self) -> usize; fn npages(&self) -> usize;
} }
impl dyn PageCacheBackend { impl dyn PageCacheBackend {
/// Reads a page from the backend synchronously. /// Reads a page from the backend synchronously.
fn read_page(&self, idx: usize, frame: &UFrame) -> Result<()> { fn read_page(&self, idx: usize, frame: &CachePage) -> Result<()> {
let waiter = self.read_page_async(idx, frame)?; let waiter = self.read_page_async(idx, frame)?;
match waiter.wait() { match waiter.wait() {
Some(BioStatus::Complete) => Ok(()), Some(BioStatus::Complete) => Ok(()),
@ -590,7 +590,7 @@ impl dyn PageCacheBackend {
} }
} }
/// Writes a page to the backend synchronously. /// Writes a page to the backend synchronously.
fn write_page(&self, idx: usize, frame: &UFrame) -> Result<()> { fn write_page(&self, idx: usize, frame: &CachePage) -> Result<()> {
let waiter = self.write_page_async(idx, frame)?; let waiter = self.write_page_async(idx, frame)?;
match waiter.wait() { match waiter.wait() {
Some(BioStatus::Complete) => Ok(()), Some(BioStatus::Complete) => Ok(()),

View File

@ -307,13 +307,6 @@ impl<M: AnyUFrameMeta> From<Frame<M>> for UFrame {
} }
} }
impl<M: AnyUFrameMeta> From<&Frame<M>> for &UFrame {
fn from(frame: &Frame<M>) -> Self {
// SAFETY: The metadata is coerceable and the struct is transmutable.
unsafe { core::mem::transmute(frame) }
}
}
impl From<UFrame> for Frame<dyn AnyFrameMeta> { impl From<UFrame> for Frame<dyn AnyFrameMeta> {
fn from(frame: UFrame) -> Self { fn from(frame: UFrame) -> Self {
// SAFETY: The metadata is coerceable and the struct is transmutable. // SAFETY: The metadata is coerceable and the struct is transmutable.

View File

@ -231,13 +231,6 @@ impl<M: AnyUFrameMeta> From<Segment<M>> for USegment {
} }
} }
impl<M: AnyUFrameMeta> From<&Segment<M>> for &USegment {
fn from(seg: &Segment<M>) -> Self {
// SAFETY: The metadata is coerceable and the struct is transmutable.
unsafe { core::mem::transmute(seg) }
}
}
impl TryFrom<Segment<dyn AnyFrameMeta>> for USegment { impl TryFrom<Segment<dyn AnyFrameMeta>> for USegment {
type Error = Segment<dyn AnyFrameMeta>; type Error = Segment<dyn AnyFrameMeta>;