https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3d4cf8d2d8327c8392fdf4cf589508f58808de83

commit 3d4cf8d2d8327c8392fdf4cf589508f58808de83
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Mon Nov 30 12:42:33 2020 +0100
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Tue Dec 8 11:48:00 2020 +0100

    [NTOS/FSRTL] Fix MCB tests
    
     - Fix behaviour when adding or removing entries in the middle of an 
existing run
     - Do not touch output parameters when failing, caller might rely on this.
---
 ntoskrnl/fsrtl/largemcb.c | 73 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 58 insertions(+), 15 deletions(-)

diff --git a/ntoskrnl/fsrtl/largemcb.c b/ntoskrnl/fsrtl/largemcb.c
index 0ce7949e5ff..7c2749ea810 100644
--- a/ntoskrnl/fsrtl/largemcb.c
+++ b/ntoskrnl/fsrtl/largemcb.c
@@ -143,7 +143,7 @@ FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
     LARGE_MCB_MAPPING_ENTRY Node, NeedleRun;
     PLARGE_MCB_MAPPING_ENTRY LowerRun, HigherRun;
     BOOLEAN NewElement;
-    LONGLONG IntLbn;
+    LONGLONG IntLbn, IntSectorCount;
 
     DPRINT("FsRtlAddBaseMcbEntry(%p, %I64d, %I64d, %I64d)\n", OpaqueMcb, Vbn, 
Lbn, SectorCount);
 
@@ -159,7 +159,7 @@ FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
         goto quit;
     }
 
-    IntResult = FsRtlLookupBaseMcbEntry(OpaqueMcb, Vbn, &IntLbn, NULL, NULL, 
NULL, NULL);
+    IntResult = FsRtlLookupBaseMcbEntry(OpaqueMcb, Vbn, &IntLbn, 
&IntSectorCount, NULL, NULL, NULL);
     if (IntResult)
     {
         if (IntLbn != -1 && IntLbn != Lbn)
@@ -167,6 +167,12 @@ FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
             Result = FALSE;
             goto quit;
         }
+
+        if ((IntLbn != -1) && (IntSectorCount >= SectorCount))
+        {
+            /* This is a no-op */
+            goto quit;
+        }
     }
 
     /* clean any possible previous entries in our range */
@@ -314,7 +320,7 @@ FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb,
  * Value less or equal to %0 is forbidden; FIXME: Is the reject of %0 W32 
compliant?
  *
  * Retrieves the parameters of the specified run with index @RunIndex.
- * 
+ *
  * Mapping %0 always starts at virtual block %0, either as 'hole' or as 'real' 
mapping.
  * libcaptive does not store 'hole' information to its #GTree.
  * Last run is always a 'real' run. 'hole' runs appear as mapping to constant 
@Lbn value %-1.
@@ -336,7 +342,7 @@ FsRtlGetNextBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
     ULONGLONG LastVbn = 0;
     ULONGLONG LastSectorCount = 0;
 
-    // Traverse the tree 
+    // Traverse the tree
     for (Run = 
(PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, TRUE);
     Run;
         Run = 
(PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, FALSE))
@@ -373,11 +379,6 @@ FsRtlGetNextBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
         LastSectorCount = Run->RunEndVbn.QuadPart - Run->RunStartVbn.QuadPart;
     }
 
-    // these values are meaningless when returning false (but setting them can 
be helpful for debugging purposes)
-    *Vbn = 0xdeadbeef;
-    *Lbn = 0xdeadbeef;
-    *SectorCount = 0xdeadbeef;
-
 quit:
     DPRINT("FsRtlGetNextBaseMcbEntry(%p, %d, %p, %p, %p) = %d (%I64d, %I64d, 
%I64d)\n", Mcb, RunIndex, Vbn, Lbn, SectorCount, Result, *Vbn, *Lbn, 
*SectorCount);
     return Result;
@@ -542,11 +543,6 @@ FsRtlLookupBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
         }
     }
 
