diff --git a/kernel/src/fs/ext2/inode.rs b/kernel/src/fs/ext2/inode.rs index 1187903f8..940afc65d 100644 --- a/kernel/src/fs/ext2/inode.rs +++ b/kernel/src/fs/ext2/inode.rs @@ -1690,6 +1690,7 @@ impl InodeImpl { .unwrap() .read() .unwrap() + .unwrap() .start, ) }; @@ -2007,7 +2008,7 @@ impl<'a> DeviceRangeReader<'a> { /// /// Note that the returned device range size may be smaller than the requested range /// due to possible inconsecutive block allocation. - pub fn read(&mut self) -> Result> { + pub fn read(&mut self) -> Result>> { let bid_path = BidPath::from(self.range.start); let max_cnt = self .range @@ -2019,9 +2020,28 @@ impl<'a> DeviceRangeReader<'a> { let mut device_range: Option> = None; for i in start_idx..start_idx + max_cnt { let device_bid = match &self.indirect_block { - None => self.block_ptrs.direct(i), + None => match bid_path { + BidPath::Direct(_) => self.block_ptrs.direct(i), + _ => 0, + }, Some(indirect_block) => indirect_block.read_bid(i)?, }; + + // Skip sparse blocks which are not allocated + if device_bid == 0 { + match device_range { + Some(ref mut range) => { + // End the current range when hitting a sparse block + break; + } + None => { + // Skip leading sparse blocks, advance the logical range + self.range.start += 1; + continue; + } + } + } + match device_range { Some(ref mut range) => { if device_bid == range.end { @@ -2035,7 +2055,16 @@ impl<'a> DeviceRangeReader<'a> { } } } - let device_range = device_range.unwrap(); + + let device_range = match device_range { + Some(range) => range, + None => { + if !self.range.is_empty() { + self.update_indirect_block()?; + } + return Ok(None); + } + }; // Updates the range self.range.start += device_range.len() as Ext2Bid; @@ -2044,7 +2073,7 @@ impl<'a> DeviceRangeReader<'a> { self.update_indirect_block()?; } - Ok(device_range) + Ok(Some(device_range)) } fn update_indirect_block(&mut self) -> Result<()> { @@ -2055,30 +2084,49 @@ impl<'a> DeviceRangeReader<'a> { } BidPath::Indirect(_) => { let indirect_bid = self.block_ptrs.indirect(); - let indirect_block = self.indirect_blocks.find(indirect_bid)?; - self.indirect_block = Some(indirect_block.clone()); + if indirect_bid == 0 { + self.indirect_block = None; + } else { + let indirect_block = self.indirect_blocks.find(indirect_bid)?; + self.indirect_block = Some(indirect_block.clone()); + } } BidPath::DbIndirect(lvl1_idx, _) => { - let lvl1_indirect_bid = { - let db_indirect_block = - self.indirect_blocks.find(self.block_ptrs.db_indirect())?; - db_indirect_block.read_bid(lvl1_idx as usize)? - }; - let lvl1_indirect_block = self.indirect_blocks.find(lvl1_indirect_bid)?; - self.indirect_block = Some(lvl1_indirect_block.clone()) + let db_indirect_bid = self.block_ptrs.db_indirect(); + if db_indirect_bid == 0 { + self.indirect_block = None; + } else { + let db_indirect_block = self.indirect_blocks.find(db_indirect_bid)?; + let lvl1_indirect_bid = db_indirect_block.read_bid(lvl1_idx as usize)?; + if lvl1_indirect_bid == 0 { + self.indirect_block = None; + } else { + let lvl1_indirect_block = self.indirect_blocks.find(lvl1_indirect_bid)?; + self.indirect_block = Some(lvl1_indirect_block.clone()); + } + } } BidPath::TbIndirect(lvl1_idx, lvl2_idx, _) => { - let lvl2_indirect_bid = { - let lvl1_indirect_bid = { - let tb_indirect_block = - self.indirect_blocks.find(self.block_ptrs.tb_indirect())?; - tb_indirect_block.read_bid(lvl1_idx as usize)? - }; - let lvl1_indirect_block = self.indirect_blocks.find(lvl1_indirect_bid)?; - lvl1_indirect_block.read_bid(lvl2_idx as usize)? - }; - let lvl2_indirect_block = self.indirect_blocks.find(lvl2_indirect_bid)?; - self.indirect_block = Some(lvl2_indirect_block.clone()) + let tb_indirect_bid = self.block_ptrs.tb_indirect(); + if tb_indirect_bid == 0 { + self.indirect_block = None; + } else { + let tb_indirect_block = self.indirect_blocks.find(tb_indirect_bid)?; + let lvl1_indirect_bid = tb_indirect_block.read_bid(lvl1_idx as usize)?; + if lvl1_indirect_bid == 0 { + self.indirect_block = None; + } else { + let lvl1_indirect_block = self.indirect_blocks.find(lvl1_indirect_bid)?; + let lvl2_indirect_bid = lvl1_indirect_block.read_bid(lvl2_idx as usize)?; + if lvl2_indirect_bid == 0 { + self.indirect_block = None; + } else { + let lvl2_indirect_block = + self.indirect_blocks.find(lvl2_indirect_bid)?; + self.indirect_block = Some(lvl2_indirect_block.clone()); + } + } + } } } @@ -2095,7 +2143,10 @@ impl Iterator for DeviceRangeReader<'_> { } let range = self.read().unwrap(); - Some(range) + match range { + Some(range) => Some(range), + None => self.next(), + } } }