From c86a489b05019bdb6e61d27c3f113242f0673df7 Mon Sep 17 00:00:00 2001 From: Chaoqun Zheng Date: Fri, 9 Jan 2026 12:48:19 +0800 Subject: [PATCH] Fix the issue of `InodeBlockManager::read_blocks` --- kernel/comps/block/src/bio.rs | 5 +++++ kernel/src/fs/ext2/inode.rs | 34 ++++++++++++++++------------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/kernel/comps/block/src/bio.rs b/kernel/comps/block/src/bio.rs index 66ba34cd3..2b165fab1 100644 --- a/kernel/comps/block/src/bio.rs +++ b/kernel/comps/block/src/bio.rs @@ -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 { + 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 diff --git a/kernel/src/fs/ext2/inode.rs b/kernel/src/fs/ext2/inode.rs index 77c6398db..9e536fae2 100644 --- a/kernel/src/fs/ext2/inode.rs +++ b/kernel/src/fs/ext2/inode.rs @@ -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; pub fn read_blocks(&self, bid: Ext2Bid, nblocks: usize, writer: &mut VmWriter) -> Result<()>; pub fn read_block_async(&self, bid: Ext2Bid, frame: &CachePage) -> Result; 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 { - debug_assert!(nblocks * BLOCK_SIZE <= writer.avail()); + fn read_blocks_async(&self, bid: Ext2Bid, nblocks: usize) -> Result { 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 {