alcyone/NTOSKRNL/CC/ccpinsupport.cpp
Dibyamartanda Samanta d825fe1dcb
[NTOSKRNL:CC] Implemented CcSetBcbOwnerPointer
Implemented CcSetBcbOwnerPointer, now it correctly handle resource from MBCB
2024-07-31 08:46:17 +02:00

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);
}