Index: fs.c =================================================================== --- ntoskrnl/cc/fs.c (revision 72853) +++ ntoskrnl/cc/fs.c (working copy) @@ -142,7 +142,77 @@ return FALSE; } +VOID +CcRosTruncateFile ( + IN PROS_SHARED_CACHE_MAP SharedCacheMap, + IN PLARGE_INTEGER TruncateSize, + IN PLARGE_INTEGER NewFileSize OPTIONAL) +{ + KIRQL OldIrql; + PLIST_ENTRY ListEntry; + PROS_VACB Vacb; + LIST_ENTRY FreeListHead; + NTSTATUS Status; + ASSERT(SharedCacheMap != NULL); + ASSERT(TruncateSize != NULL); + ASSERT(TruncateSize->QuadPart < SharedCacheMap->SectionSize.QuadPart); + + InitializeListHead(&FreeListHead); + KeAcquireGuardedMutex(&ViewLock); + KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql); + + ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink; + while (ListEntry != &SharedCacheMap->CacheMapVacbListHead) + { + Vacb = CONTAINING_RECORD(ListEntry, ROS_VACB, CacheMapVacbListEntry); + ListEntry = ListEntry->Flink; + + if (Vacb->FileOffset.QuadPart >= TruncateSize->QuadPart) + { + if ((Vacb->ReferenceCount == 0) || ((Vacb->ReferenceCount == 1) && Vacb->Dirty)) + { + RemoveEntryList(&Vacb->CacheMapVacbListEntry); + RemoveEntryList(&Vacb->VacbLruListEntry); + if (Vacb->Dirty) + { + RemoveEntryList(&Vacb->DirtyVacbListEntry); + DirtyPageCount -= VACB_MAPPING_GRANULARITY / PAGE_SIZE; + } + InsertHeadList(&FreeListHead, &Vacb->CacheMapVacbListEntry); + } + else + { + DPRINT1("Someone has referenced a VACB behind the new size.\n"); + KeBugCheck(CACHE_MANAGER); + } + } + } + + if (NewFileSize != NULL) + { + SharedCacheMap->SectionSize = *TruncateSize; + SharedCacheMap->FileSize = *NewFileSize; + } + + KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql); + KeReleaseGuardedMutex(&ViewLock); + + ListEntry = FreeListHead.Flink; + while (ListEntry != &FreeListHead) + { + Vacb = CONTAINING_RECORD(ListEntry, ROS_VACB, CacheMapVacbListEntry); + ListEntry = ListEntry->Flink; + + Status = CcRosInternalFreeVacb(Vacb); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CcRosInternalFreeVacb failed, status = %lx\n", Status); + KeBugCheck(CACHE_MANAGER); + } + } +} + /* * @implemented */ @@ -153,10 +223,7 @@ { KIRQL oldirql; PROS_SHARED_CACHE_MAP SharedCacheMap; - PLIST_ENTRY current_entry; - PROS_VACB current; - LIST_ENTRY FreeListHead; - NTSTATUS Status; + PROS_VACB LastVacb; CCTRACE(CC_API_DEBUG, "FileObject=%p FileSizes=%p\n", FileObject, FileSizes); @@ -179,58 +246,29 @@ if (FileSizes->AllocationSize.QuadPart < SharedCacheMap->SectionSize.QuadPart) { - InitializeListHead(&FreeListHead); - KeAcquireGuardedMutex(&ViewLock); - KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql); + CcRosTruncateFile(SharedCacheMap, + &FileSizes->AllocationSize, + &FileSizes->FileSize); - current_entry = SharedCacheMap->CacheMapVacbListHead.Flink; - while (current_entry != &SharedCacheMap->CacheMapVacbListHead) - { - current = CONTAINING_RECORD(current_entry, - ROS_VACB, - CacheMapVacbListEntry); - current_entry = current_entry->Flink; - if (current->FileOffset.QuadPart >= FileSizes->AllocationSize.QuadPart) - { - if ((current->ReferenceCount == 0) || ((current->ReferenceCount == 1) && current->Dirty)) - { - RemoveEntryList(¤t->CacheMapVacbListEntry); - RemoveEntryList(¤t->VacbLruListEntry); - if (current->Dirty) - { - RemoveEntryList(¤t->DirtyVacbListEntry); - DirtyPageCount -= VACB_MAPPING_GRANULARITY / PAGE_SIZE; - } - InsertHeadList(&FreeListHead, ¤t->CacheMapVacbListEntry); - } - else - { - DPRINT1("Someone has referenced a VACB behind the new size.\n"); - KeBugCheck(CACHE_MANAGER); - } - } - } - SharedCacheMap->SectionSize = FileSizes->AllocationSize; SharedCacheMap->FileSize = FileSizes->FileSize; - KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql); - KeReleaseGuardedMutex(&ViewLock); - - current_entry = FreeListHead.Flink; - while(current_entry != &FreeListHead) + } + else + { + if (SharedCacheMap->SectionSize.QuadPart < FileSizes->AllocationSize.QuadPart && + SharedCacheMap->SectionSize.QuadPart % VACB_MAPPING_GRANULARITY) { - current = CONTAINING_RECORD(current_entry, ROS_VACB, CacheMapVacbListEntry); - current_entry = current_entry->Flink; - Status = CcRosInternalFreeVacb(current); - if (!NT_SUCCESS(Status)) + LastVacb = CcRosLookupVacb(SharedCacheMap, + SharedCacheMap->SectionSize.QuadPart); + if (LastVacb != NULL) { - DPRINT1("CcRosInternalFreeVacb failed, status = %x\n", Status); - KeBugCheck(CACHE_MANAGER); + /* too lazy to handle this right now */ + //ASSERT(!LastVacb->Dirty); + + /* mark it as invalid */ + CcRosReleaseVacb(SharedCacheMap, LastVacb, LastVacb->Dirty ? LastVacb->Valid : FALSE, FALSE, FALSE); } } - } - else - { KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql); SharedCacheMap->SectionSize = FileSizes->AllocationSize; SharedCacheMap->FileSize = FileSizes->FileSize; @@ -264,11 +302,19 @@ IN PLARGE_INTEGER TruncateSize OPTIONAL, IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL) { + PROS_SHARED_CACHE_MAP SharedCacheMap; NTSTATUS Status; CCTRACE(CC_API_DEBUG, "FileObject=%p TruncateSize=%p UninitializeCompleteEvent=%p\n", FileObject, TruncateSize, UninitializeCompleteEvent); + SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; + if (SharedCacheMap && + TruncateSize && + TruncateSize->QuadPart < SharedCacheMap->SectionSize.QuadPart) + { + CcRosTruncateFile(SharedCacheMap, TruncateSize, NULL); + } Status = CcRosReleaseFileCache(FileObject); if (UninitializeCompleteEvent) KeSetEvent(&UninitializeCompleteEvent->Event, IO_NO_INCREMENT, FALSE);