[NTOSKRNL]

- Optimize CcRosTrimCache by eliminating an extra loop of all segments
- Allow swapping of dirty segments by flushing them first

svn path=/trunk/; revision=54549
This commit is contained in:
Cameron Gutman 2011-11-30 17:10:43 +00:00
parent 246357c187
commit f9794fddef

View file

@ -302,79 +302,80 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
ULONG PagesFreed; ULONG PagesFreed;
KIRQL oldIrql; KIRQL oldIrql;
LIST_ENTRY FreeList; LIST_ENTRY FreeList;
PFN_NUMBER Page;
ULONG i;
DPRINT("CcRosTrimCache(Target %d)\n", Target); DPRINT("CcRosTrimCache(Target %d)\n", Target);
*NrFreed = 0;
InitializeListHead(&FreeList); InitializeListHead(&FreeList);
KeAcquireGuardedMutex(&ViewLock); /* Flush dirty pages to disk */
current_entry = CacheSegmentLRUListHead.Flink; CcRosFlushDirtyPages(Target, NrFreed);
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
{
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
CacheSegmentLRUListEntry);
current_entry = current_entry->Flink;
KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
if (current->MappedCount > 0 && !current->Dirty && !current->PageOut)
{
ULONG i;
CcRosCacheSegmentIncRefCount(current);
current->PageOut = TRUE;
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
KeReleaseGuardedMutex(&ViewLock);
for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++)
{
PFN_NUMBER Page;
Page = (PFN_NUMBER)(MmGetPhysicalAddress((char*)current->BaseAddress + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
MmPageOutPhysicalAddress(Page);
}
KeAcquireGuardedMutex(&ViewLock);
KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
CcRosCacheSegmentDecRefCount(current);
}
if (current->ReferenceCount == 0)
{
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
// PagesFreed = PagesPerSegment;
PagesFreed = min(PagesPerSegment, Target);
Target -= PagesFreed;
(*NrFreed) += PagesFreed;
}
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
}
if ((*NrFreed) != 0) DPRINT1("Flushed %d dirty cache pages to disk\n", (*NrFreed));
*NrFreed = 0;
KeAcquireGuardedMutex(&ViewLock);
current_entry = CacheSegmentLRUListHead.Flink; current_entry = CacheSegmentLRUListHead.Flink;
while (current_entry != &CacheSegmentLRUListHead) while (current_entry != &CacheSegmentLRUListHead)
{ {
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
CacheSegmentLRUListEntry); CacheSegmentLRUListEntry);
current->PageOut = FALSE;
current_entry = current_entry->Flink; current_entry = current_entry->Flink;
KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql); KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
/* Reference the cache segment */
CcRosCacheSegmentIncRefCount(current);
/* Check if it's mapped and not dirty */
if (current->MappedCount > 0 && !current->Dirty)
{
/* We have to break these locks because Cc sucks */
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
KeReleaseGuardedMutex(&ViewLock);
/* Page out the segment */
for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++)
{
Page = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)current->BaseAddress + (i * PAGE_SIZE)).QuadPart >> PAGE_SHIFT);
MmPageOutPhysicalAddress(Page);
}
/* Reacquire the locks */
KeAcquireGuardedMutex(&ViewLock);
KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
}
/* Dereference the cache segment */
CcRosCacheSegmentDecRefCount(current);
/* Check if we can free this entry now */
if (current->ReferenceCount == 0) if (current->ReferenceCount == 0)
{ {
ASSERT(!current->Dirty);
ASSERT(!current->MappedCount);
RemoveEntryList(&current->BcbSegmentListEntry); RemoveEntryList(&current->BcbSegmentListEntry);
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
RemoveEntryList(&current->CacheSegmentListEntry); RemoveEntryList(&current->CacheSegmentListEntry);
RemoveEntryList(&current->CacheSegmentLRUListEntry); RemoveEntryList(&current->CacheSegmentLRUListEntry);
InsertHeadList(&FreeList, &current->BcbSegmentListEntry); InsertHeadList(&FreeList, &current->BcbSegmentListEntry);
/* Calculate how many pages we freed for Mm */
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
PagesFreed = min(PagesPerSegment, Target);
Target -= PagesFreed;
(*NrFreed) += PagesFreed;
} }
else
{ KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
}
} }
KeReleaseGuardedMutex(&ViewLock); KeReleaseGuardedMutex(&ViewLock);
while (!IsListEmpty(&FreeList)) while (!IsListEmpty(&FreeList))
{ {
current_entry = RemoveHeadList(&FreeList); current_entry = RemoveHeadList(&FreeList);
@ -382,7 +383,9 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
BcbSegmentListEntry); BcbSegmentListEntry);
CcRosInternalFreeCacheSegment(current); CcRosInternalFreeCacheSegment(current);
} }
DPRINT1("Evicted %d cache pages\n", (*NrFreed));
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }