https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0917c64812c6ed182c8f7…
commit 0917c64812c6ed182c8f771309dfc628127eee2d
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sun Dec 23 11:08:01 2018 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sun Dec 23 11:19:14 2018 +0100
[NTOSKRNL] When growing a file, invalid the last VACB so that it can be refreshed
This will avoid corruption when a file size is little grown and read afterwards.
Up to now, FSD where reading 0es instead of expected data, causing corruption.
This fixes MS FastFAT not being able to mount a FAT volume in ReactOS, corrupting
the FAT.
This also fixes the CcSetFileSizes kmtest tests.
This is based on a patch by Thomas Faber.
CORE-11819
---
ntoskrnl/cc/fs.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/ntoskrnl/cc/fs.c b/ntoskrnl/cc/fs.c
index e31a17b87b..5798f56a91 100644
--- a/ntoskrnl/cc/fs.c
+++ b/ntoskrnl/cc/fs.c
@@ -301,6 +301,43 @@ CcSetFileSizes (
0,
FALSE);
}
+ else
+ {
+ PROS_VACB LastVacb;
+
+ /*
+ * If file (allocation) size has increased, then we need to check whether
+ * it just grows in a single VACB (the last one).
+ * If so, we must mark the VACB as invalid to trigger a read to the
+ * FSD at the next VACB usage, and thus avoid returning garbage
+ */
+
+ /* Check for allocation size and the last VACB */
+ if (SharedCacheMap->SectionSize.QuadPart <
FileSizes->AllocationSize.QuadPart &&
+ SharedCacheMap->SectionSize.QuadPart % VACB_MAPPING_GRANULARITY)
+ {
+ LastVacb = CcRosLookupVacb(SharedCacheMap,
+ SharedCacheMap->SectionSize.QuadPart);
+ if (LastVacb != NULL)
+ {
+ /* Mark it as invalid */
+ CcRosReleaseVacb(SharedCacheMap, LastVacb, LastVacb->Dirty ?
LastVacb->Valid : FALSE, FALSE, FALSE);
+ }
+ }
+
+ /* Check for file size and the last VACB */
+ if (SharedCacheMap->FileSize.QuadPart < FileSizes->FileSize.QuadPart
&&
+ SharedCacheMap->FileSize.QuadPart % VACB_MAPPING_GRANULARITY)
+ {
+ LastVacb = CcRosLookupVacb(SharedCacheMap,
+ SharedCacheMap->FileSize.QuadPart);
+ if (LastVacb != NULL)
+ {
+ /* Mark it as invalid */
+ CcRosReleaseVacb(SharedCacheMap, LastVacb, LastVacb->Dirty ?
LastVacb->Valid : FALSE, FALSE, FALSE);
+ }
+ }
+ }
KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
SharedCacheMap->SectionSize = FileSizes->AllocationSize;