[NTOS:CC]

- Remove "VACB chain" optimization for CcCopyRead that was never applied anyway since MAX_RW_LENGTH == VACB_MAPPING_GRANULARITY, so a single read could never exceed one VACB
- Consolidate CcCopyRead, CcCopyWrite and the cached case of CcZeroData into a common worker function
CORE-8410

svn path=/trunk/; revision=63903
This commit is contained in:
Thomas Faber 2014-08-18 03:55:59 +00:00
parent 39d29c44d0
commit 1cc1113dc7
3 changed files with 193 additions and 512 deletions

View file

@ -18,8 +18,13 @@
static PFN_NUMBER CcZeroPage = 0;
#define MAX_ZERO_LENGTH (256 * 1024)
#define MAX_RW_LENGTH (256 * 1024)
C_ASSERT(MAX_RW_LENGTH <= VACB_MAPPING_GRANULARITY);
typedef enum _CC_COPY_OPERATION
{
CcOperationRead,
CcOperationWrite,
CcOperationZero
} CC_COPY_OPERATION;
ULONG CcFastMdlReadWait;
ULONG CcFastMdlReadNotPossible;
@ -54,136 +59,6 @@ CcInitCacheZeroPage (
MiZeroPhysicalPage(CcZeroPage);
}
NTSTATUS
NTAPI
ReadVacbChain (
PROS_SHARED_CACHE_MAP SharedCacheMap,
ULONG ReadOffset,
ULONG Length,
PVOID Buffer)
{
PROS_VACB head;
PROS_VACB current;
PROS_VACB previous;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
ULONG TempLength;
KEVENT Event;
PMDL Mdl;
Mdl = _alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH));
Status = CcRosGetVacbChain(SharedCacheMap, ReadOffset, Length, &head);
if (!NT_SUCCESS(Status))
{
return Status;
}
current = head;
while (current != NULL)
{
/*
* If the current VACB is valid then copy it into the user buffer.
*/
if (current->Valid)
{
TempLength = min(VACB_MAPPING_GRANULARITY, Length);
RtlCopyMemory(Buffer, current->BaseAddress, TempLength);
Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
Length = Length - TempLength;
previous = current;
current = current->NextInChain;
CcRosReleaseVacb(SharedCacheMap, previous, TRUE, FALSE, FALSE);
}
/*
* Otherwise read in as much as we can.
*/
else
{
PROS_VACB current2;
ULONG current_size;
ULONG i;
PPFN_NUMBER MdlPages;
/*
* Count the maximum number of bytes we could read starting
* from the current VACB.
*/
current2 = current;
current_size = 0;
while ((current2 != NULL) && !current2->Valid && (current_size < MAX_RW_LENGTH))
{
current2 = current2->NextInChain;
current_size += VACB_MAPPING_GRANULARITY;
}
/*
* Create an MDL which contains all their pages.
*/
MmInitializeMdl(Mdl, NULL, current_size);
Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
current2 = current;
current_size = 0;
MdlPages = (PPFN_NUMBER)(Mdl + 1);
while ((current2 != NULL) && !current2->Valid && (current_size < MAX_RW_LENGTH))
{
PVOID address = current2->BaseAddress;
for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++, address = RVA(address, PAGE_SIZE))
{
*MdlPages++ = MmGetPfnForProcess(NULL, address);
}
current2 = current2->NextInChain;
current_size += VACB_MAPPING_GRANULARITY;
}
/*
* Read in the information.
*/
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = IoPageRead(SharedCacheMap->FileObject,
Mdl,
&current->FileOffset,
&Event,
&Iosb);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = Iosb.Status;
}
if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
{
while (current != NULL)
{
previous = current;
current = current->NextInChain;
CcRosReleaseVacb(SharedCacheMap, previous, FALSE, FALSE, FALSE);
}
return Status;
}
current_size = 0;
while (current != NULL && !current->Valid && current_size < MAX_RW_LENGTH)
{
previous = current;
current = current->NextInChain;
TempLength = min(VACB_MAPPING_GRANULARITY, Length);
RtlCopyMemory(Buffer, previous->BaseAddress, TempLength);
Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
Length = Length - TempLength;
CcRosReleaseVacb(SharedCacheMap, previous, TRUE, FALSE, FALSE);
current_size += VACB_MAPPING_GRANULARITY;
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CcReadVirtualAddress (
@ -288,6 +163,170 @@ CcWriteVirtualAddress (
return STATUS_SUCCESS;
}
NTSTATUS
ReadWriteOrZero(
_Inout_ PVOID BaseAddress,
_Inout_opt_ PVOID Buffer,
_In_ ULONG Length,
_In_ CC_COPY_OPERATION Operation)
{
NTSTATUS Status = STATUS_SUCCESS;
if (Operation == CcOperationZero)
{
/* Zero */
RtlZeroMemory(BaseAddress, Length);
}
else
{
_SEH2_TRY
{
if (Operation == CcOperationWrite)
RtlCopyMemory(BaseAddress, Buffer, Length);
else
RtlCopyMemory(Buffer, BaseAddress, Length);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
}
return Status;
}
BOOLEAN
CcCopyData (
_In_ PFILE_OBJECT FileObject,
_In_ LONGLONG FileOffset,
_Inout_ PVOID Buffer,
_In_ ULONG Length,
_In_ CC_COPY_OPERATION Operation,
_In_ BOOLEAN Wait,
_Out_ PIO_STATUS_BLOCK IoStatus)
{
NTSTATUS Status;
LONGLONG CurrentOffset;
ULONG BytesCopied;
KIRQL OldIrql;
PROS_SHARED_CACHE_MAP SharedCacheMap;
PLIST_ENTRY ListEntry;
PROS_VACB Vacb;
ULONG PartialLength;
PVOID BaseAddress;
BOOLEAN Valid;
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
CurrentOffset = FileOffset;
BytesCopied = 0;
if (!Wait)
{
/* test if the requested data is available */
KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql);
/* FIXME: this loop doesn't take into account areas that don't have
* a VACB in the list yet */
ListEntry = SharedCacheMap->CacheMapVacbListHead.Flink;
while (ListEntry != &SharedCacheMap->CacheMapVacbListHead)
{
Vacb = CONTAINING_RECORD(ListEntry,
ROS_VACB,
CacheMapVacbListEntry);
ListEntry = ListEntry->Flink;
if (!Vacb->Valid &&
DoRangesIntersect(Vacb->FileOffset.QuadPart,
VACB_MAPPING_GRANULARITY,
CurrentOffset, Length))
{
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
/* data not available */
return FALSE;
}
if (Vacb->FileOffset.QuadPart >= CurrentOffset + Length)
break;
}
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql);
}
PartialLength = CurrentOffset % VACB_MAPPING_GRANULARITY;
if (PartialLength != 0)
{
PartialLength = min(Length, VACB_MAPPING_GRANULARITY - PartialLength);
Status = CcRosRequestVacb(SharedCacheMap,
ROUND_DOWN(CurrentOffset,
VACB_MAPPING_GRANULARITY),
&BaseAddress,
&Valid,
&Vacb);
if (!NT_SUCCESS(Status))
ExRaiseStatus(Status);
if (!Valid)
{
Status = CcReadVirtualAddress(Vacb);
if (!NT_SUCCESS(Status))
{
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
ExRaiseStatus(Status);
}
}
Status = ReadWriteOrZero((PUCHAR)BaseAddress + CurrentOffset % VACB_MAPPING_GRANULARITY,
Buffer,
PartialLength,
Operation);
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, Operation != CcOperationRead, FALSE);
if (!NT_SUCCESS(Status))
ExRaiseStatus(STATUS_INVALID_USER_BUFFER);
Length -= PartialLength;
CurrentOffset += PartialLength;
BytesCopied += PartialLength;
if (Buffer)
Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
}
while (Length > 0)
{
ASSERT(CurrentOffset % VACB_MAPPING_GRANULARITY == 0);
PartialLength = min(VACB_MAPPING_GRANULARITY, Length);
Status = CcRosRequestVacb(SharedCacheMap,
CurrentOffset,
&BaseAddress,
&Valid,
&Vacb);
if (!NT_SUCCESS(Status))
ExRaiseStatus(Status);
if (!Valid &&
(Operation == CcOperationRead ||
PartialLength < VACB_MAPPING_GRANULARITY))
{
Status = CcReadVirtualAddress(Vacb);
if (!NT_SUCCESS(Status))
{
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
ExRaiseStatus(Status);
}
}
Status = ReadWriteOrZero(BaseAddress, Buffer, PartialLength, Operation);
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, Operation != CcOperationRead, FALSE);
if (!NT_SUCCESS(Status))
ExRaiseStatus(STATUS_INVALID_USER_BUFFER);
Length -= PartialLength;
CurrentOffset += PartialLength;
BytesCopied += PartialLength;
if (Buffer)
Buffer = (PVOID)((ULONG_PTR)Buffer + PartialLength);
}
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = BytesCopied;
return TRUE;
}
/*
* @unimplemented
@ -304,7 +343,6 @@ CcCanIWrite (
return FALSE;
}
/*
* @implemented
*/
@ -318,121 +356,18 @@ CcCopyRead (
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus)
{
ULONG ReadOffset;
ULONG TempLength;
NTSTATUS Status = STATUS_SUCCESS;
PVOID BaseAddress;
PROS_VACB Vacb;
BOOLEAN Valid;
ULONG ReadLength = 0;
PROS_SHARED_CACHE_MAP SharedCacheMap;
KIRQL oldirql;
PLIST_ENTRY current_entry;
PROS_VACB current;
DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
"Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
FileObject, FileOffset->QuadPart, Length, Wait,
Buffer, IoStatus);
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
ReadOffset = (ULONG)FileOffset->QuadPart;
DPRINT("SectionSize %I64d, FileSize %I64d\n",
SharedCacheMap->SectionSize.QuadPart,
SharedCacheMap->FileSize.QuadPart);
/*
* Check for the nowait case that all the cache VACBs that would
* cover this read are in memory.
*/
if (!Wait)
{
KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
/* FIXME: this loop doesn't take into account areas that don't have
* a VACB in the list yet */
current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
{
current = CONTAINING_RECORD(current_entry,
ROS_VACB,
CacheMapVacbListEntry);
if (!current->Valid &&
DoRangesIntersect(current->FileOffset.QuadPart,
VACB_MAPPING_GRANULARITY,
ReadOffset, Length))
{
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
IoStatus->Status = STATUS_UNSUCCESSFUL;
IoStatus->Information = 0;
return FALSE;
}
if (current->FileOffset.QuadPart >= ReadOffset + Length)
break;
current_entry = current_entry->Flink;
}
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
}
TempLength = ReadOffset % VACB_MAPPING_GRANULARITY;
if (TempLength != 0)
{
TempLength = min(Length, VACB_MAPPING_GRANULARITY - TempLength);
Status = CcRosRequestVacb(SharedCacheMap,
ROUND_DOWN(ReadOffset,
VACB_MAPPING_GRANULARITY),
&BaseAddress, &Valid, &Vacb);
if (!NT_SUCCESS(Status))
{
IoStatus->Information = 0;
IoStatus->Status = Status;
DPRINT("CcRosRequestVacb failed, Status %x\n", Status);
return FALSE;
}
if (!Valid)
{
Status = CcReadVirtualAddress(Vacb);
if (!NT_SUCCESS(Status))
{
IoStatus->Information = 0;
IoStatus->Status = Status;
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
return FALSE;
}
}
RtlCopyMemory(Buffer,
(char*)BaseAddress + ReadOffset % VACB_MAPPING_GRANULARITY,
TempLength);
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, FALSE, FALSE);
ReadLength += TempLength;
Length -= TempLength;
ReadOffset += TempLength;
Buffer = (PVOID)((char*)Buffer + TempLength);
}
while (Length > 0)
{
TempLength = min(VACB_MAPPING_GRANULARITY, Length);
Status = ReadVacbChain(SharedCacheMap, ReadOffset, TempLength, Buffer);
if (!NT_SUCCESS(Status))
{
IoStatus->Information = 0;
IoStatus->Status = Status;
DPRINT("ReadVacbChain failed, Status %x\n", Status);
return FALSE;
}
ReadLength += TempLength;
Length -= TempLength;
ReadOffset += TempLength;
Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
}
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = ReadLength;
DPRINT("CcCopyRead O.K.\n");
return TRUE;
return CcCopyData(FileObject,
FileOffset->QuadPart,
Buffer,
Length,
CcOperationRead,
Wait,
IoStatus);
}
/*
@ -447,109 +382,19 @@ CcCopyWrite (
IN BOOLEAN Wait,
IN PVOID Buffer)
{
NTSTATUS Status;
ULONG WriteOffset;
KIRQL oldirql;
PROS_SHARED_CACHE_MAP SharedCacheMap;
PLIST_ENTRY current_entry;
PROS_VACB Vacb;
ULONG TempLength;
PVOID BaseAddress;
BOOLEAN Valid;
IO_STATUS_BLOCK IoStatus;
DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
"Length %lu, Wait %u, Buffer 0x%p)\n",
FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
WriteOffset = (ULONG)FileOffset->QuadPart;
if (!Wait)
{
/* testing, if the requested datas are available */
KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
/* FIXME: this loop doesn't take into account areas that don't have
* a VACB in the list yet */
current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
{
Vacb = CONTAINING_RECORD(current_entry,
ROS_VACB,
CacheMapVacbListEntry);
if (!Vacb->Valid &&
DoRangesIntersect(Vacb->FileOffset.QuadPart,
VACB_MAPPING_GRANULARITY,
WriteOffset, Length))
{
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
/* datas not available */
return FALSE;
}
if (Vacb->FileOffset.QuadPart >= WriteOffset + Length)
break;
current_entry = current_entry->Flink;
}
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
}
TempLength = WriteOffset % VACB_MAPPING_GRANULARITY;
if (TempLength != 0)
{
ULONG ROffset;
ROffset = ROUND_DOWN(WriteOffset, VACB_MAPPING_GRANULARITY);
TempLength = min(Length, VACB_MAPPING_GRANULARITY - TempLength);
Status = CcRosRequestVacb(SharedCacheMap, ROffset,
&BaseAddress, &Valid, &Vacb);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
if (!Valid)
{
if (!NT_SUCCESS(CcReadVirtualAddress(Vacb)))
{
return FALSE;
}
}
RtlCopyMemory((char*)BaseAddress + WriteOffset % VACB_MAPPING_GRANULARITY,
return CcCopyData(FileObject,
FileOffset->QuadPart,
Buffer,
TempLength);
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, TRUE, FALSE);
Length -= TempLength;
WriteOffset += TempLength;
Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
}
while (Length > 0)
{
TempLength = min(VACB_MAPPING_GRANULARITY, Length);
Status = CcRosRequestVacb(SharedCacheMap,
WriteOffset,
&BaseAddress,
&Valid,
&Vacb);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
if (!Valid && TempLength < VACB_MAPPING_GRANULARITY)
{
if (!NT_SUCCESS(CcReadVirtualAddress(Vacb)))
{
CcRosReleaseVacb(SharedCacheMap, Vacb, FALSE, FALSE, FALSE);
return FALSE;
}
}
RtlCopyMemory(BaseAddress, Buffer, TempLength);
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, TRUE, FALSE);
Length -= TempLength;
WriteOffset += TempLength;
Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
}
return TRUE;
Length,
CcOperationWrite,
Wait,
&IoStatus);
}
/*
@ -679,102 +524,15 @@ CcZeroData (
}
else
{
/* File is cached */
KIRQL oldirql;
PROS_SHARED_CACHE_MAP SharedCacheMap;
PLIST_ENTRY current_entry;
PROS_VACB Vacb, current, previous;
ULONG TempLength;
IO_STATUS_BLOCK IoStatus;
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
if (!Wait)
{
/* testing, if the requested datas are available */
KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
/* FIXME: this loop doesn't take into account areas that don't have
* a VACB in the list yet */
current_entry = SharedCacheMap->CacheMapVacbListHead.Flink;
while (current_entry != &SharedCacheMap->CacheMapVacbListHead)
{
Vacb = CONTAINING_RECORD(current_entry,
ROS_VACB,
CacheMapVacbListEntry);
if (!Vacb->Valid &&
DoRangesIntersect(Vacb->FileOffset.QuadPart,
VACB_MAPPING_GRANULARITY,
WriteOffset.u.LowPart, Length))
{
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
/* datas not available */
return FALSE;
}
if (Vacb->FileOffset.QuadPart >= WriteOffset.u.LowPart + Length)
break;
current_entry = current_entry->Flink;
}
KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldirql);
}
while (Length > 0)
{
ULONG Offset;
Offset = WriteOffset.u.LowPart % VACB_MAPPING_GRANULARITY;
if (Length + Offset > MAX_ZERO_LENGTH)
{
CurrentLength = MAX_ZERO_LENGTH - Offset;
}
else
{
CurrentLength = Length;
}
Status = CcRosGetVacbChain(SharedCacheMap, WriteOffset.u.LowPart - Offset,
Offset + CurrentLength, &Vacb);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
current = Vacb;
while (current != NULL)
{
Offset = WriteOffset.u.LowPart % VACB_MAPPING_GRANULARITY;
if ((Offset != 0) ||
(Offset + CurrentLength < VACB_MAPPING_GRANULARITY))
{
if (!current->Valid)
{
/* read the block */
Status = CcReadVirtualAddress(current);
if (!NT_SUCCESS(Status))
{
DPRINT1("CcReadVirtualAddress failed, status %x\n",
Status);
}
}
TempLength = min(CurrentLength, VACB_MAPPING_GRANULARITY - Offset);
}
else
{
TempLength = VACB_MAPPING_GRANULARITY;
}
RtlZeroMemory((PUCHAR)current->BaseAddress + Offset,
TempLength);
WriteOffset.QuadPart += TempLength;
CurrentLength -= TempLength;
Length -= TempLength;
current = current->NextInChain;
}
current = Vacb;
while (current != NULL)
{
previous = current;
current = current->NextInChain;
CcRosReleaseVacb(SharedCacheMap, previous, TRUE, TRUE, FALSE);
}
}
return CcCopyData(FileObject,
WriteOffset.QuadPart,
NULL,
Length,
CcOperationZero,
Wait,
&IoStatus);
}
return TRUE;

