Fix the updating strategy of `InodeDesc::occupied_sectors_count`.

This commit is contained in:
Chaoqun Zheng 2026-01-29 09:13:56 +08:00
parent f14cf37b12
commit a1eba4766f
1 changed files with 17 additions and 9 deletions

View File

@ -1889,12 +1889,14 @@ impl InodeImpl {
/// After the reduction, the block count will be decreased to `range.start`.
fn shrink_blocks(&mut self, range: Range<Ext2Bid>) {
let mut current_range = range.clone();
let mut total_freed_blocks = 0;
while !current_range.is_empty() {
let free_cnt = self.try_shrink_blocks(current_range.clone());
let (free_cnt, freed_blocks) = self.try_shrink_blocks(current_range.clone());
total_freed_blocks += freed_blocks;
current_range.end -= free_cnt;
}
self.desc.occupied_sectors_count -= blocks_to_sectors(range.len() as u32);
self.desc.occupied_sectors_count -= blocks_to_sectors(total_freed_blocks);
self.last_alloc_device_bid = if range.start == 0 {
None
} else {
@ -1910,9 +1912,9 @@ impl InodeImpl {
/// Attempts to shrink a range of blocks and returns the number of blocks
/// successfully freed.
///
/// Note that the returned number may be less than the requested range if needs
/// Note that the first returned number may be less than the requested range if needs
/// to free the indirect blocks that are no longer required.
fn try_shrink_blocks(&mut self, range: Range<Ext2Bid>) -> Ext2Bid {
fn try_shrink_blocks(&mut self, range: Range<Ext2Bid>) -> (Ext2Bid, u32) {
// Calculates the maximum range of blocks that can be freed in this round.
let range = {
let max_cnt = (range.len() as Ext2Bid)
@ -1923,12 +1925,14 @@ impl InodeImpl {
let fs = self.fs();
let device_range_reader =
DeviceRangeReader::new(&self.block_manager, range.clone()).unwrap();
let mut freed_blocks = 0u32;
for device_range in device_range_reader {
freed_blocks += device_range.len() as u32;
fs.free_blocks(device_range.clone()).unwrap();
}
self.free_indirect_blocks_required_by(range.start).unwrap();
range.len() as Ext2Bid
(range.len() as Ext2Bid, freed_blocks)
}
/// Deallocate inode blocks in a specified range.
@ -1936,12 +1940,14 @@ impl InodeImpl {
/// After the reduction, the block count will be decreased `range.len`.
fn dealloc_range_blocks(&mut self, range: Range<Ext2Bid>) {
let mut current_range = range.clone();
let mut total_freed_blocks = 0;
while !current_range.is_empty() {
let free_cnt = self.try_dealloc_range_blocks(current_range.clone());
let (free_cnt, freed_blocks) = self.try_dealloc_range_blocks(current_range.clone());
total_freed_blocks += freed_blocks;
current_range.end -= free_cnt;
}
self.desc.occupied_sectors_count -= blocks_to_sectors(range.len() as u32);
self.desc.occupied_sectors_count -= blocks_to_sectors(total_freed_blocks);
self.last_alloc_device_bid = if range.start == 0 {
None
} else {
@ -1959,7 +1965,7 @@ impl InodeImpl {
///
/// Note that the returned number may be less than the requested range if needs
/// to free the indirect blocks that are no longer required.
fn try_dealloc_range_blocks(&mut self, range: Range<Ext2Bid>) -> Ext2Bid {
fn try_dealloc_range_blocks(&mut self, range: Range<Ext2Bid>) -> (Ext2Bid, u32) {
// Calculates the maximum range of blocks that can be freed in this round.
let range = {
let max_cnt = (range.len() as Ext2Bid)
@ -1967,6 +1973,7 @@ impl InodeImpl {
(range.end - max_cnt)..range.end
};
let mut freed_blocks = 0u32;
for bid in range.clone() {
let bid_path = BidPath::from(bid);
let device_bid = self.get_device_bid(bid).unwrap();
@ -1974,6 +1981,7 @@ impl InodeImpl {
continue;
}
freed_blocks += 1;
self.fs().free_blocks(device_bid..device_bid + 1).unwrap();
match bid_path {
BidPath::Direct(idx) => {
@ -2026,7 +2034,7 @@ impl InodeImpl {
}
self.free_indirect_blocks_required_by(range.start).unwrap();
range.len() as Ext2Bid
(range.len() as Ext2Bid, freed_blocks)
}
/// Frees the indirect blocks required by the specified block ID.