Index: ntoskrnl/cc/copy.c =================================================================== --- ntoskrnl/cc/copy.c (revision 60399) +++ ntoskrnl/cc/copy.c (working copy) @@ -355,19 +355,24 @@ if (!Wait) { KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + /* FIXME: this loop doesn't take into account areas that don't have + * a segment in the list yet */ current_entry = Bcb->BcbSegmentListHead.Flink; while (current_entry != &Bcb->BcbSegmentListHead) { current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); - if (!current->Valid && current->FileOffset < ReadOffset + Length - && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset) + if (!current->Valid && + DoSegmentsIntersect(current->FileOffset, Bcb->CacheSegmentSize, + ReadOffset, Length)) { KeReleaseSpinLock(&Bcb->BcbLock, oldirql); IoStatus->Status = STATUS_UNSUCCESSFUL; IoStatus->Information = 0; return FALSE; } + if (current->FileOffset >= ReadOffset + Length) + break; current_entry = current_entry->Flink; } KeReleaseSpinLock(&Bcb->BcbLock, oldirql); @@ -466,24 +471,23 @@ { /* testing, if the requested datas are available */ KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + /* FIXME: this loop doesn't take into account areas that don't have + * a segment in the list yet */ current_entry = Bcb->BcbSegmentListHead.Flink; while (current_entry != &Bcb->BcbSegmentListHead) { CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); - if (!CacheSeg->Valid) + if (!CacheSeg->Valid && + DoSegmentsIntersect(CacheSeg->FileOffset, Bcb->CacheSegmentSize, + WriteOffset, Length)) { - if (((WriteOffset >= CacheSeg->FileOffset) && - (WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize)) - || ((WriteOffset + Length > CacheSeg->FileOffset) && - (WriteOffset + Length <= CacheSeg->FileOffset + - Bcb->CacheSegmentSize))) - { - KeReleaseSpinLock(&Bcb->BcbLock, oldirql); - /* datas not available */ - return FALSE; - } + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + /* datas not available */ + return FALSE; } + if (CacheSeg->FileOffset >= WriteOffset + Length) + break; current_entry = current_entry->Flink; } KeReleaseSpinLock(&Bcb->BcbLock, oldirql); @@ -683,28 +687,27 @@ ULONG TempLength; Bcb = FileObject->SectionObjectPointer->SharedCacheMap; - if (Wait) + if (!Wait) { /* testing, if the requested datas are available */ KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + /* FIXME: this loop doesn't take into account areas that don't have + * a segment in the list yet */ current_entry = Bcb->BcbSegmentListHead.Flink; while (current_entry != &Bcb->BcbSegmentListHead) { CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); - if (!CacheSeg->Valid) + if (!CacheSeg->Valid && + DoSegmentsIntersect(CacheSeg->FileOffset, Bcb->CacheSegmentSize, + WriteOffset.u.LowPart, Length)) { - if (((WriteOffset.u.LowPart >= CacheSeg->FileOffset) && - (WriteOffset.u.LowPart < CacheSeg->FileOffset + Bcb->CacheSegmentSize)) - || ((WriteOffset.u.LowPart + Length > CacheSeg->FileOffset) && - (WriteOffset.u.LowPart + Length <= - CacheSeg->FileOffset + Bcb->CacheSegmentSize))) - { - KeReleaseSpinLock(&Bcb->BcbLock, oldirql); - /* datas not available */ - return FALSE; - } + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + /* datas not available */ + return FALSE; } + if (CacheSeg->FileOffset >= WriteOffset.u.LowPart + Length) + break; current_entry = current_entry->Flink; } KeReleaseSpinLock(&Bcb->BcbLock, oldirql); Index: ntoskrnl/cc/fs.c =================================================================== --- ntoskrnl/cc/fs.c (revision 60399) +++ ntoskrnl/cc/fs.c (working copy) @@ -159,10 +159,11 @@ current_entry = Bcb->BcbSegmentListHead.Flink; while (current_entry != &Bcb->BcbSegmentListHead) { - current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); + current = CONTAINING_RECORD(current_entry, + CACHE_SEGMENT, + BcbSegmentListEntry); current_entry = current_entry->Flink; - if (current->FileOffset > FileSizes->AllocationSize.QuadPart || - (current->FileOffset == 0 && FileSizes->AllocationSize.QuadPart == 0)) + if (current->FileOffset >= FileSizes->AllocationSize.QuadPart) { if ((current->ReferenceCount == 0) || ((current->ReferenceCount == 1) && current->Dirty)) { Index: ntoskrnl/cc/pin.c =================================================================== --- ntoskrnl/cc/pin.c (revision 60399) +++ ntoskrnl/cc/pin.c (working copy) @@ -261,7 +261,7 @@ { IoStatus->Status = STATUS_SUCCESS; } - KeReleaseMutex(&iBcb->CacheSegment->Mutex, 0); + KeReleaseMutex(&iBcb->CacheSegment->Mutex, FALSE); } else { Index: ntoskrnl/cc/view.c =================================================================== --- ntoskrnl/cc/view.c (revision 60399) +++ ntoskrnl/cc/view.c (working copy) @@ -236,7 +236,7 @@ /* One reference is added above */ if (current->ReferenceCount > 2) { - KeReleaseMutex(¤t->Mutex, 0); + KeReleaseMutex(¤t->Mutex, FALSE); current->Bcb->Callbacks->ReleaseFromLazyWrite( current->Bcb->LazyWriteContext); CcRosCacheSegmentDecRefCount(current); @@ -249,7 +249,7 @@ Status = CcRosFlushCacheSegment(current); - KeReleaseMutex(¤t->Mutex, 0); + KeReleaseMutex(¤t->Mutex, FALSE); current->Bcb->Callbacks->ReleaseFromLazyWrite( current->Bcb->LazyWriteContext); @@ -446,7 +446,7 @@ KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); - KeReleaseMutex(&CacheSeg->Mutex, 0); + KeReleaseMutex(&CacheSeg->Mutex, FALSE); return(STATUS_SUCCESS); } @@ -474,8 +474,8 @@ { current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); - if ((current->FileOffset <= FileOffset) && - ((current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)) + if (IsPointInSegment(current->FileOffset, Bcb->CacheSegmentSize, + FileOffset)) { CcRosCacheSegmentIncRefCount(current); KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); @@ -485,15 +485,17 @@ KernelMode, FALSE, NULL); - return(current); + return current; } + if (current->FileOffset > FileOffset) + break; current_entry = current_entry->Flink; } KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); - return(NULL); + return NULL; } NTSTATUS @@ -536,7 +538,7 @@ KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); - KeReleaseMutex(&CacheSeg->Mutex, 0); + KeReleaseMutex(&CacheSeg->Mutex, FALSE); return(STATUS_SUCCESS); } @@ -589,7 +591,7 @@ KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); - KeReleaseMutex(&CacheSeg->Mutex, 0); + KeReleaseMutex(&CacheSeg->Mutex, FALSE); return(STATUS_SUCCESS); } @@ -659,8 +661,8 @@ { current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); - if (current->FileOffset <= FileOffset && - (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset) + if (IsPointInSegment(current->FileOffset, Bcb->CacheSegmentSize, + FileOffset)) { CcRosCacheSegmentIncRefCount(current); KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); @@ -673,7 +675,7 @@ current ); } #endif - KeReleaseMutex(&(*CacheSeg)->Mutex, 0); + KeReleaseMutex(&(*CacheSeg)->Mutex, FALSE); KeReleaseGuardedMutex(&ViewLock); ExFreeToNPagedLookasideList(&CacheSegLookasideList, *CacheSeg); *CacheSeg = current; @@ -686,18 +688,12 @@ } if (current->FileOffset < FileOffset) { - if (previous == NULL) - { - previous = current; - } - else - { - if (previous->FileOffset < current->FileOffset) - { - previous = current; - } - } + ASSERT(previous == NULL || + previous->FileOffset < current->FileOffset); + previous = current; } + if (current->FileOffset > FileOffset) + break; current_entry = current_entry->Flink; } /* There was no existing segment. */ @@ -996,38 +992,6 @@ return(STATUS_SUCCESS); } -NTSTATUS -NTAPI -CcRosFreeCacheSegment ( - PBCB Bcb, - PCACHE_SEGMENT CacheSeg) -{ - NTSTATUS Status; - KIRQL oldIrql; - - ASSERT(Bcb); - - DPRINT("CcRosFreeCacheSegment(Bcb 0x%p, CacheSeg 0x%p)\n", - Bcb, CacheSeg); - - KeAcquireGuardedMutex(&ViewLock); - KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); - RemoveEntryList(&CacheSeg->BcbSegmentListEntry); - RemoveEntryList(&CacheSeg->CacheSegmentListEntry); - RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry); - if (CacheSeg->Dirty) - { - RemoveEntryList(&CacheSeg->DirtySegmentListEntry); - DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE; - - } - KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); - KeReleaseGuardedMutex(&ViewLock); - - Status = CcRosInternalFreeCacheSegment(CacheSeg); - return(Status); -} - /* * @implemented */ @@ -1081,7 +1045,7 @@ IoStatus->Status = Status; } } - KeReleaseMutex(¤t->Mutex, 0); + KeReleaseMutex(¤t->Mutex, FALSE); KeAcquireGuardedMutex(&ViewLock); KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); @@ -1148,7 +1112,6 @@ */ InitializeListHead(&FreeList); KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); - current_entry = Bcb->BcbSegmentListHead.Flink; while (!IsListEmpty(&Bcb->BcbSegmentListHead)) { current_entry = RemoveTailList(&Bcb->BcbSegmentListHead); Index: ntoskrnl/include/internal/cc.h =================================================================== --- ntoskrnl/include/internal/cc.h (revision 60399) +++ ntoskrnl/include/internal/cc.h (working copy) @@ -205,13 +205,6 @@ NTSTATUS NTAPI -CcRosFreeCacheSegment( - PBCB, - PCACHE_SEGMENT -); - -NTSTATUS -NTAPI ReadCacheSegment(PCACHE_SEGMENT CacheSeg); NTSTATUS @@ -315,3 +308,28 @@ NTSTATUS NTAPI CcTryToInitializeFileCache(PFILE_OBJECT FileObject); + +FORCEINLINE +BOOLEAN +DoSegmentsIntersect( + _In_ ULONG Offset1, + _In_ ULONG Length1, + _In_ ULONG Offset2, + _In_ ULONG Length2) +{ + if (Offset1 + Length1 <= Offset2) + return FALSE; + if (Offset2 + Length2 <= Offset1) + return FALSE; + return TRUE; +} + +FORCEINLINE +BOOLEAN +IsPointInSegment( + _In_ ULONG Offset1, + _In_ ULONG Length1, + _In_ ULONG Point) +{ + return DoSegmentsIntersect(Offset1, Length1, Point, 1); +}