View file

@ -725,73 +725,6 @@ CcRosCreateVacb (
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CcRosGetVacbChain (
PROS_SHARED_CACHE_MAP SharedCacheMap,
ULONG FileOffset,
ULONG Length,
PROS_VACB *Vacb)
{
PROS_VACB current;
ULONG i;
PROS_VACB *VacbList;
PROS_VACB Previous = NULL;
ASSERT(SharedCacheMap);
DPRINT("CcRosGetVacbChain()\n");
Length = ROUND_UP(Length, VACB_MAPPING_GRANULARITY);
VacbList = _alloca(sizeof(PROS_VACB) *
(Length / VACB_MAPPING_GRANULARITY));
/*
* Look for a VACB already mapping the same data.
*/
for (i = 0; i < (Length / VACB_MAPPING_GRANULARITY); i++)
{
ULONG CurrentOffset = FileOffset + (i * VACB_MAPPING_GRANULARITY);
current = CcRosLookupVacb(SharedCacheMap, CurrentOffset);
if (current != NULL)
{
KeAcquireGuardedMutex(&ViewLock);
/* Move to tail of LRU list */
RemoveEntryList(&current->VacbLruListEntry);
InsertTailList(&VacbLruListHead, &current->VacbLruListEntry);
KeReleaseGuardedMutex(&ViewLock);
VacbList[i] = current;
}
else
{
CcRosCreateVacb(SharedCacheMap, CurrentOffset, &current);
VacbList[i] = current;
}
}
for (i = 0; i < Length / VACB_MAPPING_GRANULARITY; i++)
{
if (i == 0)
{
*Vacb = VacbList[i];
Previous = VacbList[i];
}
else
{
Previous->NextInChain = VacbList[i];
Previous = VacbList[i];
}
}
ASSERT(Previous);
Previous->NextInChain = NULL;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CcRosGetVacb (

View file

@ -145,7 +145,6 @@ typedef struct _ROS_VACB
/* Pointer to the shared cache map for the file which this view maps data for. */
PROS_SHARED_CACHE_MAP SharedCacheMap;
/* Pointer to the next VACB in a chain. */
struct _ROS_VACB *NextInChain;
} ROS_VACB, *PROS_VACB;
typedef struct _INTERNAL_BCB
@ -223,15 +222,6 @@ CcRosLookupVacb(
ULONG FileOffset
);
NTSTATUS
NTAPI
CcRosGetVacbChain(
PROS_SHARED_CACHE_MAP SharedCacheMap,
ULONG FileOffset,
ULONG Length,
PROS_VACB *Vacb
);
VOID
NTAPI
CcInitCacheZeroPage(VOID);