[NTOSKRNL:CC] Implemented CcCanIWrite and CcDeferWrite
This commit is contained in:
parent
377ff4fb9b
commit
d81565e7ec
@ -130,12 +130,120 @@ CcCanIWrite(
|
||||
_In_ PFILE_OBJECT FileObject,
|
||||
_In_ ULONG BytesToWrite,
|
||||
_In_ BOOLEAN Wait,
|
||||
_In_ BOOLEAN IsRetrying)
|
||||
_In_ UCHAR Retrying)
|
||||
{
|
||||
NT_DBGBREAK("UNIMPLEMENTED\n");
|
||||
}
|
||||
PFSRTL_COMMON_FCB_HEADER FsContext;
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
DEFERRED_WRITE DeferredWrite;
|
||||
KEVENT Event;
|
||||
ULONG WriteSize;
|
||||
ULONG Pages;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN IsSmallThreshold = FALSE;
|
||||
|
||||
|
||||
/* Quick checks for immediate return */
|
||||
if (FileObject->Flags & FO_WRITE_THROUGH)
|
||||
return TRUE;
|
||||
|
||||
if (IoIsFileOriginRemote(FileObject) && Retrying < 0xFD)
|
||||
return TRUE;
|
||||
|
||||
/* Calculate size and pages */
|
||||
WriteSize = min(BytesToWrite, 0x40000);
|
||||
Pages = ROUND_UP(WriteSize, PAGE_SIZE) / PAGE_SIZE;
|
||||
|
||||
FsContext = FileObject->FsContext;
|
||||
|
||||
/* Check threshold conditions */
|
||||
if (Retrying >= 0xFE || (FsContext->Flags & FSRTL_FLAG_LIMIT_MODIFIED_PAGES))
|
||||
{
|
||||
if (Retrying != 0xFF)
|
||||
{
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
}
|
||||
|
||||
if (FileObject->SectionObjectPointer)
|
||||
{
|
||||
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
||||
if (SharedCacheMap &&
|
||||
SharedCacheMap->DirtyPageThreshold &&
|
||||
SharedCacheMap->DirtyPages)
|
||||
{
|
||||
if (SharedCacheMap->DirtyPageThreshold < (SharedCacheMap->DirtyPages + Pages))
|
||||
{
|
||||
IsSmallThreshold = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Retrying != 0xFF)
|
||||
{
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we can write immediately */
|
||||
if ((Retrying || IsListEmpty(&CcDeferredWrites)) &&
|
||||
(CcDirtyPageThreshold > (CcTotalDirtyPages + Pages)))
|
||||
{
|
||||
if ((MmAvailablePages > MmThrottleTop && !IsSmallThreshold) ||
|
||||
(MmModifiedPageListHead.Total < 1000 &&
|
||||
MmAvailablePages > MmThrottleBottom &&
|
||||
!IsSmallThreshold))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Wait)
|
||||
return FALSE;
|
||||
|
||||
/* Initialize deferred write */
|
||||
if (IsListEmpty(&CcDeferredWrites))
|
||||
{
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
CcScheduleLazyWriteScan(TRUE);
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
}
|
||||
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
DeferredWrite.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
|
||||
DeferredWrite.NodeByteSize = sizeof(DEFERRED_WRITE);
|
||||
DeferredWrite.FileObject = FileObject;
|
||||
DeferredWrite.BytesToWrite = BytesToWrite;
|
||||
DeferredWrite.Event = &Event;
|
||||
DeferredWrite.LimitModifiedPages = (FsContext->Flags & FSRTL_FLAG_LIMIT_MODIFIED_PAGES) != 0;
|
||||
|
||||
/* Insert into deferred writes list */
|
||||
/* Insert into deferred writes list */
|
||||
if (Retrying)
|
||||
{
|
||||
ExInterlockedInsertHeadList(&CcDeferredWrites,
|
||||
&DeferredWrite.DeferredWriteLinks,
|
||||
&CcDeferredWriteSpinLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExInterlockedInsertTailList(&CcDeferredWrites,
|
||||
&DeferredWrite.DeferredWriteLinks,
|
||||
&CcDeferredWriteSpinLock);
|
||||
}
|
||||
|
||||
/* Wait for the write to complete */
|
||||
do
|
||||
{
|
||||
CcPostDeferredWrites();
|
||||
} while (KeWaitForSingleObject(&Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
&CcIdleDelay) != STATUS_SUCCESS);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
@ -165,18 +273,53 @@ CcCopyWrite(
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcDeferWrite(IN PFILE_OBJECT FileObject,
|
||||
IN PCC_POST_DEFERRED_WRITE PostRoutine,
|
||||
IN PVOID Context1,
|
||||
IN PVOID Context2,
|
||||
IN ULONG BytesToWrite,
|
||||
IN BOOLEAN Retrying)
|
||||
CcDeferWrite(
|
||||
_In_ PFILE_OBJECT FileObject,
|
||||
_In_ PCC_POST_DEFERRED_WRITE PostRoutine,
|
||||
_In_ PVOID Context1,
|
||||
_In_ PVOID Context2,
|
||||
_In_ ULONG BytesToWrite,
|
||||
_In_ BOOLEAN Retrying
|
||||
)
|
||||
{
|
||||
NT_DBGBREAK("UNIMPLEMENTED\n");
|
||||
}
|
||||
|
||||
KIRQL OldIrql;
|
||||
|
||||
|
||||
PDEFERRED_WRITE DeferredWrite = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(DEFERRED_WRITE), 'wDcC');
|
||||
if (DeferredWrite != nullptr)
|
||||
{
|
||||
RtlZeroMemory(DeferredWrite, sizeof(DEFERRED_WRITE));
|
||||
|
||||
DeferredWrite->NodeTypeCode = NODE_TYPE_DEFERRED_WRITE;
|
||||
DeferredWrite->NodeByteSize = sizeof(DEFERRED_WRITE);
|
||||
DeferredWrite->FileObject = FileObject;
|
||||
DeferredWrite->BytesToWrite = BytesToWrite;
|
||||
DeferredWrite->PostRoutine = PostRoutine;
|
||||
DeferredWrite->Context1 = Context1;
|
||||
DeferredWrite->Context2 = Context2;
|
||||
|
||||
if (Retrying)
|
||||
ExInterlockedInsertHeadList(&CcDeferredWrites,
|
||||
&DeferredWrite->DeferredWriteLinks,
|
||||
&CcDeferredWriteSpinLock);
|
||||
else
|
||||
ExInterlockedInsertTailList(&CcDeferredWrites,
|
||||
&DeferredWrite->DeferredWriteLinks,
|
||||
&CcDeferredWriteSpinLock);
|
||||
|
||||
CcPostDeferredWrites();
|
||||
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||
CcScheduleLazyWriteScan(TRUE);
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
PostRoutine(Context1, Context2);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CcFastCopyRead(
|
||||
|
Loading…
Reference in New Issue
Block a user