-    if (Lbn)
-        *Lbn = -1;
-    if (StartingLbn)
-        *StartingLbn = -1;
-
 quit:
     DPRINT("FsRtlLookupBaseMcbEntry(%p, %I64d, %p, %p, %p, %p, %p) = %d 
(%I64d, %I64d, %I64d, %I64d, %d)\n",
            OpaqueMcb, Vbn, Lbn, SectorCountFromLbn, StartingLbn, 
SectorCountFromStartingLbn, Index, Result,
@@ -821,7 +817,7 @@ FsRtlRemoveBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
 
     NeedleRun.RunStartVbn.QuadPart = Vbn;
     NeedleRun.RunEndVbn.QuadPart = Vbn + SectorCount;
-    NeedleRun.StartingLbn.QuadPart = ~0ULL;
+    NeedleRun.StartingLbn.QuadPart = -1;
 
     /* adjust/destroy all intersecting ranges */
     Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
@@ -829,13 +825,60 @@ FsRtlRemoveBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
     {
         if (HaystackRun->RunStartVbn.QuadPart < NeedleRun.RunStartVbn.QuadPart)
         {
+            LONGLONG HaystackRunEnd = HaystackRun->RunEndVbn.QuadPart;
             ASSERT(HaystackRun->RunEndVbn.QuadPart > 
NeedleRun.RunStartVbn.QuadPart);
+
             HaystackRun->RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart;
+
+            if (HaystackRunEnd > NeedleRun.RunEndVbn.QuadPart)
+            {
+                /* The run we are deleting is included in the run we just 
truncated.
+                 * Add the tail back. */
+                LARGE_MCB_MAPPING_ENTRY TailRun;
+                BOOLEAN NewElement;
+
+                TailRun.RunStartVbn.QuadPart = NeedleRun.RunEndVbn.QuadPart;
+                TailRun.RunEndVbn.QuadPart = HaystackRunEnd;
+                TailRun.StartingLbn.QuadPart = 
HaystackRun->StartingLbn.QuadPart + (NeedleRun.RunEndVbn.QuadPart - 
HaystackRun->RunStartVbn.QuadPart);
+
+                Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
+
+                RtlInsertElementGenericTable(&Mcb->Mapping->Table, &TailRun, 
sizeof(TailRun), &NewElement);
+                ++Mcb->PairCount;
+                ASSERT(NewElement);
+
+                Mcb->Mapping->Table.CompareRoutine = 
McbMappingIntersectCompare;
+            }
         }
         else if (HaystackRun->RunEndVbn.QuadPart > 
NeedleRun.RunEndVbn.QuadPart)
         {
+            LONGLONG HaystackRunStart = HaystackRun->RunStartVbn.QuadPart;
+            LONGLONG HaystackStartingLbn = HaystackRun->StartingLbn.QuadPart;
+
             ASSERT(HaystackRun->RunStartVbn.QuadPart < 
NeedleRun.RunEndVbn.QuadPart);
             HaystackRun->RunStartVbn.QuadPart = NeedleRun.RunEndVbn.QuadPart;
+            /* Adjust the starting LBN */
+            HaystackRun->StartingLbn.QuadPart += NeedleRun.RunEndVbn.QuadPart 
- HaystackRunStart;
+
+            if (HaystackRunStart < NeedleRun.RunStartVbn.QuadPart)
+            {
+                /* The run we are deleting is included in the run we just 
truncated.
+                 * Add the head back. */
+                LARGE_MCB_MAPPING_ENTRY HeadRun;
+                BOOLEAN NewElement;
+
+                HeadRun.RunStartVbn.QuadPart = HaystackRunStart;
+                HeadRun.RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart;
+                HeadRun.StartingLbn.QuadPart = HaystackStartingLbn;
+
+                Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
+
+                RtlInsertElementGenericTable(&Mcb->Mapping->Table, &HeadRun, 
sizeof(HeadRun), &NewElement);
+                ++Mcb->PairCount;
+                ASSERT(NewElement);
+
+                Mcb->Mapping->Table.CompareRoutine = 
McbMappingIntersectCompare;
+            }
         }
         else
         {

Reply via email to