diff --git a/reactos/ntoskrnl/cc/copy.c b/reactos/ntoskrnl/cc/copy.c index ec2fe741abb..ec00dabfc25 100644 --- a/reactos/ntoskrnl/cc/copy.c +++ b/reactos/ntoskrnl/cc/copy.c @@ -1,4 +1,4 @@ -/* $Id: copy.c,v 1.5 2002/06/04 15:26:55 dwelch Exp $ +/* $Id: copy.c,v 1.6 2002/06/10 21:11:56 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -26,8 +26,29 @@ #define ROUND_DOWN(N, S) ((N) - ((N) % (S))) +static PHYSICAL_ADDRESS CcZeroPage = (PHYSICAL_ADDRESS)0LL; + /* FUNCTIONS *****************************************************************/ +VOID +InitCacheZeroPage(VOID) +{ + NTSTATUS Status; + + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &CcZeroPage); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Can't allocate CcZeroPage.\n"); + KeBugCheck(0); + } + Status = MiZeroPage(CcZeroPage); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Can't zero out CcZeroPage.\n"); + KeBugCheck(0); + } +} + NTSTATUS ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length, PVOID Buffer) @@ -410,4 +431,195 @@ CcCopyWrite ( return TRUE; } +BOOLEAN STDCALL +CcZeroData ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER StartOffset, + IN PLARGE_INTEGER EndOffset, + IN BOOLEAN Wait +) +{ + NTSTATUS Status; + LARGE_INTEGER WriteOffset; + ULONG Length; + PMDL Mdl; + ULONG i; + IO_STATUS_BLOCK Iosb; + + DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, Wait %d\n", + FileObject, StartOffset->QuadPart, EndOffset->QuadPart, Wait); + + Length = EndOffset->u.LowPart - StartOffset->u.LowPart; + + // FIXME: NT uses the shared chache map field for cached/non cached detection + if (((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->Bcb == NULL) + { + // File is not cached + + CHECKPOINT; + + WriteOffset.QuadPart = StartOffset->QuadPart; + + while (Length > 0) + { + if (Length + WriteOffset.u.LowPart % PAGESIZE > 262144) + { + Mdl = MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart, 262144 - WriteOffset.u.LowPart % PAGESIZE); + WriteOffset.QuadPart += (262144 - WriteOffset.u.LowPart % PAGESIZE); + Length -= (262144 - WriteOffset.u.LowPart % PAGESIZE); + } + else + { + Mdl = MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart, Length - WriteOffset.u.LowPart % PAGESIZE); + WriteOffset.QuadPart += (Length - WriteOffset.u.LowPart % PAGESIZE); + Length = 0; + } + if (Mdl == NULL) + { + return FALSE; + } + Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ); + for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++) + { + ((PULONG)(Mdl + 1))[i] = CcZeroPage.u.LowPart; + } + Status = IoPageWrite(FileObject, Mdl, StartOffset, &Iosb, TRUE); + if (!NT_SUCCESS(Status)) + { + return FALSE; + } + } + } + else + { + // File is cached + KIRQL oldirql; + PBCB Bcb; + PLIST_ENTRY current_entry; + PCACHE_SEGMENT CacheSeg, current, previous; + ULONG TempLength; + ULONG Start; + ULONG count; + ULONG size; + PHYSICAL_ADDRESS page; + + CHECKPOINT; + Start = StartOffset->u.LowPart; + Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb; + if (Wait) + { + // testing, if the requested datas are available + KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) + { + CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); + if (!CacheSeg->Valid) + { + if ((Start >= CacheSeg->FileOffset && Start < CacheSeg->FileOffset + Bcb->CacheSegmentSize) + || (Start + Length > CacheSeg->FileOffset && + Start + Length <= CacheSeg->FileOffset + Bcb->CacheSegmentSize)) + { + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + // datas not available + return FALSE; + } + } + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + } + + while (Length > 0) + { + WriteOffset.QuadPart = ROUND_DOWN(Start, Bcb->CacheSegmentSize); + if (Start % Bcb->CacheSegmentSize + Length > 262144) + { + Mdl = MmCreateMdl(NULL, NULL, 262144); + if (Mdl == NULL) + { + return FALSE; + } + Status = CcRosGetCacheSegmentChain (Bcb, ROUND_DOWN(Start, Bcb->CacheSegmentSize), + 262144, &CacheSeg); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Mdl); + return FALSE; + } + } + else + { + Mdl = MmCreateMdl(NULL, (PVOID)ROUND_DOWN(Start, Bcb->CacheSegmentSize), + ROUND_UP(Start % Bcb->CacheSegmentSize + Length, Bcb->CacheSegmentSize)); + if (Mdl == NULL) + { + return FALSE; + } + Status = CcRosGetCacheSegmentChain (Bcb, ROUND_DOWN(Start, Bcb->CacheSegmentSize), + min(ROUND_UP(Start % Bcb->CacheSegmentSize + + Length, Bcb->CacheSegmentSize), + Bcb->AllocationSize.u.LowPart + - ROUND_DOWN(Start, Bcb->CacheSegmentSize)), + &CacheSeg); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Mdl); + return FALSE; + } + } + Mdl->MdlFlags |= (MDL_PAGES_LOCKED|MDL_IO_PAGE_READ); + current = CacheSeg; + count = 0; + while (current != NULL) + { + if (Start % Bcb->CacheSegmentSize || + Start % Bcb->CacheSegmentSize + Length < Bcb->CacheSegmentSize) + { + if (!current->Valid) + { + // Segment lesen + Status = ReadCacheSegment(current); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ReadCacheSegment failed, status %x\n", Status); + } + } + TempLength = min (Length, Bcb->CacheSegmentSize - Start % Bcb->CacheSegmentSize); + memset (current->BaseAddress + Start % Bcb->CacheSegmentSize, 0, TempLength); + } + else + { + TempLength = Bcb->CacheSegmentSize; + memset (current->BaseAddress, 0, Bcb->CacheSegmentSize); + } + Start += TempLength; + Length -= TempLength; + + size = ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); + for (i = 0; i < (Bcb->CacheSegmentSize / PAGESIZE) && count < size; i++) + { + page = MmGetPhysicalAddressForProcess(NULL, current->BaseAddress + (i * PAGESIZE)); + ((PULONG)(Mdl + 1))[count++] = page.u.LowPart; + } + current = current->NextInChain; + } + + // Write the Segment + Status = IoPageWrite(FileObject, Mdl, &WriteOffset, &Iosb, TRUE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IoPageWrite failed, status %x\n", Status); + } + current = CacheSeg; + while (current != NULL) + { + previous = current; + current = current->NextInChain; + CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE); + } + } + } + return TRUE; +} diff --git a/reactos/ntoskrnl/cc/view.c b/reactos/ntoskrnl/cc/view.c index 3a635fa4891..0715e335046 100644 --- a/reactos/ntoskrnl/cc/view.c +++ b/reactos/ntoskrnl/cc/view.c @@ -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.42 2002/06/04 15:26:55 dwelch Exp $ +/* $Id: view.c,v 1.43 2002/06/10 21:11:56 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -576,6 +576,7 @@ CcInitView(VOID) InitializeListHead(&CacheSegmentLRUListHead); ExInitializeFastMutex(&ViewLock); MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache); + InitCacheZeroPage(); } /* EOF */ diff --git a/reactos/ntoskrnl/include/internal/cc.h b/reactos/ntoskrnl/include/internal/cc.h index b8f264c83f7..2f664da7878 100644 --- a/reactos/ntoskrnl/include/internal/cc.h +++ b/reactos/ntoskrnl/include/internal/cc.h @@ -1,6 +1,6 @@ #ifndef __INCLUDE_INTERNAL_CC_H #define __INCLUDE_INTERNAL_CC_H -/* $Id: cc.h,v 1.10 2002/01/26 21:21:02 dwelch Exp $ */ +/* $Id: cc.h,v 1.11 2002/06/10 21:11:56 hbirr Exp $ */ #include typedef struct _BCB @@ -76,4 +76,5 @@ CcRosGetCacheSegmentChain(PBCB Bcb, ULONG FileOffset, ULONG Length, PCACHE_SEGMENT* CacheSeg); +VOID InitCacheZeroPage(VOID); #endif diff --git a/reactos/ntoskrnl/ntoskrnl.def b/reactos/ntoskrnl/ntoskrnl.def index 02c671fd0e8..d8e97ab1d21 100644 --- a/reactos/ntoskrnl/ntoskrnl.def +++ b/reactos/ntoskrnl/ntoskrnl.def @@ -1,4 +1,4 @@ -; $Id: ntoskrnl.def,v 1.134 2002/06/05 16:53:36 ekohl Exp $ +; $Id: ntoskrnl.def,v 1.135 2002/06/10 21:11:56 hbirr Exp $ ; ; reactos/ntoskrnl/ntoskrnl.def ; @@ -16,6 +16,7 @@ CcMdlReadComplete@8 CcSetDirtyPinnedData@8 CcSetFileSizes@8 CcUnpinData@4 +CcZeroData@16 DbgBreakPoint@0 DbgBreakPointWithStatus@4 ;DbgLoadImageSymbols@12 diff --git a/reactos/ntoskrnl/ntoskrnl.edf b/reactos/ntoskrnl/ntoskrnl.edf index 31f61291706..c92fbcf2af3 100644 --- a/reactos/ntoskrnl/ntoskrnl.edf +++ b/reactos/ntoskrnl/ntoskrnl.edf @@ -1,4 +1,4 @@ -; $Id: ntoskrnl.edf,v 1.120 2002/06/05 16:53:36 ekohl Exp $ +; $Id: ntoskrnl.edf,v 1.121 2002/06/10 21:11:56 hbirr Exp $ ; ; reactos/ntoskrnl/ntoskrnl.def ; @@ -16,6 +16,7 @@ CcMapData=CcMapData@24 CcSetDirtyPinnedData=CcSetDirtyPinnedData@8 CcUnpinData=CcUnpinData@4 CcSetFileSizes=CcSetFileSizes@8 +CcZeroData=CcZeroData@16 DbgBreakPoint=DbgBreakPoint@0 DbgBreakPointWithStatus=DbgBreakPointWithStatus@4 ;DbgLoadImageSymbols=DbgLoadImageSymbols@12