mft.c: Fix broken free MFT records accounting during bitmap extension.

When the bitmap needs extending, 'vol->free_mft_records' is incremented
by 8*8=64 records. This is due to the bitmap's initialized area being
extended 8 bytes at a time.
However the way 'vol->free_mft_records' is being initialized is that all
the bits that are currently allocated to the MFT bitmap are already
taken into account at initialization time. This leads to a value for
'vol->free_mft_records' that is larger than the actual available number
of MFT records.

For example if there are 20 used MFT records and the bitmap has a 4096
byte allocation where 16 bytes are initialized, the number of free MFT
records are ((8 * 16) - 20) + (8 * (4096 - 16)) = 32748 records
available.
If we now expand the bitmap by 8 initialized bytes, we'd be adding 64
MFT entries according to the logic in the function
'ntfs_mft_bitmap_extend_initialized'.
However we are expanding it within the bounds of the existing allocation
where there is (4096 - 16) bytes free, so they shouldn't be added at all
at this stage.

The result is that our internal accounting is that we have 32748 + 64 =
32812 available MFT records, but in reality we will have 32748 records
available all the time until we expand the allocation beyond 4096 bytes.

Fixed by incrementing 'vol->free_mft_records' when the allocation is
expanded, not when the initialized size is.
edge
Erik Larsson 2023-05-09 11:25:10 +03:00
parent 241ddb3860
commit 1565b01e21
1 changed files with 4 additions and 1 deletions

View File

@ -978,7 +978,6 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
if (ll == 8) {
ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
vol->free_mft_records += (8 * 8);
ret = 0;
goto out;
}
@ -1776,6 +1775,7 @@ retry:
(long long)mftbmp_na->initialized_size);
if (mftbmp_na->initialized_size + 8 > mftbmp_na->allocated_size) {
const s64 old_allocated_size = mftbmp_na->allocated_size;
int ret = ntfs_mft_bitmap_extend_allocation(vol);
if (ret == STATUS_ERROR)
@ -1792,6 +1792,9 @@ retry:
(long long)mftbmp_na->allocated_size,
(long long)mftbmp_na->data_size,
(long long)mftbmp_na->initialized_size);
vol->free_mft_records +=
(mftbmp_na->allocated_size - old_allocated_size) << 3;
}
/*
* We now have sufficient allocated space, extend the initialized_size