/* INCLUDES ******************************************************************/ #include #include #include #include #include #include #include #define NDEBUG #include /* GLOBALS *******************************************************************/ #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) #define ROUND_DOWN(N, S) (((N) % (S)) ? ROUND_UP(N, S) - S : N) extern FAST_MUTEX ViewLock; extern ULONG DirtyPageCount; NTSTATUS CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg); /* FUNCTIONS *****************************************************************/ /********************************************************************** * NAME INTERNAL * CcMdlReadCompleteDev@8 * * DESCRIPTION * * ARGUMENTS * MdlChain * DeviceObject * * RETURN VALUE * None. * * NOTE * Used by CcMdlReadComplete@8 and FsRtl * */ VOID STDCALL CcMdlReadCompleteDev (IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject) { UNIMPLEMENTED; } /********************************************************************** * NAME EXPORTED * CcMdlReadComplete@8 * * DESCRIPTION * * ARGUMENTS * * RETURN VALUE * None. * * NOTE * From Bo Branten's ntifs.h v13. * * @unimplemented */ VOID STDCALL CcMdlReadComplete (IN PFILE_OBJECT FileObject, IN PMDL MdlChain) { PDEVICE_OBJECT DeviceObject = NULL; DeviceObject = IoGetRelatedDeviceObject (FileObject); /* FIXME: try fast I/O first */ CcMdlReadCompleteDev (MdlChain, DeviceObject); } /* * @implemented */ VOID STDCALL CcSetFileSizes (IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes) { KIRQL oldirql; PBCB Bcb; PLIST_ENTRY current_entry; PCACHE_SEGMENT current; LIST_ENTRY FreeListHead; NTSTATUS Status; DPRINT("CcSetFileSizes(FileObject %x, FileSizes %x)\n", FileObject, FileSizes); DPRINT("AllocationSize %d, FileSize %d, ValidDataLength %d\n", (ULONG)FileSizes->AllocationSize.QuadPart, (ULONG)FileSizes->FileSize.QuadPart, (ULONG)FileSizes->ValidDataLength.QuadPart); Bcb = FileObject->SectionObjectPointer->SharedCacheMap; assert(Bcb); if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart) { InitializeListHead(&FreeListHead); ExAcquireFastMutex(&ViewLock); KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); current_entry = Bcb->BcbSegmentListHead.Flink; while (current_entry != &Bcb->BcbSegmentListHead) { current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); current_entry = current_entry->Flink; if (current->FileOffset > FileSizes->AllocationSize.QuadPart) { if (current->ReferenceCount == 0 || (current->ReferenceCount == 1 && current->Dirty)) { RemoveEntryList(¤t->BcbSegmentListEntry); RemoveEntryList(¤t->CacheSegmentListEntry); RemoveEntryList(¤t->CacheSegmentLRUListEntry); if (current->Dirty) { RemoveEntryList(¤t->DirtySegmentListEntry); DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE; } InsertHeadList(&FreeListHead, ¤t->BcbSegmentListEntry); } else { DPRINT1("Anyone has referenced a cache segment behind the new size.\n"); KEBUGCHECK(0); } } } Bcb->AllocationSize = FileSizes->AllocationSize; Bcb->FileSize = FileSizes->FileSize; KeReleaseSpinLock(&Bcb->BcbLock, oldirql); ExReleaseFastMutex(&ViewLock); current_entry = FreeListHead.Flink; while(current_entry != &FreeListHead) { current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); current_entry = current_entry->Flink; Status = CcRosInternalFreeCacheSegment(current); if (!NT_SUCCESS(Status)) { DPRINT1("CcRosInternalFreeCacheSegment failed, status = %x\n"); KEBUGCHECK(0); } } } else { KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); Bcb->AllocationSize = FileSizes->AllocationSize; Bcb->FileSize = FileSizes->FileSize; KeReleaseSpinLock(&Bcb->BcbLock, oldirql); } }