mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 18:52:57 +00:00
[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:
parent
39d29c44d0
commit
1cc1113dc7
3 changed files with 193 additions and 512 deletions
|
@ -18,8 +18,13 @@
|
||||||
static PFN_NUMBER CcZeroPage = 0;
|
static PFN_NUMBER CcZeroPage = 0;
|
||||||
|
|
||||||
#define MAX_ZERO_LENGTH (256 * 1024)
|
#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 CcFastMdlReadWait;
|
||||||
ULONG CcFastMdlReadNotPossible;
|
ULONG CcFastMdlReadNotPossible;
|
||||||
|
@ -54,136 +59,6 @@ CcInitCacheZeroPage (
|
||||||
MiZeroPhysicalPage(CcZeroPage);
|
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,
|
|
||||||
¤t->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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CcReadVirtualAddress (
|
CcReadVirtualAddress (
|
||||||
|
@ -288,6 +163,170 @@ CcWriteVirtualAddress (
|
||||||
return STATUS_SUCCESS;
|
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
|
* @unimplemented
|
||||||
|
@ -304,7 +343,6 @@ CcCanIWrite (
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -318,121 +356,18 @@ CcCopyRead (
|
||||||
OUT PVOID Buffer,
|
OUT PVOID Buffer,
|
||||||
OUT PIO_STATUS_BLOCK IoStatus)
|
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, "
|
DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
|
||||||
"Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
|
"Length %lu, Wait %u, Buffer 0x%p, IoStatus 0x%p)\n",
|
||||||
FileObject, FileOffset->QuadPart, Length, Wait,
|
FileObject, FileOffset->QuadPart, Length, Wait,
|
||||||
Buffer, IoStatus);
|
Buffer, IoStatus);
|
||||||
|
|
||||||
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
return CcCopyData(FileObject,
|
||||||
ReadOffset = (ULONG)FileOffset->QuadPart;
|
FileOffset->QuadPart,
|
||||||
|
Buffer,
|
||||||
DPRINT("SectionSize %I64d, FileSize %I64d\n",
|
Length,
|
||||||
SharedCacheMap->SectionSize.QuadPart,
|
CcOperationRead,
|
||||||
SharedCacheMap->FileSize.QuadPart);
|
Wait,
|
||||||
|
IoStatus);
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -447,109 +382,19 @@ CcCopyWrite (
|
||||||
IN BOOLEAN Wait,
|
IN BOOLEAN Wait,
|
||||||
IN PVOID Buffer)
|
IN PVOID Buffer)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
ULONG WriteOffset;
|
|
||||||
KIRQL oldirql;
|
|
||||||
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
|
||||||
PLIST_ENTRY current_entry;
|
|
||||||
PROS_VACB Vacb;
|
|
||||||
ULONG TempLength;
|
|
||||||
PVOID BaseAddress;
|
|
||||||
BOOLEAN Valid;
|
|
||||||
|
|
||||||
DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
|
DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
|
||||||
"Length %lu, Wait %u, Buffer 0x%p)\n",
|
"Length %lu, Wait %u, Buffer 0x%p)\n",
|
||||||
FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
|
FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
|
||||||
|
|
||||||
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
return CcCopyData(FileObject,
|
||||||
WriteOffset = (ULONG)FileOffset->QuadPart;
|
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,
|
|
||||||
Buffer,
|
Buffer,
|
||||||
TempLength);
|
Length,
|
||||||
CcRosReleaseVacb(SharedCacheMap, Vacb, TRUE, TRUE, FALSE);
|
CcOperationWrite,
|
||||||
|
Wait,
|
||||||
Length -= TempLength;
|
&IoStatus);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -679,102 +524,15 @@ CcZeroData (
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* File is cached */
|
IO_STATUS_BLOCK IoStatus;
|
||||||
KIRQL oldirql;
|
|
||||||
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
|
||||||
PLIST_ENTRY current_entry;
|
|
||||||
PROS_VACB Vacb, current, previous;
|
|
||||||
ULONG TempLength;
|
|
||||||
|
|
||||||
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
return CcCopyData(FileObject,
|
||||||
if (!Wait)
|
WriteOffset.QuadPart,
|
||||||
{
|
NULL,
|
||||||
/* testing, if the requested datas are available */
|
Length,
|
||||||
KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &oldirql);
|
CcOperationZero,
|
||||||
/* FIXME: this loop doesn't take into account areas that don't have
|
Wait,
|
||||||
* a VACB in the list yet */
|
&IoStatus);
|
||||||
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 TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -725,73 +725,6 @@ CcRosCreateVacb (
|
||||||
return STATUS_SUCCESS;
|
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(¤t->VacbLruListEntry);
|
|
||||||
InsertTailList(&VacbLruListHead, ¤t->VacbLruListEntry);
|
|
||||||
|
|
||||||
KeReleaseGuardedMutex(&ViewLock);
|
|
||||||
|
|
||||||
VacbList[i] = current;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CcRosCreateVacb(SharedCacheMap, CurrentOffset, ¤t);
|
|
||||||
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
CcRosGetVacb (
|
CcRosGetVacb (
|
||||||
|
|
|
@ -145,7 +145,6 @@ typedef struct _ROS_VACB
|
||||||
/* Pointer to the shared cache map for the file which this view maps data for. */
|
/* Pointer to the shared cache map for the file which this view maps data for. */
|
||||||
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
PROS_SHARED_CACHE_MAP SharedCacheMap;
|
||||||
/* Pointer to the next VACB in a chain. */
|
/* Pointer to the next VACB in a chain. */
|
||||||
struct _ROS_VACB *NextInChain;
|
|
||||||
} ROS_VACB, *PROS_VACB;
|
} ROS_VACB, *PROS_VACB;
|
||||||
|
|
||||||
typedef struct _INTERNAL_BCB
|
typedef struct _INTERNAL_BCB
|
||||||
|
@ -223,15 +222,6 @@ CcRosLookupVacb(
|
||||||
ULONG FileOffset
|
ULONG FileOffset
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
CcRosGetVacbChain(
|
|
||||||
PROS_SHARED_CACHE_MAP SharedCacheMap,
|
|
||||||
ULONG FileOffset,
|
|
||||||
ULONG Length,
|
|
||||||
PROS_VACB *Vacb
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
CcInitCacheZeroPage(VOID);
|
CcInitCacheZeroPage(VOID);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue