[NTOSKRNL:CC] Implemented CcSetDirtyInMask

This commit is contained in:
Dibyamartanda Samanta 2024-11-08 08:58:18 +01:00 committed by CodingWorkshop Signing Team
parent d81565e7ec
commit f6620f9372
Signed by: CodingWorkshop Signing Team
GPG Key ID: 6DC88369C82795D2

View File

@ -100,28 +100,160 @@ CcFindBitmapRangeToDirty(
VOID VOID
NTAPI NTAPI
CcSetDirtyInMask( CcSetDirtyInMask(
_In_ PSHARED_CACHE_MAP SharedMap, _In_ PSHARED_CACHE_MAP SharedCacheMap,
_In_ PLARGE_INTEGER FileOffset, _In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length) _In_ ULONG Length)
{ {
NT_DBGBREAK("UNIMPLEMENTED\n"); KLOCK_QUEUE_HANDLE LockHandle = {0};
LARGE_INTEGER EndOffset = {0};
ULONGLONG StartPage ={0};
ULONGLONG EndPage = {0};
ULONG CurrentPage = {0};
PMBCB Mbcb = nullptr;
PBITMAP_RANGE BitmapRange = nullptr;
PULONG Bitmap = nullptr;
PULONG VacbLevel = nullptr;
ULONG BitMask = {0};
// Calculate start and end pages
StartPage = FileOffset->QuadPart >> PAGE_SHIFT;
EndOffset.QuadPart = FileOffset->QuadPart + Length;
EndPage = (EndOffset.QuadPart - 1) >> PAGE_SHIFT;
for(;;)
{
if (SharedCacheMap->SectionSize.QuadPart > VACB_MAPPING_GRANULARITY)
{
if (!CcPrefillVacbLevelZone(1, &LockHandle, 0, 0, 0))
return;
VacbLevel = CcAllocateVacbLevel(0);
KeLowerIrql(LockHandle.OldIrql);
}
KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbSpinLock, &LockHandle);
Mbcb = SharedCacheMap->Mbcb;
if (Mbcb == nullptr)
{
Mbcb = CcAllocateInitializeBcb();
if (Mbcb == nullptr)
goto ReleaseAndExit;
Mbcb->NodeTypeCode = CACHE_NTC_BCB;
InitializeListHead(&Mbcb->BitmapRanges);
InsertHeadList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange1.Links);
Mbcb->BitmapRange1.FirstDirtyPage = (ULONG)-1;
Mbcb->BitmapRange1.Bitmap = (PULONG)&Mbcb->BitmapRange2;
SharedCacheMap->Mbcb = Mbcb;
}
if (EndPage < 512 || Mbcb->NodeTypeCode == 0x02F9)
{
BitmapRange = CcFindBitmapRangeToDirty(Mbcb, StartPage, &Bitmap);
if (BitmapRange == nullptr)
break;
if (StartPage < BitmapRange->BasePage + BitmapRange->FirstDirtyPage)
BitmapRange->FirstDirtyPage = StartPage - BitmapRange->BasePage;
if (EndPage > BitmapRange->BasePage + BitmapRange->LastDirtyPage)
BitmapRange->LastDirtyPage = EndPage - BitmapRange->BasePage;
if (SharedCacheMap->DirtyPages == 0)
{
CcScheduleLazyWriteScan(FALSE);
RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks);
InsertTailList(&CcDirtySharedCacheMapList, &SharedCacheMap->SharedCacheMapLinks);
Mbcb->ResumeWritePage = StartPage;
}
Bitmap = &BitmapRange->Bitmap[(StartPage - BitmapRange->BasePage) >> 5];
BitMask = 1 << (StartPage & 0x1F);
for (CurrentPage = StartPage; CurrentPage <= EndPage; CurrentPage++)
{
if ((*Bitmap & BitMask) == 0)
{
CcTotalDirtyPages++;
Mbcb->DirtyPages++;
BitmapRange->DirtyPages++;
SharedCacheMap->DirtyPages++;
*Bitmap |= BitMask;
}
BitMask <<= 1;
if (BitMask == 0)
{
Bitmap++;
BitMask = 1;
}
}
}
else
{
// Handle large files (>2MB)
if (Mbcb->BitmapRange1.DirtyPages)
{
RtlCopyMemory(VacbLevel, Mbcb->BitmapRange1.Bitmap, (2 * sizeof(BITMAP_RANGE)));
RtlZeroMemory(Mbcb->BitmapRange1.Bitmap, (2 * sizeof(BITMAP_RANGE)));
}
Mbcb->BitmapRange1.Bitmap = VacbLevel;
// Initialize BitmapRange2
InsertTailList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange2.Links);
Mbcb->BitmapRange2.BasePage = (ULONGLONG)-1;
Mbcb->BitmapRange2.FirstDirtyPage = (ULONG)-1;
// Initialize BitmapRange3
InsertTailList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange3.Links);
Mbcb->BitmapRange3.BasePage = (ULONGLONG)-1;
Mbcb->BitmapRange3.FirstDirtyPage = (ULONG)-1;
VacbLevel = nullptr;
Mbcb->NodeTypeCode = 0x02F9;
KeReleaseInStackQueuedSpinLock(&LockHandle);
continue;
}
// Update ValidDataGoal if necessary
if (EndOffset.QuadPart > SharedCacheMap->ValidDataGoal.QuadPart)
{
SharedCacheMap->ValidDataGoal = EndOffset;
}
break;
}
ReleaseAndExit:
if (VacbLevel != nullptr)
{
*VacbLevel = (ULONG)CcVacbLevelFreeList;
CcVacbLevelEntries++;
CcVacbLevelFreeList = VacbLevel;
}
KeReleaseInStackQueuedSpinLock(&LockHandle);
} }
BOOLEAN BOOLEAN
NTAPI NTAPI
CcMapAndCopy( CcMapAndCopy(
_In_ PSHARED_CACHE_MAP SharedMap, _In_ PSHARED_CACHE_MAP SharedCacheMap,
_In_ PVOID Buffer, _In_ PVOID Buffer,
_In_ PLARGE_INTEGER FileOffset, _In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length, _In_ ULONG Length,
_In_ ULONG CopyFlags, _In_ ULONG Flags,
_In_ PFILE_OBJECT FileObject, _In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER ValidDataLength, _In_ PLARGE_INTEGER ValidDataLength,
_In_ BOOLEAN Wait) _In_ BOOLEAN Wait)
{ {
NT_DBGBREAK("UNIMPLEMENTED\n"); NT_DBGBREAK("UNIMPLEMENTED\n");
} }
/* EXTERNAL API FUNCTIONS */ /* EXTERNAL API FUNCTIONS */
BOOLEAN BOOLEAN
@ -132,22 +264,22 @@ CcCanIWrite(
_In_ BOOLEAN Wait, _In_ BOOLEAN Wait,
_In_ UCHAR Retrying) _In_ UCHAR Retrying)
{ {
PFSRTL_COMMON_FCB_HEADER FsContext; PFSRTL_COMMON_FCB_HEADER FsContext = nullptr;
PSHARED_CACHE_MAP SharedCacheMap; PSHARED_CACHE_MAP SharedCacheMap = nullptr;
DEFERRED_WRITE DeferredWrite; DEFERRED_WRITE DeferredWrite = {0};
KEVENT Event; KEVENT Event = {0};
ULONG WriteSize; ULONG WriteSize = {0};
ULONG Pages; ULONG Pages = {0};
KIRQL OldIrql; KIRQL OldIrql = {0};
BOOLEAN IsSmallThreshold = FALSE; BOOLEAN IsSmallThreshold = false;
/* Quick checks for immediate return */ /* Quick checks for immediate return */
if (FileObject->Flags & FO_WRITE_THROUGH) if (FileObject->Flags & FO_WRITE_THROUGH)
return TRUE; return true;
if (IoIsFileOriginRemote(FileObject) && Retrying < 0xFD) if (IoIsFileOriginRemote(FileObject) && Retrying < 0xFD)
return TRUE; return true;
/* Calculate size and pages */ /* Calculate size and pages */
WriteSize = min(BytesToWrite, 0x40000); WriteSize = min(BytesToWrite, 0x40000);
@ -172,7 +304,7 @@ CcCanIWrite(
{ {
if (SharedCacheMap->DirtyPageThreshold < (SharedCacheMap->DirtyPages + Pages)) if (SharedCacheMap->DirtyPageThreshold < (SharedCacheMap->DirtyPages + Pages))
{ {
IsSmallThreshold = TRUE; IsSmallThreshold = true;
} }
} }
} }
@ -192,7 +324,7 @@ CcCanIWrite(
MmAvailablePages > MmThrottleBottom && MmAvailablePages > MmThrottleBottom &&
!IsSmallThreshold)) !IsSmallThreshold))
{ {
return TRUE; return true;
} }
} }
@ -207,7 +339,7 @@ CcCanIWrite(
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
} }
KeInitializeEvent(&Event, NotificationEvent, FALSE); KeInitializeEvent(&Event, NotificationEvent, false);
DeferredWrite.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE; DeferredWrite.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
DeferredWrite.NodeByteSize = sizeof(DEFERRED_WRITE); DeferredWrite.NodeByteSize = sizeof(DEFERRED_WRITE);
@ -238,7 +370,7 @@ CcCanIWrite(
} while (KeWaitForSingleObject(&Event, } while (KeWaitForSingleObject(&Event,
Executive, Executive,
KernelMode, KernelMode,
FALSE, false,
&CcIdleDelay) != STATUS_SUCCESS); &CcIdleDelay) != STATUS_SUCCESS);
return TRUE; return TRUE;