mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
Modified some functions, changed the sequence for acquiring some of
the protection elements (VieLock, BcbLock, SegmentLock..) and protected the access to some elements with the associated locking element. Implemented CcFlushCache and CcGetFileObjectFromSectionPtrs. svn path=/trunk/; revision=3596
This commit is contained in:
parent
ef773a3f6b
commit
8aca0dc370
1 changed files with 375 additions and 223 deletions
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: view.c,v 1.52 2002/10/01 19:27:20 chorns Exp $
|
||||
/* $Id: view.c,v 1.53 2002/10/02 19:20:51 hbirr Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/cc/view.c
|
||||
|
@ -78,7 +78,7 @@ static FAST_MUTEX ViewLock;
|
|||
void * alloca(size_t size);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
CcRosInternalFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg);
|
||||
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
@ -86,11 +86,17 @@ NTSTATUS STATIC
|
|||
CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KIRQL oldIrql;
|
||||
Status = WriteCacheSegment(CacheSegment);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
KeAcquireSpinLock(&CacheSegment->Bcb->BcbLock, &oldIrql);
|
||||
CacheSegment->Dirty = FALSE;
|
||||
RemoveEntryList(&CacheSegment->DirtySegmentListEntry);
|
||||
CacheSegment->ReferenceCount--;
|
||||
KeReleaseSpinLock(&CacheSegment->Bcb->BcbLock, oldIrql);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
@ -121,24 +127,24 @@ CcRosFlushDirtyPages(ULONG Target, PULONG Count)
|
|||
continue;
|
||||
}
|
||||
assert(current->Dirty);
|
||||
if (current->ReferenceCount > 0)
|
||||
if (current->ReferenceCount > 1)
|
||||
{
|
||||
ExReleaseFastMutex(¤t->Lock);
|
||||
continue;
|
||||
}
|
||||
current->ReferenceCount++;
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
|
||||
Status = CcRosFlushCacheSegment(current);
|
||||
current->ReferenceCount--;
|
||||
ExReleaseFastMutex(¤t->Lock);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CC: Failed to flush cache segment.\n");
|
||||
}
|
||||
(*Count) += PagesPerSegment;
|
||||
Target -= PagesPerSegment;
|
||||
|
||||
{
|
||||
DPRINT1("CC: Failed to flush cache segment.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
(*Count) += PagesPerSegment;
|
||||
Target -= PagesPerSegment;
|
||||
}
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
current_entry = DirtySegmentListHead.Flink;
|
||||
}
|
||||
|
@ -162,12 +168,15 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
|||
PCACHE_SEGMENT current;
|
||||
ULONG PagesPerSegment;
|
||||
ULONG PagesFreed;
|
||||
BOOLEAN Locked;
|
||||
KIRQL oldIrql;
|
||||
LIST_ENTRY FreeList;
|
||||
|
||||
DPRINT("CcRosTrimCache(Target %d)\n", Target);
|
||||
|
||||
*NrFreed = 0;
|
||||
|
||||
|
||||
InitializeListHead(&FreeList);
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
current_entry = CacheSegmentLRUListHead.Flink;
|
||||
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
|
||||
|
@ -175,28 +184,35 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
|||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||
CacheSegmentLRUListEntry);
|
||||
current_entry = current_entry->Flink;
|
||||
Locked = ExTryToAcquireFastMutex(¤t->Lock);
|
||||
if (!Locked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (current->MappedCount > 0 || current->Dirty ||
|
||||
current->ReferenceCount > 0)
|
||||
{
|
||||
ExReleaseFastMutex(¤t->Lock);
|
||||
continue;
|
||||
}
|
||||
ExReleaseFastMutex(¤t->Lock);
|
||||
DPRINT("current->Bcb->CacheSegmentSize %d\n",
|
||||
current->Bcb->CacheSegmentSize);
|
||||
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
|
||||
CcRosInternalFreeCacheSegment(current->Bcb, current);
|
||||
DPRINT("CcRosTrimCache(): Freed %d\n", PagesPerSegment);
|
||||
PagesFreed = min(PagesPerSegment, Target);
|
||||
Target = Target - PagesFreed;
|
||||
(*NrFreed) = (*NrFreed) + PagesFreed;
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql);
|
||||
if (current->ReferenceCount == 0)
|
||||
{
|
||||
RemoveEntryList(¤t->BcbSegmentListEntry);
|
||||
KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
|
||||
RemoveEntryList(¤t->CacheSegmentListEntry);
|
||||
RemoveEntryList(¤t->CacheSegmentLRUListEntry);
|
||||
InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
|
||||
}
|
||||
}
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
|
||||
while (!IsListEmpty(&FreeList))
|
||||
{
|
||||
current_entry = RemoveHeadList(&FreeList);
|
||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||
BcbSegmentListEntry);
|
||||
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
|
||||
PagesFreed = min(PagesPerSegment, Target);
|
||||
Target -= PagesFreed;
|
||||
(*NrFreed) += PagesFreed;
|
||||
CcRosInternalFreeCacheSegment(current);
|
||||
}
|
||||
|
||||
DPRINT("CcRosTrimCache() finished\n");
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -209,29 +225,39 @@ CcRosReleaseCacheSegment(PBCB Bcb,
|
|||
BOOLEAN Mapped)
|
||||
{
|
||||
BOOLEAN WasDirty = CacheSeg->Dirty;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcReleaseCachePage(Bcb %x, CacheSeg %x, Valid %d)\n",
|
||||
DPRINT("CcReleaseCacheSegment(Bcb %x, CacheSeg %x, Valid %d)\n",
|
||||
Bcb, CacheSeg, Valid);
|
||||
|
||||
|
||||
CacheSeg->Valid = Valid;
|
||||
CacheSeg->Dirty = CacheSeg->Dirty || Dirty;
|
||||
if (Mapped)
|
||||
{
|
||||
CacheSeg->MappedCount++;
|
||||
}
|
||||
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
if (!WasDirty && CacheSeg->Dirty)
|
||||
{
|
||||
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
|
||||
}
|
||||
RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
|
||||
InsertTailList(&CacheSegmentLRUListHead,
|
||||
&CacheSeg->CacheSegmentLRUListEntry);
|
||||
InsertTailList(&CacheSegmentLRUListHead, &CacheSeg->CacheSegmentLRUListEntry);
|
||||
|
||||
if (Mapped)
|
||||
{
|
||||
CacheSeg->MappedCount++;
|
||||
}
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
CacheSeg->ReferenceCount--;
|
||||
if (Mapped && CacheSeg->MappedCount == 1)
|
||||
{
|
||||
CacheSeg->ReferenceCount++;
|
||||
}
|
||||
if (!WasDirty && CacheSeg->Dirty)
|
||||
{
|
||||
CacheSeg->ReferenceCount++;
|
||||
}
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
InterlockedDecrement(&CacheSeg->ReferenceCount);
|
||||
|
||||
DPRINT("CcReleaseCachePage() finished\n");
|
||||
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -242,6 +268,8 @@ PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
|
|||
PCACHE_SEGMENT current;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcRosLookupCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
|
||||
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||
while (current_entry != &Bcb->BcbSegmentListHead)
|
||||
|
@ -251,6 +279,7 @@ PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
|
|||
if (current->FileOffset <= FileOffset &&
|
||||
(current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
|
||||
{
|
||||
current->ReferenceCount++;
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
return(current);
|
||||
}
|
||||
|
@ -264,8 +293,10 @@ NTSTATUS
|
|||
CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset)
|
||||
{
|
||||
PCACHE_SEGMENT CacheSeg;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcRosMarkDirtyCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
|
||||
if (CacheSeg == NULL)
|
||||
{
|
||||
|
@ -274,40 +305,21 @@ CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset)
|
|||
ExAcquireFastMutex(&CacheSeg->Lock);
|
||||
if (!CacheSeg->Dirty)
|
||||
{
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
CacheSeg->ReferenceCount--;
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
}
|
||||
|
||||
|
||||
CacheSeg->Dirty = TRUE;
|
||||
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CcRosSuggestFreeCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
|
||||
{
|
||||
PCACHE_SEGMENT CacheSeg;
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
|
||||
if (CacheSeg == NULL)
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
ExAcquireFastMutex(&CacheSeg->Lock);
|
||||
if (CacheSeg->MappedCount > 0)
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
CacheSeg->Dirty = CacheSeg->Dirty || NowDirty;
|
||||
if (CacheSeg->Dirty || CacheSeg->ReferenceCount > 0)
|
||||
{
|
||||
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||
CcRosInternalFreeCacheSegment(CacheSeg->Bcb, CacheSeg);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -315,20 +327,43 @@ NTSTATUS
|
|||
CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
|
||||
{
|
||||
PCACHE_SEGMENT CacheSeg;
|
||||
BOOLEAN WasDirty;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcRosUnmapCacheSegment(Bcb %x, FileOffset %d, NowDirty %d)\n",
|
||||
Bcb, FileOffset, NowDirty);
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
|
||||
if (CacheSeg == NULL)
|
||||
{
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
CacheSeg->ReferenceCount++;
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
ExAcquireFastMutex(&CacheSeg->Lock);
|
||||
CacheSeg->MappedCount--;
|
||||
|
||||
WasDirty = CacheSeg->Dirty;
|
||||
CacheSeg->Dirty = CacheSeg->Dirty || NowDirty;
|
||||
|
||||
CacheSeg->MappedCount--;
|
||||
|
||||
if (!WasDirty && NowDirty)
|
||||
{
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
CacheSeg->ReferenceCount--;
|
||||
if (!WasDirty && NowDirty)
|
||||
{
|
||||
CacheSeg->ReferenceCount++;
|
||||
}
|
||||
if (CacheSeg->MappedCount == 0)
|
||||
{
|
||||
CacheSeg->ReferenceCount--;
|
||||
}
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
|
||||
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -341,15 +376,66 @@ CcRosCreateCacheSegment(PBCB Bcb,
|
|||
{
|
||||
ULONG i;
|
||||
PCACHE_SEGMENT current;
|
||||
PLIST_ENTRY current_entry;
|
||||
NTSTATUS Status;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcRosCreateCacheSegment()\n");
|
||||
|
||||
current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT),
|
||||
TAG_CSEG);
|
||||
TAG_CSEG);
|
||||
current->Valid = FALSE;
|
||||
current->Dirty = FALSE;
|
||||
current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize);
|
||||
current->Bcb = Bcb;
|
||||
current->MappedCount = 0;
|
||||
current->DirtySegmentListEntry.Flink = NULL;
|
||||
current->DirtySegmentListEntry.Blink = NULL;
|
||||
current->ReferenceCount = 1;
|
||||
ExInitializeFastMutex(¤t->Lock);
|
||||
ExAcquireFastMutex(¤t->Lock);
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
|
||||
*CacheSeg = current;
|
||||
/* There is window between the call to CcRosLookupCacheSegment
|
||||
* and CcRosCreateCacheSegment. We must check if a segment on
|
||||
* the fileoffset exist. If there exist a segment, we release
|
||||
* our new created segment and return the existing one.
|
||||
*/
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||
while (current_entry != &Bcb->BcbSegmentListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||
BcbSegmentListEntry);
|
||||
if (current->FileOffset <= FileOffset &&
|
||||
(current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
|
||||
{
|
||||
current->ReferenceCount++;
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
ExReleaseFastMutex(&(*CacheSeg)->Lock);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
ExFreePool(*CacheSeg);
|
||||
*CacheSeg = current;
|
||||
if (Lock)
|
||||
{
|
||||
ExAcquireFastMutex(¤t->Lock);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
/* There was no existing segment. */
|
||||
current = *CacheSeg;
|
||||
InsertTailList(&Bcb->BcbSegmentListHead, ¤t->BcbSegmentListEntry);
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry);
|
||||
InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
current->BaseAddress = NULL;
|
||||
Status = MmCreateMemoryArea(KernelMode,
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_CACHE_SEGMENT,
|
||||
¤t->BaseAddress,
|
||||
|
@ -357,53 +443,36 @@ CcRosCreateCacheSegment(PBCB Bcb,
|
|||
PAGE_READWRITE,
|
||||
(PMEMORY_AREA*)¤t->MemoryArea,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
KeBugCheck(0);
|
||||
}
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
current->Valid = FALSE;
|
||||
current->Dirty = FALSE;
|
||||
current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize);
|
||||
current->Bcb = Bcb;
|
||||
current->MappedCount = 0;
|
||||
ExInitializeFastMutex(¤t->Lock);
|
||||
current->ReferenceCount = 1;
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
InsertTailList(&Bcb->BcbSegmentListHead, ¤t->BcbSegmentListEntry);
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry);
|
||||
InsertTailList(&CacheSegmentLRUListHead,
|
||||
¤t->CacheSegmentLRUListEntry);
|
||||
current->DirtySegmentListEntry.Flink =
|
||||
current->DirtySegmentListEntry.Blink = NULL;
|
||||
if (Lock)
|
||||
{
|
||||
ExAcquireFastMutex(¤t->Lock);
|
||||
}
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
|
||||
{
|
||||
PHYSICAL_ADDRESS Page;
|
||||
{
|
||||
PHYSICAL_ADDRESS Page;
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
current->BaseAddress + (i * PAGE_SIZE),
|
||||
PAGE_READWRITE,
|
||||
Page,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
*CacheSeg = current;
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
current->BaseAddress + (i * PAGE_SIZE),
|
||||
PAGE_READWRITE,
|
||||
Page,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
if (!Lock)
|
||||
{
|
||||
ExReleaseFastMutex(¤t->Lock);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -418,16 +487,13 @@ CcRosGetCacheSegmentChain(PBCB Bcb,
|
|||
PCACHE_SEGMENT* CacheSegList;
|
||||
PCACHE_SEGMENT Previous = NULL;
|
||||
|
||||
DPRINT("CcRosGetCacheSegmentChain()\n");
|
||||
|
||||
Length = ROUND_UP(Length, Bcb->CacheSegmentSize);
|
||||
|
||||
CacheSegList = alloca(sizeof(PCACHE_SEGMENT) *
|
||||
(Length / Bcb->CacheSegmentSize));
|
||||
|
||||
/*
|
||||
* Acquire the global lock.
|
||||
*/
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
|
||||
/*
|
||||
* Look for a cache segment already mapping the same data.
|
||||
*/
|
||||
|
@ -437,20 +503,14 @@ CcRosGetCacheSegmentChain(PBCB Bcb,
|
|||
current = CcRosLookupCacheSegment(Bcb, CurrentOffset);
|
||||
if (current != NULL)
|
||||
{
|
||||
/*
|
||||
* Make sure the cache segment can't go away outside of our control.
|
||||
*/
|
||||
current->ReferenceCount++;
|
||||
CacheSegList[i] = current;
|
||||
}
|
||||
else
|
||||
{
|
||||
CcRosCreateCacheSegment(Bcb, CurrentOffset, ¤t, FALSE);
|
||||
CacheSegList[i] = current;
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
}
|
||||
}
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
|
||||
for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++)
|
||||
{
|
||||
|
@ -482,47 +542,31 @@ CcRosGetCacheSegment(PBCB Bcb,
|
|||
PCACHE_SEGMENT current;
|
||||
NTSTATUS Status;
|
||||
|
||||
/*
|
||||
* Acquire the global lock.
|
||||
*/
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
DPRINT("CcRosGetCacheSegment()\n");
|
||||
|
||||
/*
|
||||
* Look for a cache segment already mapping the same data.
|
||||
*/
|
||||
current = CcRosLookupCacheSegment(Bcb, FileOffset);
|
||||
if (current != NULL)
|
||||
{
|
||||
/*
|
||||
* Make sure the cache segment can't go away outside of our control.
|
||||
*/
|
||||
current->ReferenceCount++;
|
||||
/*
|
||||
* Release the global lock and lock the cache segment.
|
||||
*/
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
ExAcquireFastMutex(¤t->Lock);
|
||||
/*
|
||||
* Return information about the segment to the caller.
|
||||
*/
|
||||
*UptoDate = current->Valid;
|
||||
*BaseAddress = current->BaseAddress;
|
||||
DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress);
|
||||
*CacheSeg = current;
|
||||
*BaseOffset = current->FileOffset;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
ExAcquireFastMutex(¤t->Lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Otherwise create a new segment.
|
||||
*/
|
||||
Status = CcRosCreateCacheSegment(Bcb, FileOffset, ¤t, TRUE);
|
||||
}
|
||||
/*
|
||||
* Otherwise create a new segment.
|
||||
* Return information about the segment to the caller.
|
||||
*/
|
||||
Status = CcRosCreateCacheSegment(Bcb, FileOffset, ¤t, TRUE);
|
||||
*UptoDate = current->Valid;
|
||||
*BaseAddress = current->BaseAddress;
|
||||
DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress);
|
||||
*CacheSeg = current;
|
||||
*BaseOffset = current->FileOffset;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -537,7 +581,7 @@ CcRosRequestCacheSegment(PBCB Bcb,
|
|||
*/
|
||||
{
|
||||
ULONG BaseOffset;
|
||||
|
||||
|
||||
if ((FileOffset % Bcb->CacheSegmentSize) != 0)
|
||||
{
|
||||
CPRINT("Bad fileoffset %x should be multiple of %x",
|
||||
|
@ -565,19 +609,18 @@ CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
|||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
CcRosInternalFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
|
||||
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
|
||||
/*
|
||||
* FUNCTION: Releases a cache segment associated with a BCB
|
||||
*/
|
||||
{
|
||||
|
||||
DPRINT("Freeing cache segment %x\n", CacheSeg);
|
||||
RemoveEntryList(&CacheSeg->CacheSegmentListEntry);
|
||||
RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
|
||||
RemoveEntryList(&CacheSeg->BcbSegmentListEntry);
|
||||
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||
CacheSeg->BaseAddress,
|
||||
Bcb->CacheSegmentSize,
|
||||
CacheSeg->Bcb->CacheSegmentSize,
|
||||
CcFreeCachePage,
|
||||
NULL);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
@ -589,12 +632,101 @@ NTSTATUS STDCALL
|
|||
CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcRosFreeCacheSegment(Bcb %x, CacheSeg %x)\n",
|
||||
Bcb, CacheSeg);
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
Status = CcRosInternalFreeCacheSegment(Bcb, CacheSeg);
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
RemoveEntryList(&CacheSeg->BcbSegmentListEntry);
|
||||
RemoveEntryList(&CacheSeg->CacheSegmentListEntry);
|
||||
RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
|
||||
if (CacheSeg->Dirty)
|
||||
{
|
||||
RemoveEntryList(&CacheSeg->DirtySegmentListEntry);
|
||||
}
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
|
||||
Status = CcRosInternalFreeCacheSegment(CacheSeg);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
|
||||
IN PLARGE_INTEGER FileOffset OPTIONAL,
|
||||
IN ULONG Length,
|
||||
OUT PIO_STATUS_BLOCK IoStatus)
|
||||
{
|
||||
PBCB Bcb;
|
||||
LARGE_INTEGER Offset;
|
||||
PCACHE_SEGMENT current;
|
||||
NTSTATUS Status;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcFlushCache(SectionObjectPointers %x, FileOffset %x, Length %d, IoStatus %x)\n",
|
||||
SectionObjectPointers, FileOffset, Length, IoStatus);
|
||||
|
||||
if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
|
||||
{
|
||||
Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
|
||||
if (FileOffset)
|
||||
{
|
||||
Offset = *FileOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Offset.QuadPart = 0LL;
|
||||
Length = Bcb->FileSize.u.LowPart;
|
||||
}
|
||||
|
||||
if (IoStatus)
|
||||
{
|
||||
IoStatus->Status = STATUS_SUCCESS;
|
||||
IoStatus->Information = 0;
|
||||
}
|
||||
|
||||
while (Length > 0)
|
||||
{
|
||||
current = CcRosLookupCacheSegment (Bcb, Offset.u.LowPart);
|
||||
if (current != NULL)
|
||||
{
|
||||
ExAcquireFastMutex(¤t->Lock);
|
||||
if (current->Dirty)
|
||||
{
|
||||
Status = CcRosFlushCacheSegment(current);
|
||||
if (!NT_SUCCESS(Status) && IoStatus != NULL)
|
||||
{
|
||||
IoStatus->Status = Status;
|
||||
}
|
||||
}
|
||||
ExReleaseFastMutex(¤t->Lock);
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
current->ReferenceCount--;
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
}
|
||||
|
||||
Offset.QuadPart += Bcb->CacheSegmentSize;
|
||||
if (Length > Bcb->CacheSegmentSize)
|
||||
{
|
||||
Length -= Bcb->CacheSegmentSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IoStatus)
|
||||
{
|
||||
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
||||
/*
|
||||
|
@ -604,72 +736,77 @@ CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
|||
PLIST_ENTRY current_entry;
|
||||
PCACHE_SEGMENT current;
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY FreeList;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n", Bcb->FileObject,
|
||||
Bcb);
|
||||
DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n",
|
||||
Bcb->FileObject, Bcb);
|
||||
|
||||
MmFreeSectionSegments(Bcb->FileObject);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
|
||||
/*
|
||||
* Write back dirty cache segments.
|
||||
*/
|
||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||
while (current_entry != &Bcb->BcbSegmentListHead)
|
||||
{
|
||||
current =
|
||||
CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
|
||||
if (current->Dirty)
|
||||
CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL);
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
|
||||
if (Bcb->RefCount == 0)
|
||||
{
|
||||
MmFreeSectionSegments(Bcb->FileObject);
|
||||
|
||||
/*
|
||||
* Release all cache segments.
|
||||
*/
|
||||
InitializeListHead(&FreeList);
|
||||
|
||||
FileObject->SectionObjectPointers->SharedCacheMap = NULL;
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||
while (!IsListEmpty(&Bcb->BcbSegmentListHead))
|
||||
{
|
||||
current_entry = RemoveTailList(&Bcb->BcbSegmentListHead);
|
||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
|
||||
RemoveEntryList(¤t->CacheSegmentListEntry);
|
||||
RemoveEntryList(¤t->CacheSegmentLRUListEntry);
|
||||
if (current->Dirty)
|
||||
{
|
||||
Status = WriteCacheSegment(current);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to write cache segment (Status %X)\n", Status);
|
||||
}
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
RemoveEntryList(¤t->DirtySegmentListEntry);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
RemoveEntryList(¤t->DirtySegmentListEntry);
|
||||
}
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release all cache segments.
|
||||
*/
|
||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||
while (current_entry != &Bcb->BcbSegmentListHead)
|
||||
{
|
||||
current =
|
||||
CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
|
||||
current_entry = current_entry->Flink;
|
||||
CcRosFreeCacheSegment(Bcb, current);
|
||||
}
|
||||
FileObject->SectionObjectPointers->SharedCacheMap = NULL;
|
||||
ObDereferenceObject (Bcb->FileObject);
|
||||
ExFreePool(Bcb);
|
||||
InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
|
||||
|
||||
}
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
while (!IsListEmpty(&FreeList))
|
||||
{
|
||||
current_entry = RemoveTailList(&FreeList);
|
||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
|
||||
Status = CcRosInternalFreeCacheSegment(current);
|
||||
}
|
||||
|
||||
ObDereferenceObject (Bcb->FileObject);
|
||||
ExFreePool(Bcb);
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
VOID CcRosReferenceCache(PFILE_OBJECT FileObject)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PBCB Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
PBCB Bcb;
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
|
||||
Bcb->RefCount++;
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
}
|
||||
|
||||
VOID CcRosDereferenceCache(PFILE_OBJECT FileObject)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PBCB Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
PBCB Bcb;
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
|
||||
Bcb->RefCount--;
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
if (Bcb->RefCount == 0)
|
||||
{
|
||||
CcRosDeleteFileCache(FileObject, Bcb);
|
||||
}
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
|
@ -679,21 +816,21 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
|||
* has been closed.
|
||||
*/
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
|
||||
if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
|
||||
{
|
||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||
if (FileObject->PrivateCacheMap != NULL)
|
||||
{
|
||||
FileObject->PrivateCacheMap = NULL;
|
||||
Bcb->RefCount--;
|
||||
}
|
||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||
if (Bcb->RefCount == 0)
|
||||
{
|
||||
CcRosDeleteFileCache(FileObject, Bcb);
|
||||
}
|
||||
}
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -705,7 +842,11 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
|
|||
* FUNCTION: Initializes a BCB for a file object
|
||||
*/
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
DPRINT("CcRosInitializeFileCache(FileObject %x, *Bcb %x, CacheSegmentSize %d)\n",
|
||||
FileObject, Bcb, CacheSegmentSize);
|
||||
|
||||
ExAcquireFastMutex(&ViewLock);
|
||||
|
||||
if (*Bcb == NULL)
|
||||
{
|
||||
(*Bcb) = ExAllocatePoolWithTag(NonPagedPool, sizeof(BCB), TAG_BCB);
|
||||
|
@ -731,17 +872,28 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
|
|||
InitializeListHead(&(*Bcb)->BcbSegmentListHead);
|
||||
FileObject->SectionObjectPointers->SharedCacheMap = *Bcb;
|
||||
}
|
||||
KeAcquireSpinLock(&(*Bcb)->BcbLock, &oldIrql);
|
||||
if (FileObject->PrivateCacheMap == NULL)
|
||||
{
|
||||
FileObject->PrivateCacheMap = *Bcb;
|
||||
(*Bcb)->RefCount++;
|
||||
}
|
||||
KeReleaseSpinLock(&(*Bcb)->BcbLock, oldIrql);
|
||||
ExReleaseFastMutex(&ViewLock);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
PFILE_OBJECT STDCALL
|
||||
CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
|
||||
{
|
||||
PBCB Bcb;
|
||||
if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
|
||||
{
|
||||
Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
|
||||
return Bcb->FileObject;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
CcInitView(VOID)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue