[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
|
/*
|
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
|
* FILE: ntoskrnl/cache/fssup.c
|
|
|
|
|
* PURPOSE: Logging and configuration routines
|
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
|
|
|
|
* Art Yerkes
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
|
#include "newcc.h"
|
|
|
|
|
#include "section/newmm.h"
|
|
|
|
|
#define NDEBUG
|
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
|
|
|
|
|
PFSN_PREFETCHER_GLOBALS CcPfGlobals;
|
|
|
|
|
extern LONG CcOutstandingDeletes;
|
|
|
|
|
extern KEVENT CcpLazyWriteEvent;
|
|
|
|
|
extern KEVENT CcFinalizeEvent;
|
|
|
|
|
extern VOID NTAPI CcpUnmapThread(PVOID Unused);
|
|
|
|
|
extern VOID NTAPI CcpLazyWriteThread(PVOID Unused);
|
|
|
|
|
HANDLE CcUnmapThreadHandle, CcLazyWriteThreadHandle;
|
|
|
|
|
CLIENT_ID CcUnmapThreadId, CcLazyWriteThreadId;
|
2010-12-24 22:54:24 +00:00
|
|
|
|
FAST_MUTEX GlobalPageOperation;
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
|
|
|
|
|
|
typedef struct _NOCC_PRIVATE_CACHE_MAP
|
|
|
|
|
{
|
|
|
|
|
LIST_ENTRY ListEntry;
|
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
|
PNOCC_CACHE_MAP Map;
|
|
|
|
|
} NOCC_PRIVATE_CACHE_MAP, *PNOCC_PRIVATE_CACHE_MAP;
|
|
|
|
|
|
|
|
|
|
LIST_ENTRY CcpAllSharedCacheMaps;
|
|
|
|
|
|
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
|
|
|
|
|
// Interact with legacy balance manager for now
|
|
|
|
|
// This can fall away when our section implementation supports
|
|
|
|
|
// demand paging properly
|
|
|
|
|
NTSTATUS
|
|
|
|
|
CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
|
|
|
|
{
|
|
|
|
|
ULONG i, Freed, BcbHead;
|
|
|
|
|
|
|
|
|
|
*NrFreed = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < CACHE_NUM_SECTIONS; i++) {
|
|
|
|
|
BcbHead = (i+CcCacheClockHand) % CACHE_NUM_SECTIONS;
|
|
|
|
|
|
|
|
|
|
// Reference a cache stripe so it won't go away
|
|
|
|
|
CcpLock();
|
|
|
|
|
if (CcCacheSections[BcbHead].BaseAddress) {
|
2010-12-23 08:42:51 +00:00
|
|
|
|
CcpReferenceCache(BcbHead);
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
|
CcpUnlock();
|
|
|
|
|
} else {
|
|
|
|
|
CcpUnlock();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Defer to MM to try recovering pages from it
|
|
|
|
|
Freed = MiCacheEvictPages
|
|
|
|
|
(CcCacheSections[BcbHead].BaseAddress, Target);
|
|
|
|
|
|
|
|
|
|
Target -= Freed;
|
|
|
|
|
*NrFreed += Freed;
|
|
|
|
|
|
|
|
|
|
CcpLock();
|
2010-12-23 08:42:51 +00:00
|
|
|
|
CcpUnpinData(&CcCacheSections[BcbHead], TRUE);
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
|
CcpUnlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
|
|
|
|
CcInitializeCacheManager(VOID)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
DPRINT("Initialize\n");
|
|
|
|
|
for (i = 0; i < CACHE_NUM_SECTIONS; i++)
|
|
|
|
|
{
|
|
|
|
|
KeInitializeEvent(&CcCacheSections[i].ExclusiveWait, SynchronizationEvent, FALSE);
|
|
|
|
|
InitializeListHead(&CcCacheSections[i].ThisFileList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InitializeListHead(&CcpAllSharedCacheMaps);
|
|
|
|
|
|
|
|
|
|
KeInitializeEvent(&CcDeleteEvent, SynchronizationEvent, FALSE);
|
|
|
|
|
KeInitializeEvent(&CcFinalizeEvent, SynchronizationEvent, FALSE);
|
|
|
|
|
KeInitializeEvent(&CcpLazyWriteEvent, SynchronizationEvent, FALSE);
|
|
|
|
|
|
|
|
|
|
CcCacheBitmap->Buffer = ((PULONG)&CcCacheBitmap[1]);
|
|
|
|
|
CcCacheBitmap->SizeOfBitMap = ROUND_UP(CACHE_NUM_SECTIONS, 32);
|
|
|
|
|
DPRINT("Cache has %d entries\n", CcCacheBitmap->SizeOfBitMap);
|
|
|
|
|
ExInitializeFastMutex(&CcMutex);
|
2010-12-24 22:54:24 +00:00
|
|
|
|
ExInitializeFastMutex(&GlobalPageOperation);
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
|
|
|
|
|
|
// MM stub
|
|
|
|
|
KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
|
|
|
|
|
|
|
|
|
|
// Until we're fully demand paged, we can do things the old way through
|
|
|
|
|
// the balance manager
|
|
|
|
|
MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
|
|
|
|
CcPfInitializePrefetcher(VOID)
|
|
|
|
|
{
|
|
|
|
|
/* Notify debugger */
|
|
|
|
|
DbgPrintEx(DPFLTR_PREFETCHER_ID,
|
|
|
|
|
DPFLTR_TRACE_LEVEL,
|
|
|
|
|
"CCPF: InitializePrefetecher()\n");
|
|
|
|
|
|
|
|
|
|
/* Setup the Prefetcher Data */
|
|
|
|
|
InitializeListHead(&CcPfGlobals.ActiveTraces);
|
|
|
|
|
InitializeListHead(&CcPfGlobals.CompletedTraces);
|
|
|
|
|
ExInitializeFastMutex(&CcPfGlobals.CompletedTracesLock);
|
|
|
|
|
|
|
|
|
|
/* FIXME: Setup the rest of the prefetecher */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
|
|
|
|
CcpAcquireFileLock(PNOCC_CACHE_MAP Map)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Calling AcquireForLazyWrite: %x\n", Map->LazyContext);
|
|
|
|
|
return Map->Callbacks.AcquireForLazyWrite(Map->LazyContext, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
|
|
|
|
CcpReleaseFileLock(PNOCC_CACHE_MAP Map)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Releasing Lazy Write %x\n", Map->LazyContext);
|
|
|
|
|
Map->Callbacks.ReleaseFromLazyWrite(Map->LazyContext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Must have CcpLock()
|
|
|
|
|
PFILE_OBJECT CcpFindOtherStreamFileObject(PFILE_OBJECT FileObject)
|
|
|
|
|
{
|
|
|
|
|
PLIST_ENTRY Entry, Private;
|
|
|
|
|
for (Entry = CcpAllSharedCacheMaps.Flink;
|
|
|
|
|
Entry != &CcpAllSharedCacheMaps;
|
|
|
|
|
Entry = Entry->Flink)
|
|
|
|
|
{
|
|
|
|
|
// 'Identical' test for other stream file object
|
|
|
|
|
PNOCC_CACHE_MAP Map = CONTAINING_RECORD(Entry, NOCC_CACHE_MAP, Entry);
|
|
|
|
|
for (Private = Map->PrivateCacheMaps.Flink;
|
|
|
|
|
Private != &Map->PrivateCacheMaps;
|
|
|
|
|
Private = Private->Flink)
|
|
|
|
|
{
|
|
|
|
|
PNOCC_PRIVATE_CACHE_MAP PrivateMap = CONTAINING_RECORD(Private, NOCC_PRIVATE_CACHE_MAP, ListEntry);
|
|
|
|
|
if (PrivateMap->FileObject->Flags & FO_STREAM_FILE &&
|
|
|
|
|
PrivateMap->FileObject->DeviceObject == FileObject->DeviceObject &&
|
|
|
|
|
PrivateMap->FileObject->Vpb == FileObject->Vpb &&
|
|
|
|
|
PrivateMap->FileObject->FsContext == FileObject->FsContext &&
|
|
|
|
|
PrivateMap->FileObject->FsContext2 == FileObject->FsContext2 &&
|
|
|
|
|
1)
|
|
|
|
|
{
|
|
|
|
|
return PrivateMap->FileObject;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Thanks: http://windowsitpro.com/Windows/Articles/ArticleID/3864/pg/2/2.html
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
|
|
|
|
CcInitializeCacheMap(IN PFILE_OBJECT FileObject,
|
|
|
|
|
IN PCC_FILE_SIZES FileSizes,
|
|
|
|
|
IN BOOLEAN PinAccess,
|
|
|
|
|
IN PCACHE_MANAGER_CALLBACKS Callbacks,
|
|
|
|
|
IN PVOID LazyWriteContext)
|
|
|
|
|
{
|
|
|
|
|
PNOCC_CACHE_MAP Map = FileObject->SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
PNOCC_PRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap;
|
|
|
|
|
|
|
|
|
|
CcpLock();
|
|
|
|
|
if (!Map && FileObject->Flags & FO_STREAM_FILE)
|
|
|
|
|
{
|
|
|
|
|
PFILE_OBJECT IdenticalStreamFileObject =
|
|
|
|
|
CcpFindOtherStreamFileObject(FileObject);
|
|
|
|
|
if (IdenticalStreamFileObject)
|
|
|
|
|
Map = IdenticalStreamFileObject->SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
if (Map)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1
|
|
|
|
|
("Linking SFO %x to previous SFO %x through cache map %x #\n",
|
|
|
|
|
FileObject, IdenticalStreamFileObject, Map);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!Map)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Initializing file object for (%p) %wZ\n", FileObject, &FileObject->FileName);
|
|
|
|
|
Map = ExAllocatePool(NonPagedPool, sizeof(NOCC_CACHE_MAP));
|
|
|
|
|
FileObject->SectionObjectPointer->SharedCacheMap = Map;
|
|
|
|
|
Map->FileSizes = *FileSizes;
|
|
|
|
|
Map->LazyContext = LazyWriteContext;
|
|
|
|
|
Map->ReadAheadGranularity = PAGE_SIZE;
|
|
|
|
|
RtlCopyMemory(&Map->Callbacks, Callbacks, sizeof(*Callbacks));
|
|
|
|
|
// For now ...
|
|
|
|
|
DPRINT("FileSizes->ValidDataLength %08x%08x\n", FileSizes->ValidDataLength.HighPart, FileSizes->ValidDataLength.LowPart);
|
|
|
|
|
InitializeListHead(&Map->AssociatedBcb);
|
|
|
|
|
InitializeListHead(&Map->PrivateCacheMaps);
|
|
|
|
|
InsertTailList(&CcpAllSharedCacheMaps, &Map->Entry);
|
|
|
|
|
DPRINT("New Map %x\n", Map);
|
|
|
|
|
}
|
|
|
|
|
if (!PrivateCacheMap)
|
|
|
|
|
{
|
|
|
|
|
PrivateCacheMap = ExAllocatePool(NonPagedPool, sizeof(*PrivateCacheMap));
|
|
|
|
|
FileObject->PrivateCacheMap = PrivateCacheMap;
|
|
|
|
|
PrivateCacheMap->FileObject = FileObject;
|
|
|
|
|
ObReferenceObject(PrivateCacheMap->FileObject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PrivateCacheMap->Map = Map;
|
|
|
|
|
InsertTailList(&Map->PrivateCacheMaps, &PrivateCacheMap->ListEntry);
|
|
|
|
|
|
|
|
|
|
CcpUnlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
|
NTAPI
|
|
|
|
|
CcpCountCacheSections(IN PNOCC_CACHE_MAP Map)
|
|
|
|
|
{
|
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
|
ULONG Count;
|
|
|
|
|
|
|
|
|
|
for (Count = 0, Entry = Map->AssociatedBcb.Flink; Entry != &Map->AssociatedBcb; Entry = Entry->Flink, Count++);
|
|
|
|
|
|
|
|
|
|
return Count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
|
|
|
|
CcUninitializeCacheMap(IN PFILE_OBJECT FileObject,
|
|
|
|
|
IN OPTIONAL PLARGE_INTEGER TruncateSize,
|
|
|
|
|
IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
|
|
|
|
|
{
|
|
|
|
|
BOOLEAN LastMap = FALSE;
|
|
|
|
|
PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
PNOCC_PRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap;
|
|
|
|
|
|
|
|
|
|
DPRINT("Uninitializing file object for %wZ SectionObjectPointer %x\n", &FileObject->FileName, FileObject->SectionObjectPointer);
|
|
|
|
|
|
|
|
|
|
ASSERT(UninitializeEvent == NULL);
|
|
|
|
|
|
|
|
|
|
if (Map)
|
|
|
|
|
CcpFlushCache(Map, NULL, 0, NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
CcpLock();
|
|
|
|
|
if (PrivateCacheMap)
|
|
|
|
|
{
|
|
|
|
|
ASSERT(!Map || Map == PrivateCacheMap->Map);
|
|
|
|
|
ASSERT(PrivateCacheMap->FileObject == FileObject);
|
|
|
|
|
|
|
|
|
|
RemoveEntryList(&PrivateCacheMap->ListEntry);
|
|
|
|
|
if (IsListEmpty(&PrivateCacheMap->Map->PrivateCacheMaps))
|
|
|
|
|
{
|
|
|
|
|
while (!IsListEmpty(&Map->AssociatedBcb))
|
|
|
|
|
{
|
|
|
|
|
PNOCC_BCB Bcb = CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList);
|
|
|
|
|
DPRINT("Evicting cache stripe #%x\n", Bcb - CcCacheSections);
|
|
|
|
|
Bcb->RefCount = 1;
|
|
|
|
|
CcpDereferenceCache(Bcb - CcCacheSections, TRUE);
|
|
|
|
|
}
|
|
|
|
|
RemoveEntryList(&PrivateCacheMap->Map->Entry);
|
|
|
|
|
ExFreePool(PrivateCacheMap->Map);
|
|
|
|
|
FileObject->SectionObjectPointer->SharedCacheMap = NULL;
|
|
|
|
|
LastMap = TRUE;
|
|
|
|
|
}
|
|
|
|
|
ObDereferenceObject(PrivateCacheMap->FileObject);
|
|
|
|
|
FileObject->PrivateCacheMap = NULL;
|
|
|
|
|
ExFreePool(PrivateCacheMap);
|
|
|
|
|
}
|
|
|
|
|
CcpUnlock();
|
|
|
|
|
|
|
|
|
|
DPRINT("Uninit complete\n");
|
|
|
|
|
|
|
|
|
|
return LastMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
|
|
|
|
CcSetFileSizes(IN PFILE_OBJECT FileObject,
|
|
|
|
|
IN PCC_FILE_SIZES FileSizes)
|
|
|
|
|
{
|
|
|
|
|
PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
if (!Map) return;
|
|
|
|
|
Map->FileSizes = *FileSizes;
|
|
|
|
|
PNOCC_BCB Bcb = Map->AssociatedBcb.Flink == &Map->AssociatedBcb ?
|
|
|
|
|
NULL : CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList);
|
|
|
|
|
if (!Bcb) return;
|
|
|
|
|
MmExtendCacheSection(Bcb->SectionObject, &FileSizes->FileSize, FALSE);
|
|
|
|
|
DPRINT("FileSizes->FileSize %x\n", FileSizes->FileSize.LowPart);
|
|
|
|
|
DPRINT("FileSizes->AllocationSize %x\n", FileSizes->AllocationSize.LowPart);
|
|
|
|
|
DPRINT("FileSizes->ValidDataLength %x\n", FileSizes->ValidDataLength.LowPart);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
|
|
|
|
CcGetFileSizes
|
|
|
|
|
(IN PFILE_OBJECT FileObject,
|
|
|
|
|
IN PCC_FILE_SIZES FileSizes)
|
|
|
|
|
{
|
|
|
|
|
PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
if (!Map) return FALSE;
|
|
|
|
|
*FileSizes = Map->FileSizes;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
|
|
|
|
CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
|
|
|
|
|
IN OPTIONAL PLARGE_INTEGER FileOffset,
|
|
|
|
|
IN ULONG Length,
|
|
|
|
|
IN BOOLEAN UninitializeCacheMaps)
|
|
|
|
|
{
|
|
|
|
|
PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
if (!Map) return TRUE;
|
|
|
|
|
CcpFlushCache(Map, NULL, 0, NULL, TRUE);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
|
|
|
|
CcSetDirtyPageThreshold(IN PFILE_OBJECT FileObject,
|
|
|
|
|
IN ULONG DirtyPageThreshold)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
while (TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
|
|
|
|
CcZeroData(IN PFILE_OBJECT FileObject,
|
|
|
|
|
IN PLARGE_INTEGER StartOffset,
|
|
|
|
|
IN PLARGE_INTEGER EndOffset,
|
|
|
|
|
IN BOOLEAN Wait)
|
|
|
|
|
{
|
|
|
|
|
PNOCC_BCB Bcb = NULL;
|
|
|
|
|
PLIST_ENTRY ListEntry = NULL;
|
|
|
|
|
LARGE_INTEGER LowerBound = *StartOffset;
|
|
|
|
|
LARGE_INTEGER UpperBound = *EndOffset;
|
|
|
|
|
LARGE_INTEGER Target, End;
|
|
|
|
|
PVOID PinnedBcb, PinnedBuffer;
|
|
|
|
|
PNOCC_CACHE_MAP Map = FileObject->SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
|
|
|
|
|
DPRINT
|
|
|
|
|
("S %08x%08x E %08x%08x\n",
|
|
|
|
|
StartOffset->u.HighPart, StartOffset->u.LowPart,
|
|
|
|
|
EndOffset->u.HighPart, EndOffset->u.LowPart);
|
|
|
|
|
|
|
|
|
|
if (!Map)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
IO_STATUS_BLOCK IOSB;
|
|
|
|
|
PCHAR ZeroBuf = ExAllocatePool(PagedPool, PAGE_SIZE);
|
|
|
|
|
ULONG ToWrite;
|
|
|
|
|
|
|
|
|
|
if (!ZeroBuf) RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
|
DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, PAGE_SIZE);
|
|
|
|
|
RtlZeroMemory(ZeroBuf, PAGE_SIZE);
|
|
|
|
|
|
|
|
|
|
Target.QuadPart = PAGE_ROUND_DOWN(LowerBound.QuadPart);
|
|
|
|
|
End.QuadPart = PAGE_ROUND_UP(UpperBound.QuadPart);
|
|
|
|
|
|
|
|
|
|
// Handle leading page
|
|
|
|
|
if (LowerBound.QuadPart != Target.QuadPart)
|
|
|
|
|
{
|
|
|
|
|
ToWrite = MIN(UpperBound.QuadPart - LowerBound.QuadPart, (PAGE_SIZE - LowerBound.QuadPart) & (PAGE_SIZE - 1));
|
|
|
|
|
DPRINT("Zero last half %08x%08x %x\n", Target.u.HighPart, Target.u.LowPart, ToWrite);
|
|
|
|
|
Status = MiSimpleRead(FileObject, &Target, ZeroBuf, PAGE_SIZE, &IOSB);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ExFreePool(ZeroBuf);
|
|
|
|
|
RtlRaiseStatus(Status);
|
|
|
|
|
}
|
|
|
|
|
DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf + LowerBound.QuadPart - Target.QuadPart, ToWrite);
|
|
|
|
|
RtlZeroMemory(ZeroBuf + LowerBound.QuadPart - Target.QuadPart, ToWrite);
|
|
|
|
|
Status = MiSimpleWrite(FileObject, &Target, ZeroBuf, MIN(PAGE_SIZE,UpperBound.QuadPart-Target.QuadPart), &IOSB);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ExFreePool(ZeroBuf);
|
|
|
|
|
RtlRaiseStatus(Status);
|
|
|
|
|
}
|
|
|
|
|
Target.QuadPart += PAGE_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, PAGE_SIZE);
|
|
|
|
|
RtlZeroMemory(ZeroBuf, PAGE_SIZE);
|
|
|
|
|
|
|
|
|
|
while (UpperBound.QuadPart - Target.QuadPart > PAGE_SIZE)
|
|
|
|
|
{
|
|
|
|
|
DPRINT("Zero full page %08x%08x\n", Target.u.HighPart, Target.u.LowPart);
|
|
|
|
|
Status = MiSimpleWrite(FileObject, &Target, ZeroBuf, PAGE_SIZE, &IOSB);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ExFreePool(ZeroBuf);
|
|
|
|
|
RtlRaiseStatus(Status);
|
|
|
|
|
}
|
|
|
|
|
Target.QuadPart += PAGE_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (UpperBound.QuadPart > Target.QuadPart)
|
|
|
|
|
{
|
|
|
|
|
ToWrite = UpperBound.QuadPart - Target.QuadPart;
|
|
|
|
|
DPRINT("Zero first half %08x%08x %x\n", Target.u.HighPart, Target.u.LowPart, ToWrite);
|
|
|
|
|
Status = MiSimpleRead(FileObject, &Target, ZeroBuf, PAGE_SIZE, &IOSB);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ExFreePool(ZeroBuf);
|
|
|
|
|
RtlRaiseStatus(Status);
|
|
|
|
|
}
|
|
|
|
|
DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, ToWrite);
|
|
|
|
|
RtlZeroMemory(ZeroBuf, ToWrite);
|
|
|
|
|
Status = MiSimpleWrite(FileObject, &Target, ZeroBuf, MIN(PAGE_SIZE, UpperBound.QuadPart-Target.QuadPart), &IOSB);
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
ExFreePool(ZeroBuf);
|
|
|
|
|
RtlRaiseStatus(Status);
|
|
|
|
|
}
|
|
|
|
|
Target.QuadPart += PAGE_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExFreePool(ZeroBuf);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CcpLock();
|
|
|
|
|
ListEntry = Map->AssociatedBcb.Flink;
|
|
|
|
|
|
|
|
|
|
while (ListEntry != &Map->AssociatedBcb)
|
|
|
|
|
{
|
|
|
|
|
Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList);
|
|
|
|
|
CcpReferenceCache(Bcb - CcCacheSections);
|
|
|
|
|
|
|
|
|
|
if (Bcb->FileOffset.QuadPart + Bcb->Length >= LowerBound.QuadPart &&
|
|
|
|
|
Bcb->FileOffset.QuadPart < UpperBound.QuadPart)
|
|
|
|
|
{
|
|
|
|
|
DPRINT
|
|
|
|
|
("Bcb #%x (@%08x%08x)\n",
|
|
|
|
|
Bcb - CcCacheSections,
|
|
|
|
|
Bcb->FileOffset.u.HighPart, Bcb->FileOffset.u.LowPart);
|
|
|
|
|
|
|
|
|
|
Target.QuadPart = MAX(Bcb->FileOffset.QuadPart, LowerBound.QuadPart);
|
|
|
|
|
End.QuadPart = MIN(Map->FileSizes.ValidDataLength.QuadPart, UpperBound.QuadPart);
|
|
|
|
|
End.QuadPart = MIN(End.QuadPart, Bcb->FileOffset.QuadPart + Bcb->Length);
|
|
|
|
|
CcpUnlock();
|
|
|
|
|
|
|
|
|
|
if (!CcPreparePinWrite
|
|
|
|
|
(FileObject,
|
|
|
|
|
&Target,
|
|
|
|
|
End.QuadPart - Target.QuadPart,
|
|
|
|
|
TRUE,
|
|
|
|
|
Wait,
|
|
|
|
|
&PinnedBcb,
|
|
|
|
|
&PinnedBuffer))
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT(PinnedBcb == Bcb);
|
|
|
|
|
|
|
|
|
|
CcpLock();
|
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
|
// Return from pin state
|
2010-12-23 08:42:51 +00:00
|
|
|
|
CcpUnpinData(PinnedBcb, TRUE);
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-23 08:42:51 +00:00
|
|
|
|
CcpUnpinData(Bcb, TRUE);
|
[CACHE]
The cache manager rewrite I started years ago has finally appeared in
ReactOS' trunk and although at this point it's not quite perfectly
integrated, it's enough to boot up the bootcd or livecd. To check out
the more mature original, check out arty-newcc-reactos, branch
arty-newcc on bitbucket.org . Amine Khaldi encouraged me quite a bit
to not give up on it, and was able to reach out and be an advocate
when i really wasn't able to. Others agree that the time has come to
begin removing the old cache manager. I expect the remaining problems
in the version going to trunk will be taken care of relatively
quickly.
The motivation for this effort lies in the particularly hairy
relationship between ReactOS' cache manager and data sections. This
code completely removes page sharing between cache manager and section
and reimagines cache manager as being a facility layered on the memory
manager, not really caring about individual pages, but simply managing
data section objects where caching might occur.
It took me about 2 years to do the first pass of this rewrite and most
of this year to fix some lingering issues, properly implement demand
paging in ReactOS (code which didn't come with this patch in a
recognizable form), and finish getting the PrivateCacheMap and
SharedCacheMap relationship correct.
Currently, the new ntoskrnl/cache directory contains an own
implementation of data file sections. After things have settled down,
we can begin to deprecate and remove the parts of ReactOS' section
implementation that depend on a close relationship with cache
manager. Eventually, I think that the extra code added to
ntoskrnl/cache/section will be removed and ReactOS' own sections will
replace the use of the special MM_CACHE_SECTION_SEGMENT in the cache
path.
Note also, that this makes all cache manager (and new section parts)
use wide file offsets. If my section code were to take over other
parts of the ReactOS memory manager, they would also benefit from
these improvements.
I invite anyone who wants to to peek at this code and fix whatever
bugs can be found.
svn path=/trunk/; revision=49423
2010-11-02 02:32:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CcpUnlock();
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PFILE_OBJECT
|
|
|
|
|
NTAPI
|
|
|
|
|
CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointer)
|
|
|
|
|
{
|
|
|
|
|
PFILE_OBJECT Result = NULL;
|
|
|
|
|
PNOCC_CACHE_MAP Map = SectionObjectPointer->SharedCacheMap;
|
|
|
|
|
CcpLock();
|
|
|
|
|
if (!IsListEmpty(&Map->AssociatedBcb))
|
|
|
|
|
{
|
|
|
|
|
PNOCC_BCB Bcb = CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList);
|
|
|
|
|
Result = MmGetFileObjectForSection((PROS_SECTION_OBJECT)Bcb->SectionObject);
|
|
|
|
|
}
|
|
|
|
|
CcpUnlock();
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PFILE_OBJECT
|
|
|
|
|
NTAPI
|
|
|
|
|
CcGetFileObjectFromBcb(PVOID Bcb)
|
|
|
|
|
{
|
|
|
|
|
PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb;
|
|
|
|
|
DPRINT("BCB #%x\n", RealBcb - CcCacheSections);
|
|
|
|
|
return MmGetFileObjectForSection((PROS_SECTION_OBJECT)RealBcb->SectionObject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* EOF */
|