Implemented CcSetBcbOwnerPointer, now it correctly handle resource from MBCB
361 lines
8.0 KiB
C++
361 lines
8.0 KiB
C++
/*
|
|
* PROJECT: Alcyone System Kernel
|
|
* LICENSE: BSD Clause 3
|
|
* PURPOSE: Cache Controller:: Lazy Writer
|
|
* NT KERNEL: 5.11.9360
|
|
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
|
|
*/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NTDEBUG
|
|
#include <debug.h>
|
|
#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<PVACB>(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<PCC_BCB>(BcbPtr);
|
|
BOOLEAN WRITE_FLAG = NULL;
|
|
|
|
if (reinterpret_cast<ULONG_PTR>((Bcb & 1))
|
|
{
|
|
WRITE_FLAG = TRUE;
|
|
Bcb = reinterpret_cast<PCC_BCB>(reinterpret_cast<ULONG_PTR>(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<ULONG_PTR>((Bcb & 1))
|
|
{
|
|
WRITE_FLAG = TRUE;
|
|
Bcb = reinterpret_cast<PCC_BCB>(reinterpret_cast<ULONG_PTR>(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);
|
|
|
|
}
|
|
|
|
|