https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f9ea58dc978124b6b1e09…
commit f9ea58dc978124b6b1e090301459ce94116ba6cc
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Mon Mar 22 09:46:06 2021 +0100
Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com>
CommitDate: Wed Jun 9 11:27:18 2021 +0200
[NTOS:MM] Unconditionally delete the PFN in MiDeletePte when PTE is in transition
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 | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/ntoskrnl/mm/ARM3/virtual.c b/ntoskrnl/mm/ARM3/virtual.c
index 9396e18b05a..ace22a19887 100644
--- a/ntoskrnl/mm/ARM3/virtual.c
+++ b/ntoskrnl/mm/ARM3/virtual.c
@@ -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;