mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
Present large reads to the filesystem from CcCopyRead
svn path=/trunk/; revision=2561
This commit is contained in:
parent
b51e21217f
commit
aebf70e07f
5 changed files with 420 additions and 201 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: copy.c,v 1.3 2001/12/29 14:32:21 dwelch Exp $
|
/* $Id: copy.c,v 1.4 2002/01/26 21:21:02 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -28,7 +28,120 @@
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
|
NTSTATUS
|
||||||
|
ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
|
||||||
|
PVOID Buffer)
|
||||||
|
{
|
||||||
|
PCACHE_SEGMENT head;
|
||||||
|
PCACHE_SEGMENT current;
|
||||||
|
PCACHE_SEGMENT previous;
|
||||||
|
IO_STATUS_BLOCK Iosb;
|
||||||
|
LARGE_INTEGER SegOffset;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG TempLength;
|
||||||
|
|
||||||
|
Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
current = head;
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If the current segment is valid then copy it into the
|
||||||
|
* user buffer.
|
||||||
|
*/
|
||||||
|
if (current->Valid)
|
||||||
|
{
|
||||||
|
TempLength = min(Bcb->CacheSegmentSize, Length);
|
||||||
|
memcpy(Buffer, current->BaseAddress, TempLength);
|
||||||
|
Buffer += TempLength;
|
||||||
|
Length = Length - TempLength;
|
||||||
|
previous = current;
|
||||||
|
current = current->NextInChain;
|
||||||
|
CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Otherwise read in a much as we can.
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PCACHE_SEGMENT current2;
|
||||||
|
ULONG current_size;
|
||||||
|
PMDL Mdl;
|
||||||
|
ULONG i;
|
||||||
|
ULONG offset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count the maximum number of bytes we could read starting
|
||||||
|
* from the current segment.
|
||||||
|
*/
|
||||||
|
current2 = current;
|
||||||
|
current_size = 0;
|
||||||
|
while (current2 != NULL && !current2->Valid)
|
||||||
|
{
|
||||||
|
current2 = current2->NextInChain;
|
||||||
|
current_size += Bcb->CacheSegmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an MDL which contains all their pages.
|
||||||
|
*/
|
||||||
|
Mdl = MmCreateMdl(NULL, NULL, current_size);
|
||||||
|
Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
|
||||||
|
current2 = current;
|
||||||
|
offset = 0;
|
||||||
|
while (current2 != NULL && !current2->Valid)
|
||||||
|
{
|
||||||
|
for (i = 0; i < (Bcb->CacheSegmentSize / PAGESIZE); i++)
|
||||||
|
{
|
||||||
|
PVOID address;
|
||||||
|
ULONG page;
|
||||||
|
address = current2->BaseAddress + (i * PAGESIZE);
|
||||||
|
page = MmGetPhysicalAddressForProcess(NULL, address);
|
||||||
|
((PULONG)(Mdl + 1))[offset] = page;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
current2 = current2->NextInChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read in the information.
|
||||||
|
*/
|
||||||
|
SegOffset.QuadPart = current->FileOffset;
|
||||||
|
Status = IoPageRead(Bcb->FileObject,
|
||||||
|
Mdl,
|
||||||
|
&SegOffset,
|
||||||
|
&Iosb,
|
||||||
|
TRUE);
|
||||||
|
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
|
||||||
|
{
|
||||||
|
while (current != NULL)
|
||||||
|
{
|
||||||
|
previous = current;
|
||||||
|
current = current->NextInChain;
|
||||||
|
CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
while (current != NULL && !current->Valid)
|
||||||
|
{
|
||||||
|
previous = current;
|
||||||
|
current = current->NextInChain;
|
||||||
|
TempLength = min(Bcb->CacheSegmentSize, Length);
|
||||||
|
memcpy(Buffer, previous->BaseAddress, TempLength);
|
||||||
|
Buffer += TempLength;
|
||||||
|
Length = Length - TempLength;
|
||||||
|
CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
|
||||||
{
|
{
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
|
@ -39,22 +152,24 @@ NTSTATUS ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
|
||||||
SegOffset.QuadPart = CacheSeg->FileOffset;
|
SegOffset.QuadPart = CacheSeg->FileOffset;
|
||||||
Size = CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset;
|
Size = CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset;
|
||||||
if (Size > CacheSeg->Bcb->CacheSegmentSize)
|
if (Size > CacheSeg->Bcb->CacheSegmentSize)
|
||||||
{
|
{
|
||||||
Size = CacheSeg->Bcb->CacheSegmentSize;
|
Size = CacheSeg->Bcb->CacheSegmentSize;
|
||||||
}
|
}
|
||||||
Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size);
|
Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size);
|
||||||
MmBuildMdlForNonPagedPool(Mdl);
|
MmBuildMdlForNonPagedPool(Mdl);
|
||||||
Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &IoStatus, TRUE);
|
Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &IoStatus,
|
||||||
|
TRUE);
|
||||||
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
|
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(CacheSeg->Bcb, CacheSeg, FALSE, FALSE, FALSE);
|
CcRosReleaseCacheSegment(CacheSeg->Bcb, CacheSeg, FALSE, FALSE, FALSE);
|
||||||
DPRINT1("IoPageRead failed, Status %x\n", Status);
|
DPRINT1("IoPageRead failed, Status %x\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
if (CacheSeg->Bcb->CacheSegmentSize > Size)
|
if (CacheSeg->Bcb->CacheSegmentSize > Size)
|
||||||
{
|
{
|
||||||
memset (CacheSeg->BaseAddress + Size, 0, CacheSeg->Bcb->CacheSegmentSize - Size);
|
memset (CacheSeg->BaseAddress + Size, 0,
|
||||||
}
|
CacheSeg->Bcb->CacheSegmentSize - Size);
|
||||||
|
}
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,123 +198,109 @@ NTSTATUS WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN STDCALL
|
BOOLEAN STDCALL
|
||||||
CcCopyRead (
|
CcCopyRead (IN PFILE_OBJECT FileObject,
|
||||||
IN PFILE_OBJECT FileObject,
|
IN PLARGE_INTEGER FileOffset,
|
||||||
IN PLARGE_INTEGER FileOffset,
|
IN ULONG Length,
|
||||||
IN ULONG Length,
|
IN BOOLEAN Wait,
|
||||||
IN BOOLEAN Wait,
|
OUT PVOID Buffer,
|
||||||
OUT PVOID Buffer,
|
OUT PIO_STATUS_BLOCK IoStatus)
|
||||||
OUT PIO_STATUS_BLOCK IoStatus)
|
|
||||||
{
|
{
|
||||||
ULONG ReadOffset;
|
ULONG ReadOffset;
|
||||||
ULONG TempLength;
|
ULONG TempLength;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
PCACHE_SEGMENT CacheSeg;
|
PCACHE_SEGMENT CacheSeg;
|
||||||
BOOLEAN Valid;
|
BOOLEAN Valid;
|
||||||
ULONG ReadLength = 0;
|
ULONG ReadLength = 0;
|
||||||
PBCB Bcb;
|
PBCB Bcb;
|
||||||
KIRQL oldirql;
|
KIRQL oldirql;
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
PCACHE_SEGMENT current;
|
PCACHE_SEGMENT current;
|
||||||
|
|
||||||
|
DPRINT("CcCopyRead(FileObject %x, FileOffset %x, "
|
||||||
|
"Length %d, Wait %d, Buffer %x, IoStatus %x)\n",
|
||||||
|
FileObject, (ULONG)FileOffset->QuadPart, Length, Wait,
|
||||||
|
Buffer, IoStatus);
|
||||||
|
|
||||||
DPRINT("CcCopyRead(FileObject %x, FileOffset %x, "
|
Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb;
|
||||||
"Length %d, Wait %d, Buffer %x, IoStatus %x)\n",
|
ReadOffset = FileOffset->QuadPart;
|
||||||
FileObject, (ULONG)FileOffset->QuadPart, Length, Wait,
|
|
||||||
Buffer, IoStatus);
|
DPRINT("AllocationSize %d, FileSize %d\n",
|
||||||
|
|
||||||
Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb;
|
|
||||||
ReadOffset = FileOffset->QuadPart;
|
|
||||||
|
|
||||||
DPRINT("AllocationSize %d, FileSize %d\n",
|
|
||||||
(ULONG)Bcb->AllocationSize.QuadPart,
|
(ULONG)Bcb->AllocationSize.QuadPart,
|
||||||
(ULONG)Bcb->FileSize.QuadPart);
|
(ULONG)Bcb->FileSize.QuadPart);
|
||||||
|
|
||||||
if (!Wait)
|
/*
|
||||||
{
|
* Check for the nowait case that all the cache segments that would
|
||||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
|
* cover this read are in memory.
|
||||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
*/
|
||||||
while (current_entry != &Bcb->BcbSegmentListHead)
|
if (!Wait)
|
||||||
{
|
{
|
||||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
|
KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
|
||||||
if (!current->Valid && current->FileOffset < ReadOffset + Length
|
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||||
&& current->FileOffset + Bcb->CacheSegmentSize > ReadOffset)
|
while (current_entry != &Bcb->BcbSegmentListHead)
|
||||||
{
|
{
|
||||||
KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
|
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||||
IoStatus->Status = STATUS_UNSUCCESSFUL;
|
BcbSegmentListEntry);
|
||||||
IoStatus->Information = 0;
|
if (!current->Valid && current->FileOffset < ReadOffset + Length
|
||||||
return FALSE;
|
&& current->FileOffset + Bcb->CacheSegmentSize > ReadOffset)
|
||||||
}
|
{
|
||||||
current_entry = current_entry->Flink;
|
KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
|
||||||
}
|
IoStatus->Status = STATUS_UNSUCCESSFUL;
|
||||||
KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
|
IoStatus->Information = 0;
|
||||||
}
|
return FALSE;
|
||||||
|
}
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
|
||||||
|
}
|
||||||
|
|
||||||
TempLength = ReadOffset % Bcb->CacheSegmentSize;
|
TempLength = ReadOffset % Bcb->CacheSegmentSize;
|
||||||
if (TempLength != 0)
|
if (TempLength != 0)
|
||||||
{
|
{
|
||||||
TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
|
TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
|
||||||
Status = CcRosRequestCacheSegment(Bcb,
|
Status = CcRosRequestCacheSegment(Bcb,
|
||||||
ROUND_DOWN(ReadOffset, Bcb->CacheSegmentSize),
|
ROUND_DOWN(ReadOffset,
|
||||||
&BaseAddress, &Valid, &CacheSeg);
|
Bcb->CacheSegmentSize),
|
||||||
if (!NT_SUCCESS(Status))
|
&BaseAddress, &Valid, &CacheSeg);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
IoStatus->Information = 0;
|
{
|
||||||
IoStatus->Status = Status;
|
IoStatus->Information = 0;
|
||||||
DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status);
|
IoStatus->Status = Status;
|
||||||
return FALSE;
|
DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status);
|
||||||
}
|
return FALSE;
|
||||||
if (!Valid)
|
}
|
||||||
{
|
if (!Valid)
|
||||||
Status = ReadCacheSegment(CacheSeg);
|
{
|
||||||
if (!NT_SUCCESS(Status))
|
Status = ReadCacheSegment(CacheSeg);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
IoStatus->Information = 0;
|
{
|
||||||
IoStatus->Status = Status;
|
IoStatus->Information = 0;
|
||||||
return FALSE;
|
IoStatus->Status = Status;
|
||||||
}
|
return FALSE;
|
||||||
}
|
}
|
||||||
memcpy (Buffer, BaseAddress + ReadOffset % Bcb->CacheSegmentSize, TempLength);
|
}
|
||||||
CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
|
memcpy (Buffer, BaseAddress + ReadOffset % Bcb->CacheSegmentSize,
|
||||||
ReadLength += TempLength;
|
TempLength);
|
||||||
Length -= TempLength;
|
CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
|
||||||
ReadOffset += TempLength;
|
ReadLength += TempLength;
|
||||||
Buffer += TempLength;
|
Length -= TempLength;
|
||||||
}
|
ReadOffset += TempLength;
|
||||||
|
Buffer += TempLength;
|
||||||
while (Length > 0)
|
}
|
||||||
{
|
|
||||||
TempLength = min (Bcb->CacheSegmentSize, Length);
|
while (Length > 0)
|
||||||
Status = CcRosRequestCacheSegment(Bcb, ReadOffset,
|
{
|
||||||
&BaseAddress, &Valid, &CacheSeg);
|
TempLength = min(max(Bcb->CacheSegmentSize, 65536), Length);
|
||||||
if (!NT_SUCCESS(Status))
|
ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer);
|
||||||
{
|
ReadLength += TempLength;
|
||||||
IoStatus->Information = 0;
|
Length -= TempLength;
|
||||||
IoStatus->Status = Status;
|
ReadOffset += TempLength;
|
||||||
DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status);
|
Buffer += TempLength;
|
||||||
return FALSE;
|
}
|
||||||
}
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
if (!Valid)
|
IoStatus->Information = ReadLength;
|
||||||
{
|
DPRINT("CcCopyRead O.K.\n");
|
||||||
Status = ReadCacheSegment(CacheSeg);
|
return TRUE;
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
IoStatus->Information = 0;
|
|
||||||
IoStatus->Status = Status;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memcpy (Buffer, BaseAddress, TempLength);
|
|
||||||
CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
|
|
||||||
ReadLength += TempLength;
|
|
||||||
Length -= TempLength;
|
|
||||||
ReadOffset += TempLength;
|
|
||||||
Buffer += TempLength;
|
|
||||||
}
|
|
||||||
IoStatus->Status = STATUS_SUCCESS;
|
|
||||||
IoStatus->Information = ReadLength;
|
|
||||||
DPRINT("CcCopyRead O.K.\n");
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN STDCALL
|
BOOLEAN STDCALL
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: view.c,v 1.35 2002/01/08 00:49:00 dwelch Exp $
|
/* $Id: view.c,v 1.36 2002/01/26 21:21:02 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -98,7 +98,8 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
||||||
current_entry = CacheSegmentLRUListHead.Flink;
|
current_entry = CacheSegmentLRUListHead.Flink;
|
||||||
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
|
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
|
||||||
{
|
{
|
||||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, CacheSegmentLRUListEntry);
|
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||||
|
CacheSegmentLRUListEntry);
|
||||||
current_entry = current_entry->Flink;
|
current_entry = current_entry->Flink;
|
||||||
Locked = ExTryToAcquireFastMutex(¤t->Lock);
|
Locked = ExTryToAcquireFastMutex(¤t->Lock);
|
||||||
if (!Locked)
|
if (!Locked)
|
||||||
|
@ -229,6 +230,144 @@ CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS STATIC
|
||||||
|
CcRosCreateCacheSegment(PBCB Bcb,
|
||||||
|
ULONG FileOffset,
|
||||||
|
PCACHE_SEGMENT* CacheSeg,
|
||||||
|
BOOLEAN Lock)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
PCACHE_SEGMENT current;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT),
|
||||||
|
TAG_CSEG);
|
||||||
|
|
||||||
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
current->BaseAddress = NULL;
|
||||||
|
Status = MmCreateMemoryArea(KernelMode,
|
||||||
|
MmGetKernelAddressSpace(),
|
||||||
|
MEMORY_AREA_CACHE_SEGMENT,
|
||||||
|
¤t->BaseAddress,
|
||||||
|
Bcb->CacheSegmentSize,
|
||||||
|
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);
|
||||||
|
for (i = 0; i < (Bcb->CacheSegmentSize / PAGESIZE); i++)
|
||||||
|
{
|
||||||
|
PVOID Page;
|
||||||
|
|
||||||
|
Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = MmCreateVirtualMapping(NULL,
|
||||||
|
current->BaseAddress + (i * PAGESIZE),
|
||||||
|
PAGE_READWRITE,
|
||||||
|
(ULONG)Page,
|
||||||
|
TRUE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*CacheSeg = current;
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CcRosGetCacheSegmentChain(PBCB Bcb,
|
||||||
|
ULONG FileOffset,
|
||||||
|
ULONG Length,
|
||||||
|
PCACHE_SEGMENT* CacheSeg)
|
||||||
|
{
|
||||||
|
PCACHE_SEGMENT current;
|
||||||
|
ULONG i;
|
||||||
|
PCACHE_SEGMENT* CacheSegList;
|
||||||
|
PCACHE_SEGMENT Previous;
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++)
|
||||||
|
{
|
||||||
|
ULONG CurrentOffset = FileOffset + (i * Bcb->CacheSegmentSize);
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
ExAcquireFastMutex(&CacheSegList[i]->Lock);
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
*CacheSeg = CacheSegList[i];
|
||||||
|
Previous = CacheSegList[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Previous->NextInChain = CacheSegList[i];
|
||||||
|
Previous = CacheSegList[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Previous->NextInChain = NULL;
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CcRosGetCacheSegment(PBCB Bcb,
|
CcRosGetCacheSegment(PBCB Bcb,
|
||||||
ULONG FileOffset,
|
ULONG FileOffset,
|
||||||
|
@ -238,9 +377,7 @@ CcRosGetCacheSegment(PBCB Bcb,
|
||||||
PCACHE_SEGMENT* CacheSeg)
|
PCACHE_SEGMENT* CacheSeg)
|
||||||
{
|
{
|
||||||
PCACHE_SEGMENT current;
|
PCACHE_SEGMENT current;
|
||||||
ULONG i;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Acquire the global lock.
|
* Acquire the global lock.
|
||||||
|
@ -267,6 +404,7 @@ CcRosGetCacheSegment(PBCB Bcb,
|
||||||
*/
|
*/
|
||||||
*UptoDate = current->Valid;
|
*UptoDate = current->Valid;
|
||||||
*BaseAddress = current->BaseAddress;
|
*BaseAddress = current->BaseAddress;
|
||||||
|
DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress);
|
||||||
*CacheSeg = current;
|
*CacheSeg = current;
|
||||||
*BaseOffset = current->FileOffset;
|
*BaseOffset = current->FileOffset;
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
|
@ -275,64 +413,13 @@ CcRosGetCacheSegment(PBCB Bcb,
|
||||||
/*
|
/*
|
||||||
* Otherwise create a new segment.
|
* Otherwise create a new segment.
|
||||||
*/
|
*/
|
||||||
current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT),
|
Status = CcRosCreateCacheSegment(Bcb, FileOffset, ¤t, TRUE);
|
||||||
TAG_CSEG);
|
|
||||||
|
|
||||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
|
||||||
current->BaseAddress = NULL;
|
|
||||||
Status = MmCreateMemoryArea(KernelMode,
|
|
||||||
MmGetKernelAddressSpace(),
|
|
||||||
MEMORY_AREA_CACHE_SEGMENT,
|
|
||||||
¤t->BaseAddress,
|
|
||||||
Bcb->CacheSegmentSize,
|
|
||||||
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;
|
|
||||||
ExAcquireFastMutex(¤t->Lock);
|
|
||||||
ExReleaseFastMutex(&ViewLock);
|
|
||||||
*UptoDate = current->Valid;
|
*UptoDate = current->Valid;
|
||||||
*BaseAddress = current->BaseAddress;
|
*BaseAddress = current->BaseAddress;
|
||||||
|
DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress);
|
||||||
*CacheSeg = current;
|
*CacheSeg = current;
|
||||||
*BaseOffset = current->FileOffset;
|
*BaseOffset = current->FileOffset;
|
||||||
for (i = 0; i < (Bcb->CacheSegmentSize / PAGESIZE); i++)
|
|
||||||
{
|
|
||||||
PVOID Page;
|
|
||||||
|
|
||||||
Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = MmCreateVirtualMapping(NULL,
|
|
||||||
current->BaseAddress + (i * PAGESIZE),
|
|
||||||
PAGE_READWRITE,
|
|
||||||
(ULONG)Page,
|
|
||||||
TRUE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,8 +451,8 @@ CcRosRequestCacheSegment(PBCB Bcb,
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC VOID
|
STATIC VOID
|
||||||
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
|
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
SWAPENTRY SwapEntry, BOOLEAN Dirty)
|
ULONG PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
assert(SwapEntry == 0);
|
assert(SwapEntry == 0);
|
||||||
if (PhysAddr != 0)
|
if (PhysAddr != 0)
|
||||||
|
@ -414,7 +501,8 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
PCACHE_SEGMENT current;
|
PCACHE_SEGMENT current;
|
||||||
|
|
||||||
DPRINT("CcRosReleaseFileCache(FileObject %x, Bcb %x)\n", Bcb->FileObject, Bcb);
|
DPRINT("CcRosReleaseFileCache(FileObject %x, Bcb %x)\n", Bcb->FileObject,
|
||||||
|
Bcb);
|
||||||
|
|
||||||
MmFreeSectionSegments(Bcb->FileObject);
|
MmFreeSectionSegments(Bcb->FileObject);
|
||||||
|
|
||||||
|
@ -460,7 +548,8 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
|
||||||
{
|
{
|
||||||
(*Bcb)->AllocationSize =
|
(*Bcb)->AllocationSize =
|
||||||
((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize;
|
((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize;
|
||||||
(*Bcb)->FileSize = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize;
|
(*Bcb)->FileSize =
|
||||||
|
((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize;
|
||||||
}
|
}
|
||||||
KeInitializeSpinLock(&(*Bcb)->BcbLock);
|
KeInitializeSpinLock(&(*Bcb)->BcbLock);
|
||||||
InitializeListHead(&(*Bcb)->BcbSegmentListHead);
|
InitializeListHead(&(*Bcb)->BcbSegmentListHead);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef __INCLUDE_INTERNAL_CC_H
|
#ifndef __INCLUDE_INTERNAL_CC_H
|
||||||
#define __INCLUDE_INTERNAL_CC_H
|
#define __INCLUDE_INTERNAL_CC_H
|
||||||
/* $Id: cc.h,v 1.9 2001/12/31 01:53:44 dwelch Exp $ */
|
/* $Id: cc.h,v 1.10 2002/01/26 21:21:02 dwelch Exp $ */
|
||||||
#include <ddk/ntifs.h>
|
#include <ddk/ntifs.h>
|
||||||
|
|
||||||
typedef struct _BCB
|
typedef struct _BCB
|
||||||
|
@ -17,7 +17,10 @@ typedef struct _CACHE_SEGMENT
|
||||||
{
|
{
|
||||||
/* Base address of the region where the cache segment data is mapped. */
|
/* Base address of the region where the cache segment data is mapped. */
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
/* Memory area representing the region where the cache segment data is mapped. */
|
/*
|
||||||
|
* Memory area representing the region where the cache segment data is
|
||||||
|
* mapped.
|
||||||
|
*/
|
||||||
struct _MEMORY_AREA* MemoryArea;
|
struct _MEMORY_AREA* MemoryArea;
|
||||||
/* Are the contents of the cache segment data valid. */
|
/* Are the contents of the cache segment data valid. */
|
||||||
BOOLEAN Valid;
|
BOOLEAN Valid;
|
||||||
|
@ -39,6 +42,8 @@ typedef struct _CACHE_SEGMENT
|
||||||
ULONG ReferenceCount;
|
ULONG ReferenceCount;
|
||||||
/* Pointer to the BCB for the file which this cache segment maps data for. */
|
/* Pointer to the BCB for the file which this cache segment maps data for. */
|
||||||
PBCB Bcb;
|
PBCB Bcb;
|
||||||
|
/* Pointer to the next cache segment in a chain. */
|
||||||
|
struct _CACHE_SEGMENT* NextInChain;
|
||||||
} CACHE_SEGMENT;
|
} CACHE_SEGMENT;
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
|
@ -66,5 +71,9 @@ NTSTATUS
|
||||||
CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty);
|
CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CcRosSuggestFreeCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty);
|
CcRosSuggestFreeCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty);
|
||||||
|
NTSTATUS
|
||||||
|
CcRosGetCacheSegmentChain(PBCB Bcb,
|
||||||
|
ULONG FileOffset,
|
||||||
|
ULONG Length,
|
||||||
|
PCACHE_SEGMENT* CacheSeg);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: ps.h,v 1.28 2002/01/15 02:51:32 dwelch Exp $
|
/* $Id: ps.h,v 1.29 2002/01/26 21:21:02 dwelch Exp $
|
||||||
*
|
*
|
||||||
* FILE: ntoskrnl/ke/kthread.c
|
* FILE: ntoskrnl/ke/kthread.c
|
||||||
* PURPOSE: Process manager definitions
|
* PURPOSE: Process manager definitions
|
||||||
|
@ -285,7 +285,7 @@ typedef struct _ETHREAD
|
||||||
*/
|
*/
|
||||||
struct _EPROCESS* OldProcess; /* 240/26C */
|
struct _EPROCESS* OldProcess; /* 240/26C */
|
||||||
|
|
||||||
PW32THREAD Win32Thread;
|
struct _W32THREAD* Win32Thread;
|
||||||
|
|
||||||
} __attribute__((packed)) ETHREAD, *PETHREAD;
|
} __attribute__((packed)) ETHREAD, *PETHREAD;
|
||||||
|
|
||||||
|
@ -354,12 +354,6 @@ typedef struct _KPROCESS
|
||||||
UCHAR DisableBoost; /* 067 */
|
UCHAR DisableBoost; /* 067 */
|
||||||
} KPROCESS, *PKPROCESS;
|
} KPROCESS, *PKPROCESS;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _W32PROCESS
|
|
||||||
{
|
|
||||||
} __attribute__((packed)) W32PROCESS, *PW32PROCESS;
|
|
||||||
|
|
||||||
|
|
||||||
struct _EPROCESS
|
struct _EPROCESS
|
||||||
{
|
{
|
||||||
/* Microkernel specific process state. */
|
/* Microkernel specific process state. */
|
||||||
|
@ -459,7 +453,7 @@ struct _EPROCESS
|
||||||
UCHAR SubSystemMinorVersion;
|
UCHAR SubSystemMinorVersion;
|
||||||
UCHAR SubSystemMajorVersion;
|
UCHAR SubSystemMajorVersion;
|
||||||
USHORT SubSystemVersion;
|
USHORT SubSystemVersion;
|
||||||
PW32PROCESS Win32Process;
|
struct _W32PROCESS* Win32Process;
|
||||||
HANDLE Win32WindowStation;
|
HANDLE Win32WindowStation;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: win32.c,v 1.2 2002/01/13 22:52:07 dwelch Exp $
|
/* $Id: win32.c,v 1.3 2002/01/26 21:21:02 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -31,12 +31,14 @@
|
||||||
|
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <internal/ps.h>
|
#include <internal/ps.h>
|
||||||
|
#include <napi/win32.h>
|
||||||
|
|
||||||
/* TYPES *******************************************************************/
|
/* TYPES *******************************************************************/
|
||||||
|
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
static ULONG PspWin32ProcessSize = 0;
|
static ULONG PspWin32ProcessSize = 0;
|
||||||
|
static ULONG PspWin32ThreadSize = 0;
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
@ -46,6 +48,29 @@ PsGetWin32Thread(VOID)
|
||||||
return(PsGetCurrentThread()->Win32Thread);
|
return(PsGetCurrentThread()->Win32Thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
PsCreateWin32Thread(PETHREAD Thread)
|
||||||
|
{
|
||||||
|
if (Thread->Win32Thread != NULL)
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
|
||||||
|
Thread->Win32Thread = ExAllocatePool(NonPagedPool,
|
||||||
|
PspWin32ThreadSize);
|
||||||
|
if (Thread->Win32Thread == NULL)
|
||||||
|
return(STATUS_NO_MEMORY);
|
||||||
|
|
||||||
|
RtlZeroMemory(Thread->Win32Thread,
|
||||||
|
PspWin32ThreadSize);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
PW32PROCESS STDCALL
|
||||||
|
PsGetWin32Process(VOID)
|
||||||
|
{
|
||||||
|
return(PsGetCurrentProcess()->Win32Process);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
PsCreateWin32Process(PEPROCESS Process)
|
PsCreateWin32Process(PEPROCESS Process)
|
||||||
{
|
{
|
||||||
|
@ -69,10 +94,11 @@ PsEstablishWin32Callouts(PVOID Param1,
|
||||||
PVOID Param2,
|
PVOID Param2,
|
||||||
PVOID Param3,
|
PVOID Param3,
|
||||||
PVOID Param4,
|
PVOID Param4,
|
||||||
PVOID Param5,
|
ULONG W32ThreadSize,
|
||||||
ULONG W32ProcessSize)
|
ULONG W32ProcessSize)
|
||||||
{
|
{
|
||||||
PspWin32ProcessSize = W32ProcessSize;
|
PspWin32ProcessSize = W32ProcessSize;
|
||||||
|
PspWin32ThreadSize = W32ThreadSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue