Fix the issue of `InodeBlockManager::read_blocks`

This commit is contained in:
Chaoqun Zheng 2026-01-09 12:48:19 +08:00
parent 01cf00a4c6
commit c86a489b05
2 changed files with 21 additions and 18 deletions

View File

@ -204,6 +204,11 @@ impl BioWaiter {
self.bios.append(&mut other.bios);
}
/// Returns an iterator for the `Bio` requests associated with `self`.
pub fn reqs(&self) -> impl Iterator<Item = Bio> {
self.bios.iter().map(|bio_inner| Bio(bio_inner.clone()))
}
/// Waits for the completion of all `Bio` requests.
///
/// This method iterates through each `Bio` in the list, waiting for their

View File

@ -1817,12 +1817,6 @@ impl InodeImpl {
#[inherit_methods(from = "self.block_manager")]
impl InodeImpl {
pub fn read_blocks_async(
&self,
bid: Ext2Bid,
nblocks: usize,
writer: &mut VmWriter,
) -> Result<BioWaiter>;
pub fn read_blocks(&self, bid: Ext2Bid, nblocks: usize, writer: &mut VmWriter) -> Result<()>;
pub fn read_block_async(&self, bid: Ext2Bid, frame: &CachePage) -> Result<BioWaiter>;
pub fn write_blocks_async(
@ -1850,13 +1844,7 @@ struct InodeBlockManager {
impl InodeBlockManager {
/// Reads one or multiple blocks to the segment start from `bid` asynchronously.
pub fn read_blocks_async(
&self,
bid: Ext2Bid,
nblocks: usize,
writer: &mut VmWriter,
) -> Result<BioWaiter> {
debug_assert!(nblocks * BLOCK_SIZE <= writer.avail());
fn read_blocks_async(&self, bid: Ext2Bid, nblocks: usize) -> Result<BioWaiter> {
let mut bio_waiter = BioWaiter::new();
for dev_range in DeviceRangeReader::new(self, bid..bid + nblocks as Ext2Bid)? {
@ -1864,8 +1852,6 @@ impl InodeBlockManager {
let range_nblocks = dev_range.len();
let bio_segment = BioSegment::alloc(range_nblocks, BioDirection::FromDevice);
bio_segment.reader().unwrap().read_fallible(writer)?;
let waiter = self.fs().read_blocks_async(start_bid, bio_segment)?;
bio_waiter.concat(waiter);
}
@ -1874,10 +1860,22 @@ impl InodeBlockManager {
}
pub fn read_blocks(&self, bid: Ext2Bid, nblocks: usize, writer: &mut VmWriter) -> Result<()> {
match self.read_blocks_async(bid, nblocks, writer)?.wait() {
Some(BioStatus::Complete) => Ok(()),
_ => return_errno!(Errno::EIO),
debug_assert!(nblocks * BLOCK_SIZE <= writer.avail());
let bio_waiter = self.read_blocks_async(bid, nblocks)?;
if Some(BioStatus::Complete) != bio_waiter.wait() {
return_errno!(Errno::EIO);
}
for bio in bio_waiter.reqs() {
for segment in bio.segments() {
segment
.reader()?
.read_fallible(writer)
.map_err(|(e, _)| Error::from(e))?;
}
}
Ok(())
}
pub fn read_block_async(&self, bid: Ext2Bid, frame: &CachePage) -> Result<BioWaiter> {