update for HEAD-2003091401
[reactos.git] / ntoskrnl / cc / view.c
index be8e239..7e7e85c 100644 (file)
@@ -132,9 +132,6 @@ CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment)
   return(Status);
 }
 
-VOID CcRosRemoveUnusedFiles(VOID);
-
-
 NTSTATUS
 CcRosFlushDirtyPages(ULONG Target, PULONG Count)
 {
@@ -231,7 +228,7 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
  */
 {
   PLIST_ENTRY current_entry;
-  PCACHE_SEGMENT current;
+  PCACHE_SEGMENT current, last = NULL;
   ULONG PagesPerSegment;
   ULONG PagesFreed;
   KIRQL oldIrql;
@@ -259,10 +256,40 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
          RemoveEntryList(&current->CacheSegmentListEntry);
          RemoveEntryList(&current->CacheSegmentLRUListEntry);
         InsertHeadList(&FreeList, &current->BcbSegmentListEntry);
+         PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
+         PagesFreed = min(PagesPerSegment, Target);
+         Target -= PagesFreed;
+         (*NrFreed) += PagesFreed;
       }
       else
       {
-         KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
+         if (last != current && current->MappedCount > 0 && !current->Dirty)
+          {
+            ULONG i;
+            NTSTATUS Status;
+               
+             current->ReferenceCount++;
+            last = current;
+             KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
+            ExReleaseFastMutex(&ViewLock);
+            for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++)
+              {
+                PHYSICAL_ADDRESS Page;
+                Page = MmGetPhysicalAddress(current->BaseAddress + i * PAGE_SIZE);
+                 Status = MmPageOutPhysicalAddress(Page);
+                if (!NT_SUCCESS(Status))
+                  {
+                    break;
+                  }
+              }
+             ExAcquireFastMutex(&ViewLock);
+             KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
+            current->ReferenceCount--;
+             KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
+             current_entry = &current->CacheSegmentLRUListEntry;
+            continue;
+          }
+        KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
       }
   }
   ExReleaseFastMutex(&ViewLock);
@@ -272,10 +299,6 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
      current_entry = RemoveHeadList(&FreeList);
      current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 
                                 BcbSegmentListEntry);
-     PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
-     PagesFreed = min(PagesPerSegment, Target);
-     Target -= PagesFreed;
-     (*NrFreed) += PagesFreed;
      CcRosInternalFreeCacheSegment(current);
   }
 
@@ -353,6 +376,7 @@ CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
        {
          current->ReferenceCount++;
          KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
+          ExAcquireFastMutex(&current->Lock);
          return(current);
        }
       current_entry = current_entry->Flink;
