/* * PROJECT: Alcyone System Kernel * LICENSE: BSD Clause 3 * PURPOSE: Cache Controller:: Lazy Writer * NT KERNEL: 5.11.9360 * COPYRIGHT: 2023-2029 Dibymartanda Samanta <> */ #include #define NTDEBUG #include #include "ccinternal.hpp" extern "C" /*Internal Function*/ BOOLEAN NTAPI CcPinFileData( _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length, _In_ BOOLEAN IsNoWrite, _In_ BOOLEAN Flags, _In_ ULONG PinFlags, _Out_ PCC_BCB* Bcb, _Out_ PVOID* Buffer, _Out_ LARGE_INTEGER* BeyondLastByte) { // Unimplemented } BOOLEAN NTAPI CcMapDataCommon( _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length, _In_ ULONG Flags, _Out_ PVOID *Bcb, _Out_ PVOID *Buffer ) { if (Flags & FILE_PIN_SEQUENTIAL_READ) InterlockedIncrement(&CcSequentialReadCount); else InterlockedIncrement(&CcRandomReadCount); KeGetCurrentThread()->WaitIrql = PASSIVE_LEVEL; if (Flags & FILE_PIN_SEQUENTIAL_READ) { *Buffer = CcGetVirtualAddress(SharedMap, *FileOffset, (PVACB *)&Bcb, &ReceivedLength); return TRUE; } else { LARGE_INTEGER BeyondLastByte; if (CcPinFileData(FileObject, FileOffset, Length, TRUE, 0, Flags, Bcb, Buffer, &BeyondLastByte)) { return TRUE; } else { InterlockedIncrement(&CCFailedPinReadCount); return FALSE; } } } } VOID NTAPI CcUnpinFileDataEx( _In_ PCC_BCB Bcb, _In_ BOOLEAN& WriteStatus, _In_ ULONG& UnPinType) { PSHARED_CACHE_MAP SharedCacheMap = nullptr; KIRQL OldIrql = {0}; ULONG NumberOfPages = {0}; BOOLEAN ReadOnly = false; /* If it is not BCB Ptr,it must be VACB Pointer, free it*/ if (Bcb->NodeTypeCode != BCB_NODE_TYPE_CODE) { PVACB Vacb = reinterpret_cast(Bcb); CcFreeVirtualAddress(Vacb); return; } SharedCacheMap = Bcb->SharedCacheMap; /* Is it only Unpinning if so is their no write performed by Cache Controller */ if (!(SharedCacheMap->Flags & SHARED_CACHE_MAP_MODIFIED_NO_WRITE) || UnPinType == UnPin) ReadOnly = TRUE; OldIrql = KeAcquireSpinLockRaiseToDpc(&SharedCacheMap->BcbSpinLock); /* Just reduce pin count if BCB is not set to be cleaned else perform cleaning of BCB*/ if (UnPinType < CLEAN_BCB_PIN) { ASSERT(Bcb->PinCount > 0); Bcb->PinCount--; } else { if (UnPinType != CLEAN_BCB_PIN) KeBugCheckEx(UNEXPECTED_VALUE, UnPinType, (ULONG_PTR)Bcb, 0, 0); if (Bcb->IsBCBDirty) { NumberOfPages = (Bcb->Length / PAGE_SIZE); Bcb->IsBCBDirty = FALSE; Bcb->NewestDirtiedPage = 0; Bcb->NewestLsn.QuadPart = 0; CcDeductIsBCBDirtyPages(SharedCacheMap, NumberOfPages); /*Adjust page count */ if (CcPagesYetToWrite <= NumberOfPages) CcPagesYetToWrite = 0; else CcPagesYetToWrite -= NumberOfPages; if (!SharedCacheMap->IsBCBDirtyPages && SharedCacheMap->OpenCount) CcInsertIntoCleanSharedCacheMapList(SharedCacheMap); } } if (Bcb->PinCount) { /* If not read only BCB, release resources,their no point being pinned at that case */ if (!ReadOnly) ExReleaseResourceLite(&Bcb->BcbResource); KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); } /*if BCB is dirty, free the virtual adress*/ else if (Bcb->IsBCBDirty) { if (Bcb->BaseAddress) { CcFreeVirtualAddress(Bcb->Vacb); Bcb->BaseAddress = NULL; Bcb->Vacb = NULL; } if (!ReadOnly) ExReleaseResourceLite(&Bcb->BcbResource); KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); } else { KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->VacbSpinLock); RemoveEntryList(&Bcb->Link); if (SharedCacheMap->SectionSize.QuadPart > CACHE_OVERALL_SIZE && (SharedCacheMap->Flags & SHARED_CACHE_MAP_MODIFIED_NO_WRITE)) { CcAdjustVacbLevelLockCount(SharedCacheMap, &Bcb->FileOffset.QuadPart, -1); } KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->VacbSpinLock); if (Bcb->BaseAddress) CcFreeVirtualAddress(Bcb->Vacb); if (!ReadOnly) ExReleaseResourceLite(&Bcb->BcbResource); KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql); CcDeallocateBcb(Bcb); } } BOOLEAN VECTORCALL CcPinFileData( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN IsReadOnly, IN BOOLEAN IsWriteOnly, IN ULONG Flags, OUT PCC_BCB *Bcb, OUT PVOID *BaseAddress, OUT PLARGE_INTEGER BeyondLastByte) { // Unimplemented } BOOLEAN NTAPI CcMapData( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer) { //Unimplemented } BOOLEAN FASTCALL CcMapDataCommon( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer) { //Unimplemented } BOOLEAN NTAPI CcPinMappedData( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, IN OUT PCC_BCB Bcb) { //Unimplemented } BOOLEAN NTAPI CcPinRead( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer) { //Unimplemented } BOOLEAN NTAPI CcPreparePinWrite( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Zero, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer) { //Unimplemented } VOID NTAPI CcSetBcbOwnerPointer( IN PMBCB Bcb, IN PVOID OwnerPointer) { if (Bcb->NodeTypeCode == 762) { /* Iterate through all bitmap ranges */ for (auto it = ListEntryIterator::begin(&Bcb->BitmapRanges); it != ListEntryIterator::end(&Bcb->BitmapRanges); ++it) { auto* Bcb = CONTAINING_RECORD(it->Blink,MBCB,BitmapRanges); ExSetResourceOwnerPointer(&Bcb->DirtyPages,OwnerPointer); } } else { /* Single bitmap range */ ExSetResourceOwnerPointer(&Bcb->BitmapRange1.FirstDirtyPage,OwnerPointer); } } VOID NTAPI CcUnpinData( _In_ PVOID BcbPtr) { PCC_BCB Bcb = reinterpret_cast(BcbPtr); BOOLEAN WRITE_FLAG = NULL; if (reinterpret_cast((Bcb & 1)) { WRITE_FLAG = TRUE; Bcb = reinterpret_cast(reinterpret_cast(Bcb) & ~(1)); CcUnpinFileDataEx(Bcb, WRITE_FLAG, UNPIN_BCB); return; } if (Bcb->NodeTypeCode != 762) { WRITE_FLAG = FALSE; CcUnpinFileDataEx(Bcb, WRITE_FLAG, UNPIN_BCB); return; } for (auto it = ListEntryIterator::begin(&Bcb->BcbLinks); it != ListEntryIterator::end(&Bcb->BcbLinks); ++it) { auto* BCB_CURRENT = CONTAINING_RECORD(it->Blink, CC_BCB, BcbLinks); CcUnpinData(BCB_CURRENT); } ExFreePoolWithTag(Bcb,NULL); } VOID NTAPI CcUnpinDataForThread(IN PVOID BcbPtr, IN ERESOURCE_THREAD ResourceThreadId) { PCC_BCB Bcb = BcbPtr; BOOLEAN WRITE_FLAG = NULL; if (reinterpret_cast((Bcb & 1)) { WRITE_FLAG = TRUE; Bcb = reinterpret_cast(reinterpret_cast(Bcb) & ~(1)); CcUnpinFileDataEx(Bcb, WRITE_FLAG, ); return; } if (Bcb->NodeTypeCode != 762) { WRITE_FLAG = FALSE; ExReleaseResourceForThreadLite(&Bcb->Resource, ResourceThreadId); CcUnpinFileDataEx(Bcb, WRITE_FLAG, UNPIN_BCB); return; } for (auto it = ListEntryIterator::begin(&Bcb->BcbLinks); it != ListEntryIterator::end(&Bcb->BcbLinks); ++it) { auto* BCB_CURRENT = CONTAINING_RECORD(it->Blink, CC_BCB, BcbLinks); CcUnpinData(BCB_CURRENT); } ExFreePoolWithTag(Bcb,NULL); }