[NTOS:MM] Unconditionally delete the PFN in MiDeletePte when PTE is in transition
authorJérôme Gardou <jerome.gardou@reactos.org>
Mon, 22 Mar 2021 08:46:06 +0000 (09:46 +0100)
committerJérôme Gardou <zefklop@users.noreply.github.com>
Wed, 9 Jun 2021 09:27:18 +0000 (11:27 +0200)
When we will have a modified page writer, it will have to know if the written
page is stale when being done, and act accordingly.

CORE-8552

ntoskrnl/mm/ARM3/virtual.c

index 9396e18..ace22a1 100644 (file)
@@ -401,6 +401,12 @@ MiDeletePte(IN PMMPTE PointerPte,
     /* PFN lock must be held */
     MI_ASSERT_PFN_LOCK_HELD();
 
+    /* WorkingSet must be exclusively locked */
+    ASSERT(MM_ANY_WS_LOCK_HELD_EXCLUSIVE(PsGetCurrentThread()));
+
+    /* This must be current process. */
+    ASSERT(CurrentProcess == PsGetCurrentProcess());
+
     /* Capture the PTE */
     TempPte = *PointerPte;
 
@@ -428,9 +434,16 @@ MiDeletePte(IN PMMPTE PointerPte,
             /* Drop the reference on the page table. */
             MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
 
+            /* In case of shared page, the prototype PTE must be in transition, not the process one */
             ASSERT(Pfn1->u3.e1.PrototypePte == 0);
 
-            /* Make the page free. For prototypes, it will be made free when deleting the section object */
+            /* Delete the PFN */
+            MI_SET_PFN_DELETED(Pfn1);
+
+            /* It must be either free (refcount == 0) or being written (refcount == 1) */
+            ASSERT(Pfn1->u3.e2.ReferenceCount == Pfn1->u3.e1.WriteInProgress);
+
+            /* See if we must free it ourselves, or if it will be freed once I/O is over */
             if (Pfn1->u3.e2.ReferenceCount == 0)
             {
                 /* And it should be in standby or modified list */
@@ -441,7 +454,6 @@ MiDeletePte(IN PMMPTE PointerPte,
                 Pfn1->u3.e2.ReferenceCount++;
 
                 /* This will put it back in free list and clean properly up */
-                MI_SET_PFN_DELETED(Pfn1);
                 MiDecrementReferenceCount(Pfn1, PageFrameIndex);
             }
             return;