@@ -374,9 +398,8 @@ CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset)
   CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
   if (CacheSeg == NULL)
     {
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
-  ExAcquireFastMutex(&CacheSeg->Lock);
   if (!CacheSeg->Dirty)
     {
       ExAcquireFastMutex(&ViewLock);
@@ -415,7 +438,6 @@ CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
     {
       return(STATUS_UNSUCCESSFUL);
     }
-  ExAcquireFastMutex(&CacheSeg->Lock);
 
   WasDirty = CacheSeg->Dirty;
   CacheSeg->Dirty = CacheSeg->Dirty || NowDirty;
@@ -449,11 +471,11 @@ CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
 NTSTATUS STATIC
 CcRosCreateCacheSegment(PBCB Bcb,
                        ULONG FileOffset,
-                       PCACHE_SEGMENT* CacheSeg,
-                       BOOLEAN Lock)
+                       PCACHE_SEGMENT* CacheSeg)
 {
   ULONG i;
   PCACHE_SEGMENT current;
+  PCACHE_SEGMENT previous;
   PLIST_ENTRY current_entry;
   NTSTATUS Status;
   KIRQL oldIrql;
@@ -465,6 +487,12 @@ CcRosCreateCacheSegment(PBCB Bcb,
 
   DPRINT("CcRosCreateCacheSegment()\n");
 
+  if (FileOffset >= Bcb->FileSize.u.LowPart)
+  {
+     CacheSeg = NULL;
+     return STATUS_INVALID_PARAMETER;
+  }
+
   current = ExAllocateFromNPagedLookasideList(&CacheSegLookasideList);
   current->Valid = FALSE;
   current->Dirty = FALSE;
@@ -486,6 +514,7 @@ CcRosCreateCacheSegment(PBCB Bcb,
    */
   KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
   current_entry = Bcb->BcbSegmentListHead.Flink;
+  previous = NULL;
   while (current_entry != &Bcb->BcbSegmentListHead)
   {
      current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 
@@ -499,17 +528,35 @@ CcRosCreateCacheSegment(PBCB Bcb,
        ExReleaseFastMutex(&ViewLock);
        ExFreeToNPagedLookasideList(&CacheSegLookasideList, *CacheSeg);
        *CacheSeg = current;
-       if (Lock)
+        ExAcquireFastMutex(&current->Lock);
+       return STATUS_SUCCESS;
+     }
+     if (current->FileOffset < FileOffset)
+     {
+        if (previous == NULL)
        {
-          ExAcquireFastMutex(&current->Lock);
+          previous = current;
+       }
+       else
+       {
+          if (previous->FileOffset < current->FileOffset)
+          {
+             previous = current;
+          }
        }
-       return STATUS_SUCCESS;
      }
      current_entry = current_entry->Flink;
   }
   /* There was no existing segment. */
   current = *CacheSeg;
-  InsertTailList(&Bcb->BcbSegmentListHead, &current->BcbSegmentListEntry);
+  if (previous)
+  {
+     InsertHeadList(&previous->BcbSegmentListEntry, &current->BcbSegmentListEntry);
+  }
+  else
+  {
+     InsertHeadList(&Bcb->BcbSegmentListHead, &current->BcbSegmentListEntry);
+  }
   KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
   InsertTailList(&CacheSegmentListHead, &current->CacheSegmentListEntry);
   InsertTailList(&CacheSegmentLRUListHead, &current->CacheSegmentLRUListEntry);
@@ -522,7 +569,7 @@ CcRosCreateCacheSegment(PBCB Bcb,
   if (StartingOffset == 0xffffffff)
   {
      DPRINT1("Out of CacheSeg mapping space\n");
-     KeBugCheck(0);
+     KEBUGCHECK(0);
   }
 
   current->BaseAddress = CiCacheSegMappingRegionBase + StartingOffset * PAGE_SIZE;
@@ -543,11 +590,12 @@ CcRosCreateCacheSegment(PBCB Bcb,
                              Bcb->CacheSegmentSize,
                              PAGE_READWRITE,
                              (PMEMORY_AREA*)&current->MemoryArea,
+                             FALSE,
                              FALSE);
   MmUnlockAddressSpace(MmGetKernelAddressSpace());
   if (!NT_SUCCESS(Status))
   {
-     KeBugCheck(0);
+     KEBUGCHECK(0);
   }
 #endif
   for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
@@ -557,7 +605,7 @@ CcRosCreateCacheSegment(PBCB Bcb,
      Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page);
      if (!NT_SUCCESS(Status))
      {
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
       
      Status = MmCreateVirtualMapping(NULL,
@@ -567,14 +615,9 @@ CcRosCreateCacheSegment(PBCB Bcb,
                                     TRUE);
      if (!NT_SUCCESS(Status))
      {
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
   }
-  if (!Lock)
-  {
-     ExReleaseFastMutex(&current->Lock);
-  }
-
   return(STATUS_SUCCESS);
 }
 
@@ -611,14 +654,13 @@ CcRosGetCacheSegmentChain(PBCB Bcb,
        }
       else
        {
-         CcRosCreateCacheSegment(Bcb, CurrentOffset, &current, FALSE);
+         CcRosCreateCacheSegment(Bcb, CurrentOffset, &current);
          CacheSegList[i] = current;
        }
     }
 
   for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++)
     {
-      ExAcquireFastMutex(&CacheSegList[i]->Lock);
       if (i == 0)
        {
          *CacheSeg = CacheSegList[i];
@@ -654,16 +696,16 @@ CcRosGetCacheSegment(PBCB Bcb,
     * Look for a cache segment already mapping the same data.
     */
    current = CcRosLookupCacheSegment(Bcb, FileOffset);
-   if (current != NULL)
-   {
-      ExAcquireFastMutex(&current->Lock);
-   }
-   else
+   if (current == NULL)
    {
      /*
       * Otherwise create a new segment.
       */
-      Status = CcRosCreateCacheSegment(Bcb, FileOffset, &current, TRUE);
+      Status = CcRosCreateCacheSegment(Bcb, FileOffset, &current);
+      if (!NT_SUCCESS(Status))
+      {
+       return Status;
+      }
    }
    /*
     * Return information about the segment to the caller.
@@ -694,7 +736,7 @@ CcRosRequestCacheSegment(PBCB Bcb,
     {
       CPRINT("Bad fileoffset %x should be multiple of %x",
         FileOffset, Bcb->CacheSegmentSize);
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
 
   return(CcRosGetCacheSegment(Bcb,
@@ -796,6 +838,9 @@ CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
   return(Status);
 }
 
+/*
+ * @implemented
+ */
 VOID STDCALL
 CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
             IN PLARGE_INTEGER FileOffset OPTIONAL,
@@ -836,7 +881,6 @@ CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
         current = CcRosLookupCacheSegment (Bcb, Offset.u.LowPart);
         if (current != NULL)
         {
-           ExAcquireFastMutex(&current->Lock);
            if (current->Dirty)
            {
               Status = CcRosFlushCacheSegment(current);
@@ -888,7 +932,7 @@ CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
    Bcb->RefCount++;
    ExReleaseFastMutex(&ViewLock);
 
-   CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL);
+   CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
 
    ExAcquireFastMutex(&ViewLock);
    Bcb->RefCount--;
@@ -900,7 +944,7 @@ CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
          Bcb->BcbRemoveListEntry.Flink = NULL;
       }
 
-      FileObject->SectionObjectPointers->SharedCacheMap = NULL;  
+      FileObject->SectionObjectPointer->SharedCacheMap = NULL;  
 
       /*
        * Release all cache segments.
@@ -943,8 +987,19 @@ VOID CcRosReferenceCache(PFILE_OBJECT FileObject)
 {
   PBCB Bcb;
   ExAcquireFastMutex(&ViewLock);
-  Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
+  Bcb = (PBCB)FileObject->SectionObjectPointer->SharedCacheMap;
   assert(Bcb);
+  if (Bcb->RefCount == 0)
+  {
+     assert(Bcb->BcbRemoveListEntry.Flink != NULL);
+     RemoveEntryList(&Bcb->BcbRemoveListEntry);
+     Bcb->BcbRemoveListEntry.Flink = NULL;
+
+  }
+  else
+  {
+     assert(Bcb->BcbRemoveListEntry.Flink == NULL);
+  }
   Bcb->RefCount++;
   ExReleaseFastMutex(&ViewLock);
 }
@@ -952,7 +1007,7 @@ VOID CcRosReferenceCache(PFILE_OBJECT FileObject)
 VOID CcRosSetRemoveOnClose(PSECTION_OBJECT_POINTERS SectionObjectPointer)
 {
   PBCB Bcb;
-//  DPRINT1("CcRosSetRemoveOnClose()\n");
+  DPRINT("CcRosSetRemoveOnClose()\n");
   ExAcquireFastMutex(&ViewLock);
   Bcb = (PBCB)SectionObjectPointer->SharedCacheMap;
   if (Bcb)
@@ -971,7 +1026,7 @@ VOID CcRosDereferenceCache(PFILE_OBJECT FileObject)
 {
   PBCB Bcb;
   ExAcquireFastMutex(&ViewLock);
-  Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
+  Bcb = (PBCB)FileObject->SectionObjectPointer->SharedCacheMap;
   assert(Bcb);
   if (Bcb->RefCount > 0)
   {
@@ -1004,9 +1059,9 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject)
 
   ExAcquireFastMutex(&ViewLock);
 
-  if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
+  if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
   {
-    Bcb = FileObject->SectionObjectPointers->SharedCacheMap;
+    Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
     if (FileObject->PrivateCacheMap != NULL)
     {
       FileObject->PrivateCacheMap = NULL;
@@ -1032,6 +1087,39 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject)
   return(STATUS_SUCCESS);
 }
 
+NTSTATUS 
+CcTryToInitializeFileCache(PFILE_OBJECT FileObject)
+{
+   PBCB Bcb;
+   NTSTATUS Status;
+
+   ExAcquireFastMutex(&ViewLock);
+
+   Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+   if (Bcb == NULL)
+   {
+      Status = STATUS_UNSUCCESSFUL;
+   }
+   else
+   {
+      if (FileObject->PrivateCacheMap == NULL)
+      {
+         FileObject->PrivateCacheMap = Bcb;
+         Bcb->RefCount++;
+      }
+      if (Bcb->BcbRemoveListEntry.Flink != NULL)
+      {
+         RemoveEntryList(&Bcb->BcbRemoveListEntry);
+         Bcb->BcbRemoveListEntry.Flink = NULL;
+      }
+      Status = STATUS_SUCCESS;
+   }
+   ExReleaseFastMutex(&ViewLock);
+
+   return Status;
+}
+
+
 NTSTATUS STDCALL 
 CcRosInitializeFileCache(PFILE_OBJECT FileObject,
                         ULONG CacheSegmentSize)
@@ -1045,7 +1133,7 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
 
    ExAcquireFastMutex(&ViewLock);
 
-   Bcb = FileObject->SectionObjectPointers->SharedCacheMap;
+   Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
    if (Bcb == NULL)
    {
       Bcb = ExAllocateFromNPagedLookasideList(&BcbLookasideList);      
@@ -1064,13 +1152,13 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
       if (FileObject->FsContext)
       {
          Bcb->AllocationSize = 
-          ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize;
+          ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->AllocationSize;
          Bcb->FileSize = 
-          ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize;
+          ((PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize;
       }
       KeInitializeSpinLock(&Bcb->BcbLock);
       InitializeListHead(&Bcb->BcbSegmentListHead);
-      FileObject->SectionObjectPointers->SharedCacheMap = Bcb;
+      FileObject->SectionObjectPointer->SharedCacheMap = Bcb;
    }
    if (FileObject->PrivateCacheMap == NULL)
    {
@@ -1087,6 +1175,9 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
    return(STATUS_SUCCESS);
 }
 
+/*
+ * @implemented
+ */
 PFILE_OBJECT STDCALL
 CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
 {
@@ -1125,7 +1216,7 @@ CmLazyCloseThreadMain(PVOID Ignored)
       if (!NT_SUCCESS(Status))
       {
          DbgPrint("LazyCloseThread: Wait failed\n");
-         KeBugCheck(0);
+         KEBUGCHECK(0);
          break;
       }
       if (LazyCloseThreadShouldTerminate)
@@ -1178,11 +1269,12 @@ CcInitView(VOID)
                              CI_CACHESEG_MAPPING_REGION_SIZE,
                              0,
                              &marea,
+                             FALSE,
                              FALSE);
   MmUnlockAddressSpace(MmGetKernelAddressSpace());
   if (!NT_SUCCESS(Status))
     {
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
 
   Buffer = ExAllocatePool(NonPagedPool, CI_CACHESEG_MAPPING_REGION_SIZE / (PAGE_SIZE * 8));