[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / fsrtl / largemcb.c
index a642781..ddb8d6d 100644 (file)
@@ -135,10 +135,12 @@ FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
                      IN LONGLONG SectorCount)
 {
     BOOLEAN Result = TRUE;
+    BOOLEAN IntResult;
     PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
     LARGE_MCB_MAPPING_ENTRY Node, NeedleRun;
     PLARGE_MCB_MAPPING_ENTRY LowerRun, HigherRun;
     BOOLEAN NewElement;
+    LONGLONG IntLbn;
 
     DPRINT("FsRtlAddBaseMcbEntry(%p, %I64d, %I64d, %I64d)\n", OpaqueMcb, Vbn, Lbn, SectorCount);
 
@@ -154,6 +156,16 @@ FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
         goto quit;
     }
 
+    IntResult = FsRtlLookupBaseMcbEntry(OpaqueMcb, Vbn, &IntLbn, NULL, NULL, NULL, NULL);
+    if (IntResult)
+    {
+        if (IntLbn != -1 && IntLbn != Lbn)
+        {
+            Result = FALSE;
+            goto quit;
+        }
+    }
+
     /* clean any possible previous entries in our range */
     FsRtlRemoveBaseMcbEntry(OpaqueMcb, Vbn, SectorCount);
 
@@ -171,13 +183,15 @@ FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
     NeedleRun.RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart + 1;
     NeedleRun.StartingLbn.QuadPart = ~0ULL;
     Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
-    if ((LowerRun = RtlLookupElementGenericTable(&Mcb->Mapping->Table, &NeedleRun)))
+    if ((LowerRun = RtlLookupElementGenericTable(&Mcb->Mapping->Table, &NeedleRun)) &&
+        (LowerRun->StartingLbn.QuadPart + (LowerRun->RunEndVbn.QuadPart - LowerRun->RunStartVbn.QuadPart) == Node.StartingLbn.QuadPart))
     {
         ASSERT(LowerRun->RunEndVbn.QuadPart == Node.RunStartVbn.QuadPart);
         Node.RunStartVbn.QuadPart = LowerRun->RunStartVbn.QuadPart;
         Node.StartingLbn.QuadPart = LowerRun->StartingLbn.QuadPart;
         Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
         RtlDeleteElementGenericTable(&Mcb->Mapping->Table, LowerRun);
+        --Mcb->PairCount;
         DPRINT("Intersecting lower run found (%I64d,%I64d) Lbn: %I64d\n", LowerRun->RunStartVbn.QuadPart, LowerRun->RunEndVbn.QuadPart, LowerRun->StartingLbn.QuadPart);
     }
 
@@ -185,18 +199,21 @@ FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
     NeedleRun.RunStartVbn.QuadPart = Node.RunEndVbn.QuadPart;
     NeedleRun.RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart + 1;
     Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
-    if ((HigherRun = RtlLookupElementGenericTable(&Mcb->Mapping->Table, &NeedleRun)))
+    if ((HigherRun = RtlLookupElementGenericTable(&Mcb->Mapping->Table, &NeedleRun)) &&
+        (Node.StartingLbn.QuadPart <= HigherRun->StartingLbn.QuadPart))
     {
         ASSERT(HigherRun->RunStartVbn.QuadPart == Node.RunEndVbn.QuadPart);
         Node.RunEndVbn.QuadPart = HigherRun->RunEndVbn.QuadPart;
         Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
         RtlDeleteElementGenericTable(&Mcb->Mapping->Table, HigherRun);
+        --Mcb->PairCount;
         DPRINT("Intersecting higher run found (%I64d,%I64d) Lbn: %I64d\n", HigherRun->RunStartVbn.QuadPart, HigherRun->RunEndVbn.QuadPart, HigherRun->StartingLbn.QuadPart);
     }
     Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
 
     /* finally insert the resulting run */
     RtlInsertElementGenericTable(&Mcb->Mapping->Table, &Node, sizeof(Node), &NewElement);
+    ++Mcb->PairCount
     ASSERT(NewElement);
 
     // NB: Two consecutive runs can only be merged, if actual LBNs also match!
@@ -833,12 +850,11 @@ FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB OpaqueMcb)
 {
     PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
     LONGLONG LbnAtVbn0 = -1;
-    ULONG Nodes = RtlNumberGenericTableElements(&Mcb->Mapping->Table);
     ULONG NumberOfRuns = 0;
 
     DPRINT("FsRtlNumberOfRunsInBaseMcb(%p)\n", OpaqueMcb);
 
-    if (Nodes == 0) goto quit;
+    if (Mcb->PairCount == 0) goto quit;
 
     FsRtlLookupBaseMcbEntry(OpaqueMcb,
         0,                           /* Vbn */
@@ -851,7 +867,7 @@ FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB OpaqueMcb)
        /* Return the number of 'real' and 'hole' runs.
         * If we do not have sector 0 as 'real' emulate a 'hole' there.
         */
-    NumberOfRuns = Nodes * 2 - (LbnAtVbn0 != -1 ? 1 : 0);      /* include holes as runs */
+    NumberOfRuns = Mcb->PairCount * 2 - (LbnAtVbn0 != -1 ? 1 : 0);     /* include holes as runs */
 
 quit:
     DPRINT("FsRtlNumberOfRunsInBaseMcb(%p) = %d\n", OpaqueMcb, NumberOfRuns);
@@ -940,6 +956,7 @@ FsRtlRemoveBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
             //ASSERT(NeedleRun.RunEndVbn.QuadPart <= HaystackRun->RunEndVbn.QuadPart);
             Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
             RtlDeleteElementGenericTable(&Mcb->Mapping->Table, HaystackRun);
+            --Mcb->PairCount;
             Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
         }
     }
@@ -1055,7 +1072,10 @@ FsRtlSplitBaseMcb(IN PBASE_MCB OpaqueMcb,
     }
 
     if (InsertLowerRun)
+    {
         ExistingRun = RtlInsertElementGenericTable(&Mcb->Mapping->Table, InsertLowerRun, sizeof(*InsertLowerRun), &NewElement);
+        ++Mcb->PairCount;
+    }
 
     ASSERT(ExistingRun == NULL);