[NTOSKRNL:CC] Catch Controller Add LOG Handler Directives
Implemented everything, CcGetLsnForFileObject is left now
This commit is contained in:
parent
98d2bb9ea6
commit
47d3ad5e82
@ -21,9 +21,123 @@ CcGetDirtyPages(IN PVOID LogHandle,
|
||||
IN PVOID Context1,
|
||||
IN PVOID Context2)
|
||||
{
|
||||
/* IMPLEMENTATION INCOMPLETE*/
|
||||
__try
|
||||
{
|
||||
KIRQL OldIrql = {0};
|
||||
PSHARED_CACHE_MAP SharedCacheMap = nullptr;
|
||||
PFILE_OBJECT *FileObject = nullptr;
|
||||
PCC_BCB Bcb = nullptr,
|
||||
PCC_BCB BcbToUnpin = nullptr;
|
||||
PLIST_ENTRY Entry = &CcDirtyLoggedStreamLinks;
|
||||
LARGE_INTEGER OldestLsn = {0};
|
||||
LARGE_INTEGER Result = {0};
|
||||
BOOLEAN FirstIteration = TRUE;
|
||||
|
||||
// Acquire Master Lock
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
|
||||
// Iterate through all Dirty Shared Cache Maps
|
||||
for (auto it = ListEntryIterator::begin(Entry); it != ListEntryIterator::end(Entry); ++it)
|
||||
{
|
||||
SharedCacheMap = CONTAINING_RECORD(*it, SHARED_CACHE_MAP, LoggedStreamLinks);
|
||||
|
||||
// Check flags and validate LogHandle
|
||||
if ((SharedCacheMap->Flags & 0x800) != 0)
|
||||
{
|
||||
DBGPRINT("CcGetDirtyPages::Invalid Flag \n")
|
||||
return;
|
||||
}
|
||||
|
||||
if ((SharedCacheMap->Flags & 0x2000000) != 0 && SharedCacheMap->LogHandle == LogHandle)
|
||||
{
|
||||
SharedCacheMap->OpenCount++;
|
||||
SharedCacheMap->DirtyPages++;
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
|
||||
/* Reference the shared cache map file object*/
|
||||
FileObject = CcReferenceSharedCacheMapFileObject(SharedCacheMap);
|
||||
|
||||
/* Acquire the BCB Lock */
|
||||
oldIrql = ExAcquireSpinLockShared (&SharedCacheMap->BcbSpinLock);
|
||||
|
||||
/* Iterate over BCB List */
|
||||
for (auto it = ListEntryIterator::begin(&SharedCacheMap->BcbList); it != ListEntryIterator::end(&SharedCacheMap->BcbList); ++it)
|
||||
{
|
||||
Bcb = CONTAINING_RECORD(*it, CC_BCB, BcbLinks);
|
||||
|
||||
/* Ensure the BCB is marked as dirty */
|
||||
if (Bcb->NodeTypeCode == NODE_TYPE_DIRTY_BCB && Bcb->NodeByteCode)
|
||||
{ LocalFileOffset = Bcb->BaseData;
|
||||
LocalOldestLsn = Bcb->OldestLsn;
|
||||
LocalNewestLsn = Bcb->NewestLsn;
|
||||
|
||||
/*Increment the PinCount to keep the BCB pinned*/
|
||||
Bcb->PinCount++;
|
||||
|
||||
/*Release the BCB lock temporarily for the callback*/
|
||||
ExReleaseSpinLockShared (&SharedCacheMap->BcbSpinLock,oldIrql);
|
||||
|
||||
/*Unpin any previously pinned BCB*/
|
||||
if (BcbToUnpin)
|
||||
{
|
||||
CcUnpinFileDataEx(BcbToUnpin, 1, 0);
|
||||
BcbToUnpin = NULL;
|
||||
}
|
||||
|
||||
/* Invoke the provided dirty page routine*/
|
||||
DirtyPageRoutine(FileObject,
|
||||
&LocalFileOffset,
|
||||
SharedCacheMap,
|
||||
&LocalOldestLsn,
|
||||
&LocalNewestLsn,
|
||||
Context1,
|
||||
Context2);
|
||||
if (LocalOldestLsn.QuadPart && OldestLsn.QuadPart || LocalOldestLsn.QuadPart < OldestLsn.QuadPart)
|
||||
{
|
||||
OldestLsn = LocalOldestLsn;
|
||||
}
|
||||
}
|
||||
|
||||
// Reacquire the BCB lock
|
||||
oldIrql = ExAcquireSpinLockShared (&SharedCacheMap->BcbSpinLock);
|
||||
// Decrement the PinCount or mark for unpinning
|
||||
if (Bcb->PinCount > 1)
|
||||
{
|
||||
Bcb->PinCount--;
|
||||
BcbToUnpin = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
BcbToUnpin = Bcb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Release the BCB lock*/
|
||||
ExReleaseSpinLockShared (&SharedCacheMap->BcbSpinLock,oldIrql);
|
||||
|
||||
/* Dereference the shared cache map file object*/
|
||||
CcDereferenceSharedCacheMapFileObject(SharedCacheMap, FileObject);
|
||||
|
||||
/*Unpin any remaining BCB*/
|
||||
if (BcbToUnpin)
|
||||
{
|
||||
CcUnpinFileDataEx(BcbToUnpin, 1,0);
|
||||
BcbToUnpin = NULL;
|
||||
}
|
||||
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
|
||||
/*Decrement the OpenCount and DirtyPages*/
|
||||
SharedCacheMap->OpenCount--;
|
||||
SharedCacheMap->DirtyPages--;
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock,OldIrql);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
LARGE_INTEGER
|
||||
NTAPI
|
||||
CcGetLsnForFileObject(IN PFILE_OBJECT FileObject,
|
||||
@ -113,3 +227,99 @@ CcSetLogHandleForFile(IN PFILE_OBJECT FileObject,
|
||||
SharedCacheMap->FlushToLsnRoutine = FlushToLsnRoutine;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcSetLogHandleForFileEx(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PVOID LogHandle,
|
||||
IN PFLUSH_TO_LSN FlushToLsnRoutine
|
||||
IN PQUERY_LOG_USAGE QueryLogUsageRoutine
|
||||
IN PFILE_OBJECT RelatedLogHandleFileObject
|
||||
)
|
||||
{
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
KIRQL OldIrql;
|
||||
LOG_HANDLE_CONTEXT LogHandleContext;
|
||||
PLOG_HANDLE_CONTEXT VolumeLogHandleContext;
|
||||
LIST_ENTRY *ListHead;
|
||||
LIST_ENTRY *PrevEntry;
|
||||
|
||||
// Retrieve the Shared Cache Map
|
||||
SharedCacheMap = (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
|
||||
|
||||
// Validate Shared Cache Map
|
||||
if (!SharedCacheMap || SharedCacheMap->OpenCount == 0) {
|
||||
|
||||
return;
|
||||
}
|
||||
if (SharedCacheMap->Flags & FLAG_LOGHANDLE_SET) {
|
||||
return;
|
||||
}
|
||||
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
|
||||
/* Remove the existing log handle if present*/
|
||||
if (SharedCacheMap->LogHandle)
|
||||
{
|
||||
RemoveEntryList(&SharedCacheMap->LoggedStreamLinks);
|
||||
}
|
||||
|
||||
/*Handle the case when a new log handle is not provided*/
|
||||
if (!LogHandle)
|
||||
{
|
||||
SharedCacheMap->Flags &= ~FLAG_LOGHANDLE_NOT_SET;
|
||||
SharedCacheMap->LogHandle = NULL;
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine the appropriate list based on whether there are dirty pages*/
|
||||
if (SharedCacheMap->DirtyPages)
|
||||
{
|
||||
ListHead = &CcDirtyLoggedStreamLinks;
|
||||
}
|
||||
else
|
||||
{
|
||||
ListHead = &CcCleanLoggedStreamLinks;
|
||||
}
|
||||
|
||||
PrevEntry = ListHead->Blink;
|
||||
InsertTailList(ListHead, &SharedCacheMap->LoggedStreamLinks);
|
||||
|
||||
/*Initialize the volume log handle context if not already present*/
|
||||
VolumeLogHandleContext = &SharedCacheMap->VolumeCacheMap->LogHandleContext;
|
||||
|
||||
if (VolumeLogHandleContext->LogHandle == NULL)
|
||||
{
|
||||
RtlZeroMemory(&LogHandleContext, sizeof(LOG_HANDLE_CONTEXT));
|
||||
LogHandleContext.LastLWTimeStamp.QuadPart = -1;
|
||||
LogHandleContext.LogHandle = LogHandle;
|
||||
LogHandleContext.FlushToLsnRoutine = FlushToLsnRoutine;
|
||||
LogHandleContext.QueryLogUsageRoutine = QueryLogUsageRoutine;
|
||||
|
||||
if (RelatedLogHandleFileObject)
|
||||
{
|
||||
ObfReferenceObjectWithTag(RelatedLogHandleFileObject, 'tlFD');
|
||||
LogHandleContext.RelatedFileObject = RelatedLogHandleFileObject;
|
||||
}
|
||||
|
||||
RtlCopyMemory(VolumeLogHandleContext, &LogHandleContext, sizeof(LOG_HANDLE_CONTEXT));
|
||||
}
|
||||
|
||||
|
||||
SharedCacheMap->LogHandle = VolumeLogHandleContext;
|
||||
|
||||
/*Update the flags and dirty page statistics*/
|
||||
if (!(SharedCacheMap->Flags & FLAG_LOGHANDLE_NOT_SET))
|
||||
{
|
||||
if (SharedCacheMap->DirtyPages)
|
||||
{
|
||||
VolumeLogHandleContext->DirtyPageStatistics.DirtyPages += SharedCacheMap->DirtyPages;
|
||||
}
|
||||
}
|
||||
|
||||
SharedCacheMap->Flags |= FLAG_LOGHANDLE_NOT_SET;
|
||||
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user