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 8c8635009..6508d4a3d 100644 --- a/kernel/src/fs/ext2/inode.rs +++ b/kernel/src/fs/ext2/inode.rs @@ -1821,12 +1821,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( @@ -1854,13 +1848,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)? { @@ -1868,8 +1856,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); } @@ -1878,10 +1864,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 {