Release the rmap list lock after cleaning the head entry in MmDeleteAllRmaps. This...
[reactos.git] / reactos / ntoskrnl / mm / rmap.c
index 404f1c2..402706b 100644 (file)
-/*
- *  ReactOS kernel
- *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
+/* $Id$
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
+ * COPYRIGHT:       See COPYING in the top directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/mm/rmap.c
+ * PURPOSE:         Kernel memory managment functions
  *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id: rmap.c,v 1.4 2002/05/13 18:10:40 chorns Exp $
- *
- * COPYRIGHT:   See COPYING in the top directory
- * PROJECT:     ReactOS kernel 
- * FILE:        ntoskrnl/mm/rmap.c
- * PURPOSE:     kernel memory managment functions
- * PROGRAMMER:  David Welch (welch@cwcom.net)
- *              Casper S. Hornstrup (chorns@users.sourceforge.net)
- * UPDATE HISTORY:
- *              Created 27/12/01
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/mm.h>
-#include <internal/ps.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, MmInitializeRmapList)
+#endif
+
 /* TYPES ********************************************************************/
 
 typedef struct _MM_RMAP_ENTRY
 {
-  struct _MM_RMAP_ENTRY* Next;
-  PEPROCESS Process;
-  PVOID Address;
-  ULONG ReferenceCount;
-} MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
+   struct _MM_RMAP_ENTRY* Next;
+   PEPROCESS Process;
+   PVOID Address;
+#ifdef DBG
+   PVOID Caller;
+#endif
+}
+MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
 
 /* GLOBALS ******************************************************************/
 
-static FAST_MUTEX MiRmapListLock;
+static FAST_MUTEX RmapListLock;
+static NPAGED_LOOKASIDE_LIST RmapLookasideList;
 
 /* FUNCTIONS ****************************************************************/
 
-#ifdef DBG
-
-VOID
-MiValidateRmapList(struct _MM_RMAP_ENTRY*  RmapList)
-{
-       if (RmapList != NULL)
-               {
-                       PMM_RMAP_ENTRY CurrentEntry = RmapList;
-
-                       while (CurrentEntry != NULL)
-                               {
-                                       PMM_RMAP_ENTRY Entry = RmapList;
-                                       ULONG Count = 0;
-
-                                       assertmsg(RmapList->ReferenceCount >= 0, ("Bad reference count %d for rmap entry\n",
-                                               RmapList->ReferenceCount));
-
-                                       while (Entry != NULL)
-                                               {
-                                                       if (Entry->Process == CurrentEntry->Process)
-                                                               {
-                                                                       Count++;
-                                                               }
-                                                               Entry = Entry->Next;
-                                               }
-
-                                       assertmsg(Count == 1, ("%d rmap entries for process 0x%.08x\n",
-                                               Count, CurrentEntry->Process));
-
-                                       CurrentEntry = CurrentEntry->Next;
-                               }
-               }
-}
-
-#endif /* DBG */
-
-
 VOID
+INIT_FUNCTION
+NTAPI
 MmInitializeRmapList(VOID)
 {
-  ExInitializeFastMutex(&MiRmapListLock);
+   ExInitializeFastMutex(&RmapListLock);
+   ExInitializeNPagedLookasideList (&RmapLookasideList,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    sizeof(MM_RMAP_ENTRY),
+                                    TAG_RMAP,
+                                    50);
 }
 
-
 NTSTATUS
-MmPageOutPhysicalAddress(ULONG_PTR  PhysicalAddress)
+NTAPI
+MmWritePagePhysicalAddress(PFN_TYPE Page)
 {
-  PMM_RMAP_ENTRY entry;
-  PMEMORY_AREA MemoryArea;
-  ULONG Type;
-  PVOID Address;
-  PEPROCESS Process;
-  PMM_PAGEOP PageOp;
-  LARGE_INTEGER Offset;
-  NTSTATUS Status;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-  entry = MmGetRmapListHeadPage(PhysicalAddress);
-  if (entry == NULL)
-    {
-      ExReleaseFastMutex(&MiRmapListLock);
+   PMM_RMAP_ENTRY entry;
+   PMEMORY_AREA MemoryArea;
+   PMADDRESS_SPACE AddressSpace;
+   ULONG Type;
+   PVOID Address;
+   PEPROCESS Process;
+   PMM_PAGEOP PageOp;
+   ULONG Offset;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   /*
+    * Check that the address still has a valid rmap; then reference the
+    * process so it isn't freed while we are working.
+    */
+   ExAcquireFastMutex(&RmapListLock);
+   entry = MmGetRmapListHeadPage(Page);
+   if (entry == NULL)
+   {
+      ExReleaseFastMutex(&RmapListLock);
       return(STATUS_UNSUCCESSFUL);
-    }
-  Process = entry->Process;
-  Address = entry->Address;
-  if ((((ULONG)Address) & 0xFFF) != 0)
-    {
-      KeBugCheck(0);
-    }
-
-  MmLockAddressSpace(&Process->AddressSpace);
-  MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, Address);
-  Type = MemoryArea->Type;
-  if (Type == MEMORY_AREA_SECTION_VIEW_COMMIT)
-    {
-      Offset.QuadPart = (ULONG)((Address - (ULONG)MemoryArea->BaseAddress) +
-       MemoryArea->Data.SectionData.ViewOffset);
+   }
+   Process = entry->Process;
+   Address = entry->Address;
+   if ((((ULONG_PTR)Address) & 0xFFF) != 0)
+   {
+      KEBUGCHECK(0);
+   }
+   if (Address < MmSystemRangeStart)
+   {
+      Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
+      ExReleaseFastMutex(&RmapListLock);
+      if (!NT_SUCCESS(Status))
+      {
+         return Status;
+      }
+      AddressSpace = &Process->AddressSpace;
+   }
+   else
+   {
+      ExReleaseFastMutex(&RmapListLock);
+      AddressSpace = MmGetKernelAddressSpace();
+   }
+
+   /*
+    * Lock the address space; then check that the address we are using
+    * still corresponds to a valid memory area (the page might have been
+    * freed or paged out after we read the rmap entry.)
+    */
+   MmLockAddressSpace(AddressSpace);
+   MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
+   if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
+   {
+      MmUnlockAddressSpace(AddressSpace);
+      if (Address < MmSystemRangeStart)
+      {
+         ObDereferenceObject(Process);
+      }
+      return(STATUS_UNSUCCESSFUL);
+   }
 
+   Type = MemoryArea->Type;
+   if (Type == MEMORY_AREA_SECTION_VIEW)
+   {
+      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+               + MemoryArea->Data.SectionData.ViewOffset;
       /*
        * Get or create a pageop
        */
-      PageOp = MmGetPageOp(MemoryArea, 0, 0,
-                          MemoryArea->Data.SectionData.Segment,
-                          Offset.u.LowPart, MM_PAGEOP_PAGEOUT);
+      PageOp = MmGetPageOp(MemoryArea, NULL, 0,
+                           MemoryArea->Data.SectionData.Segment,
+                           Offset, MM_PAGEOP_PAGEOUT, TRUE);
+
       if (PageOp == NULL)
-       {
-         DPRINT1("MmGetPageOp failed\n");
-         KeBugCheck(0);
-       }
-
-      if (PageOp->Thread != PsGetCurrentThread())
-       {
-         MmReleasePageOp(PageOp);
-         MmUnlockAddressSpace(&Process->AddressSpace);
-         ExReleaseFastMutex(&MiRmapListLock);
-         return(STATUS_UNSUCCESSFUL);
-       }
+      {
+         MmUnlockAddressSpace(AddressSpace);
+         if (Address < MmSystemRangeStart)
+         {
+            ObDereferenceObject(Process);
+         }
+         return(STATUS_UNSUCCESSFUL);
+      }
 
       /*
        * Release locks now we have a page op.
        */
-      MmUnlockAddressSpace(&Process->AddressSpace);
-      ExReleaseFastMutex(&MiRmapListLock);
+      MmUnlockAddressSpace(AddressSpace);
 
       /*
        * Do the actual page out work.
        */
-      Status = MmPageOutSectionView(&Process->AddressSpace, MemoryArea,
-                                   Address, PageOp);
-    }
-  else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
-    {
-      PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId,
-                          Address, NULL, 0, MM_PAGEOP_PAGEOUT);
-      if (PageOp->Thread != PsGetCurrentThread())
-       {
-         MmReleasePageOp(PageOp);
-         MmUnlockAddressSpace(&Process->AddressSpace);
-         ExReleaseFastMutex(&MiRmapListLock);
-         return(STATUS_UNSUCCESSFUL);
-       }
+      Status = MmWritePageSectionView(AddressSpace, MemoryArea,
+                                      Address, PageOp);
+   }
+   else if ((Type == MEMORY_AREA_VIRTUAL_MEMORY) || (Type == MEMORY_AREA_PEB_OR_TEB))
+   {
+      PageOp = MmGetPageOp(MemoryArea, Address < MmSystemRangeStart ? Process->UniqueProcessId : NULL,
+                           Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
+
+      if (PageOp == NULL)
+      {
+         MmUnlockAddressSpace(AddressSpace);
+         if (Address < MmSystemRangeStart)
+         {
+            ObDereferenceObject(Process);
+         }
+         return(STATUS_UNSUCCESSFUL);
+      }
 
       /*
        * Release locks now we have a page op.
        */
-      MmUnlockAddressSpace(&Process->AddressSpace);
-      ExReleaseFastMutex(&MiRmapListLock);
+      MmUnlockAddressSpace(AddressSpace);
 
       /*
        * Do the actual page out work.
        */
-      Status = MmPageOutVirtualMemory(&Process->AddressSpace, MemoryArea,
-                                     Address, PageOp);
-    }
-  else
-    {
-      KeBugCheck(0);
-    }
-  return(Status);
-}
-
-
-VOID
-MmReferenceRmap(IN PMM_RMAP_ENTRY  RmapEntry)
-{
-  InterlockedIncrement(&RmapEntry->ReferenceCount);
-}
-
-
-VOID
-MmDereferenceRmap(IN PMM_RMAP_ENTRY  RmapEntry)
-{
-       InterlockedDecrement(&RmapEntry->ReferenceCount);
-
-       assertmsg(RmapEntry->ReferenceCount > 0, ("Bad reference count (%d) for "
-         "Process (0x%.08x)  Addresss (0x%.08x)\n",
-         RmapEntry->ReferenceCount, RmapEntry->Process, RmapEntry->Address));
-}
-
-
-VOID
-MiDisableAllRmaps(IN ULONG_PTR  PhysicalAddress,
-  IN PBOOLEAN  Modified)
-{
-  PMM_RMAP_ENTRY CurrentEntry;
-  PMM_RMAP_ENTRY NextEntry;
-  BOOLEAN WasDirty;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-
-  CurrentEntry = MmGetRmapListHeadPage(PhysicalAddress);
-
-  assertmsg(CurrentEntry != NULL, ("MiDisableAllRmaps: No rmaps.\n"))
-
-  *Modified = FALSE;
-  while (CurrentEntry != NULL)
-    {
-      NextEntry = CurrentEntry->Next;
-
-                       MmLockAddressSpace(&CurrentEntry->Process->AddressSpace);
-                       
-      MmDisableVirtualMapping(CurrentEntry->Process,
-        CurrentEntry->Address,
-        &WasDirty,
-        NULL);
-
-      if (WasDirty)
-        {
-          *Modified = TRUE;
-        }
-
-      MmUnlockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      CurrentEntry = NextEntry;
-    }
-
-  ExReleaseFastMutex(&MiRmapListLock);
-}
-
-
-VOID
-MiEnableAllRmaps(IN ULONG_PTR  PhysicalAddress,
-  IN BOOLEAN  Modified)
-{
-  PMM_RMAP_ENTRY CurrentEntry;
-  PMM_RMAP_ENTRY NextEntry;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-
-  CurrentEntry = MmGetRmapListHeadPage(PhysicalAddress);
-
-  assertmsg(CurrentEntry != NULL, ("MiEnableAllRmaps: No rmaps.\n"))
-
-  while (CurrentEntry != NULL)
-    {
-      NextEntry = CurrentEntry->Next;
-
-                       MmLockAddressSpace(&CurrentEntry->Process->AddressSpace);
-                       
-      MmEnableVirtualMapping(CurrentEntry->Process,
-        CurrentEntry->Address);
-
-      if (Modified)
-        {
-          MmSetDirtyPage(CurrentEntry->Process,
-            CurrentEntry->Address);
-        }
-
-      MmUnlockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      CurrentEntry = NextEntry;
-    }
-
-  ExReleaseFastMutex(&MiRmapListLock);
-}
-
-
-VOID
-MiGetDirtyAllRmaps(IN ULONG_PTR  PhysicalAddress,
-  OUT PBOOLEAN  Dirty)
-{
-  PMM_RMAP_ENTRY CurrentEntry;
-  PMM_RMAP_ENTRY NextEntry;
-  BOOLEAN WasDirty;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-
-  CurrentEntry = MmGetRmapListHeadPage(PhysicalAddress);
-
-  assertmsg(CurrentEntry != NULL, ("MiGetDirtyAllRmaps: No rmaps.\n"))
-
-  *Dirty = FALSE;
-  while (CurrentEntry != NULL)
-    {
-      NextEntry = CurrentEntry->Next;
-
-                       MmLockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      WasDirty = MmIsPageDirty(CurrentEntry->Process,
-        CurrentEntry->Address);
-
-      MmUnlockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      if (WasDirty)
-        {
-          *Dirty = TRUE;
-        }
-
-      CurrentEntry = NextEntry;
-    }
-
-  ExReleaseFastMutex(&MiRmapListLock);
+      Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
+                                        Address, PageOp);
+   }
+   else
+   {
+      KEBUGCHECK(0);
+   }
+   if (Address < MmSystemRangeStart)
+   {
+      ObDereferenceObject(Process);
+   }
+   return(Status);
 }
 
-
-VOID
-MiSetDirtyAllRmaps(IN ULONG_PTR  PhysicalAddress,
-  IN BOOLEAN  Dirty)
+NTSTATUS
+NTAPI
+MmPageOutPhysicalAddress(PFN_TYPE Page)
 {
-  PMM_RMAP_ENTRY CurrentEntry;
-  PMM_RMAP_ENTRY NextEntry;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-
-  CurrentEntry = MmGetRmapListHeadPage(PhysicalAddress);
-
-  assertmsg(CurrentEntry != NULL, ("MiSetDirtyAllRmaps: No rmaps.\n"))
+   PMM_RMAP_ENTRY entry;
+   PMEMORY_AREA MemoryArea;
+   PMADDRESS_SPACE AddressSpace;
+   ULONG Type;
+   PVOID Address;
+   PEPROCESS Process;
+   PMM_PAGEOP PageOp;
+   ULONG Offset;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   ExAcquireFastMutex(&RmapListLock);
+   entry = MmGetRmapListHeadPage(Page);
+   if (entry == NULL || MmGetLockCountPage(Page) != 0)
+   {
+      ExReleaseFastMutex(&RmapListLock);
+      return(STATUS_UNSUCCESSFUL);
+   }
+   Process = entry->Process;
+   Address = entry->Address;
+   if ((((ULONG_PTR)Address) & 0xFFF) != 0)
+   {
+      KEBUGCHECK(0);
+   }
+
+   if (Address < MmSystemRangeStart)
+   {
+      Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
+      ExReleaseFastMutex(&RmapListLock);
+      if (!NT_SUCCESS(Status))
+      {
+         return Status;
+      }
+      AddressSpace = &Process->AddressSpace;
+   }
+   else
+   {
+      ExReleaseFastMutex(&RmapListLock);
+      AddressSpace = MmGetKernelAddressSpace();
+   }
+
+   MmLockAddressSpace(AddressSpace);
+   MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
+   if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
+   {
+      MmUnlockAddressSpace(AddressSpace);
+      if (Address < MmSystemRangeStart)
+      {
+         ObDereferenceObject(Process);
+      }
+      return(STATUS_UNSUCCESSFUL);
+   }
+   Type = MemoryArea->Type;
+   if (Type == MEMORY_AREA_SECTION_VIEW)
+   {
+      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+             + MemoryArea->Data.SectionData.ViewOffset;;
 
-  while (CurrentEntry != NULL)
-    {
-      NextEntry = CurrentEntry->Next;
+      /*
+       * Get or create a pageop
+       */
+      PageOp = MmGetPageOp(MemoryArea, NULL, 0,
+                           MemoryArea->Data.SectionData.Segment,
+                           Offset, MM_PAGEOP_PAGEOUT, TRUE);
+      if (PageOp == NULL)
+      {
+         MmUnlockAddressSpace(AddressSpace);
+         if (Address < MmSystemRangeStart)
+         {
+            ObDereferenceObject(Process);
+         }
+         return(STATUS_UNSUCCESSFUL);
+      }
 
-                       MmLockAddressSpace(&CurrentEntry->Process->AddressSpace);
-                       
-      if (Dirty)
-        {
-          MmSetDirtyPage(CurrentEntry->Process,
-            CurrentEntry->Address);
-        }
-      else
-        {
-          MmSetCleanPage(CurrentEntry->Process,
-            CurrentEntry->Address);
-        }
+      /*
+       * Release locks now we have a page op.
+       */
+      MmUnlockAddressSpace(AddressSpace);
 
-      MmUnlockAddressSpace(&CurrentEntry->Process->AddressSpace);
+      /*
+       * Do the actual page out work.
+       */
+      Status = MmPageOutSectionView(AddressSpace, MemoryArea,
+                                    Address, PageOp);
+   }
+   else if ((Type == MEMORY_AREA_VIRTUAL_MEMORY) || (Type == MEMORY_AREA_PEB_OR_TEB))
+   {
+      PageOp = MmGetPageOp(MemoryArea, Address < MmSystemRangeStart ? Process->UniqueProcessId : NULL,
+                           Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
+      if (PageOp == NULL)
+      {
+         MmUnlockAddressSpace(AddressSpace);
+         if (Address < MmSystemRangeStart)
+         {
+            ObDereferenceObject(Process);
+         }
+         return(STATUS_UNSUCCESSFUL);
+      }
 
-      CurrentEntry = NextEntry;
-    }
+      /*
+       * Release locks now we have a page op.
+       */
+      MmUnlockAddressSpace(AddressSpace);
 
-  ExReleaseFastMutex(&MiRmapListLock);
+      /*
+       * Do the actual page out work.
+       */
+      Status = MmPageOutVirtualMemory(AddressSpace, MemoryArea,
+                                      Address, PageOp);
+   }
+   else
+   {
+      KEBUGCHECK(0);
+   }
+   if (Address < MmSystemRangeStart)
+   {
+      ObDereferenceObject(Process);
+   }
+   return(Status);
 }
 
-
 VOID
-MiGetPageStateAllRmaps(IN ULONG_PTR  PhysicalAddress,
-  IN ULONG  PageState,
-  OUT PBOOLEAN  Result)
+NTAPI
+MmSetCleanAllRmaps(PFN_TYPE Page)
 {
-  PMM_RMAP_ENTRY CurrentEntry;
-  PMM_RMAP_ENTRY NextEntry;
-  ULONG State;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-
-  CurrentEntry = MmGetRmapListHeadPage(PhysicalAddress);
-
-  assertmsg(CurrentEntry != NULL, ("MiGetPageStateAllRmaps: No rmaps.\n"))
-
-  *Result = FALSE;
-  while (CurrentEntry != NULL)
-    {
-      NextEntry = CurrentEntry->Next;
-
-                       MmLockAddressSpace(&CurrentEntry->Process->AddressSpace);
-                       
-      State = MiPageState(CurrentEntry->Process,
-        CurrentEntry->Address,
-        PageState);
-
-      MmUnlockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      if (State)
-        {
-          *Result = TRUE;
-        }
-
-      CurrentEntry = NextEntry;
-    }
-
-  ExReleaseFastMutex(&MiRmapListLock);
+   PMM_RMAP_ENTRY current_entry;
+
+   ExAcquireFastMutex(&RmapListLock);
+   current_entry = MmGetRmapListHeadPage(Page);
+   if (current_entry == NULL)
+   {
+      DPRINT1("MmIsDirtyRmap: No rmaps.\n");
+      KEBUGCHECK(0);
+   }
+   while (current_entry != NULL)
+   {
+      MmSetCleanPage(current_entry->Process, current_entry->Address);
+      current_entry = current_entry->Next;
+   }
+   ExReleaseFastMutex(&RmapListLock);
 }
 
-
 VOID
-MiClearPageStateAllRmaps(IN ULONG_PTR  PhysicalAddress,
-  IN ULONG  PageState)
+NTAPI
+MmSetDirtyAllRmaps(PFN_TYPE Page)
 {
-  PMM_RMAP_ENTRY CurrentEntry;
-  PMM_RMAP_ENTRY NextEntry;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-
-  CurrentEntry = MmGetRmapListHeadPage(PhysicalAddress);
-
-  assertmsg(CurrentEntry != NULL, ("MiClearPageStateAllRmaps: No rmaps.\n"))
-
-  while (CurrentEntry != NULL)
-    {
-      NextEntry = CurrentEntry->Next;
-
-                       MmLockAddressSpace(&CurrentEntry->Process->AddressSpace);
-                       
-      MiClearPageState(CurrentEntry->Process,
-        CurrentEntry->Address,
-        PageState);
-
-      MmUnlockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      CurrentEntry = NextEntry;
-    }
-
-  ExReleaseFastMutex(&MiRmapListLock);
+   PMM_RMAP_ENTRY current_entry;
+
+   ExAcquireFastMutex(&RmapListLock);
+   current_entry = MmGetRmapListHeadPage(Page);
+   if (current_entry == NULL)
+   {
+      DPRINT1("MmIsDirtyRmap: No rmaps.\n");
+      KEBUGCHECK(0);
+   }
+   while (current_entry != NULL)
+   {
+      MmSetDirtyPage(current_entry->Process, current_entry->Address);
+      current_entry = current_entry->Next;
+   }
+   ExReleaseFastMutex(&RmapListLock);
 }
 
-
-VOID
-MiSetPageStateAllRmaps(IN ULONG_PTR  PhysicalAddress,
-  IN ULONG  PageState)
+BOOL
+NTAPI
+MmIsDirtyPageRmap(PFN_TYPE Page)
 {
-  PMM_RMAP_ENTRY CurrentEntry;
-  PMM_RMAP_ENTRY NextEntry;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-
-  CurrentEntry = MmGetRmapListHeadPage(PhysicalAddress);
-
-  assertmsg(CurrentEntry != NULL, ("MiSetPageStateAllRmaps: No rmaps.\n"))
-
-  while (CurrentEntry != NULL)
-    {
-      NextEntry = CurrentEntry->Next;
-
-                       MmLockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      MiSetPageState(CurrentEntry->Process,
-        CurrentEntry->Address,
-        PageState);
-
-                       MmUnlockAddressSpace(&CurrentEntry->Process->AddressSpace);
-
-      CurrentEntry = NextEntry;
-    }
-
-  ExReleaseFastMutex(&MiRmapListLock);
+   PMM_RMAP_ENTRY current_entry;
+
+   ExAcquireFastMutex(&RmapListLock);
+   current_entry = MmGetRmapListHeadPage(Page);
+   if (current_entry == NULL)
+   {
+      ExReleaseFastMutex(&RmapListLock);
+      return(FALSE);
+   }
+   while (current_entry != NULL)
+   {
+      if (MmIsDirtyPage(current_entry->Process, current_entry->Address))
+      {
+         ExReleaseFastMutex(&RmapListLock);
+         return(TRUE);
+      }
+      current_entry = current_entry->Next;
+   }
+   ExReleaseFastMutex(&RmapListLock);
+   return(FALSE);
 }
 
-
 VOID
-MmInsertRmap(ULONG_PTR PhysicalAddress, PEPROCESS Process, PVOID Address)
+NTAPI
+MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
+             PVOID Address)
 {
-  PMM_RMAP_ENTRY Current;
-  PMM_RMAP_ENTRY New;
-
-  Address = (PVOID)PAGE_ROUND_DOWN(Address);
-
-  New = ExAllocatePool(NonPagedPool, sizeof(MM_RMAP_ENTRY));
-  assert(New);
-  New->ReferenceCount = 1;
-  New->Address = Address;
-  New->Process = Process;
-
-  if (MmGetPhysicalAddressForProcess(Process, Address) !=
-      (ULONG_PTR)PhysicalAddress)
-    {
-      DPRINT("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
-             "address 0x%.8X\n", Process->UniqueProcessId, Address,
-             MmGetPhysicalAddressForProcess(Process, Address),
-             PhysicalAddress)
-      KeBugCheck(0);
-    }
-
-  ExAcquireFastMutex(&MiRmapListLock);
-  Current = MmGetRmapListHeadPage(PhysicalAddress);
-  New->Next = Current;
-  MmSetRmapListHeadPage(PhysicalAddress, New);
-  MmSetRmapCallback(PhysicalAddress, NULL, NULL);
-  ExReleaseFastMutex(&MiRmapListLock);
+   PMM_RMAP_ENTRY current_entry;
+   PMM_RMAP_ENTRY new_entry;
+   ULONG PrevSize;
+
+   Address = (PVOID)PAGE_ROUND_DOWN(Address);
+
+   new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
+   if (new_entry == NULL)
+   {
+      KEBUGCHECK(0);
+   }
+   new_entry->Address = Address;
+   new_entry->Process = Process;
+#ifdef DBG
+   new_entry->Caller = __builtin_return_address(0);
+#endif   
+
+   if (MmGetPfnForProcess(Process, Address) != Page)
+   {
+      DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
+              "address 0x%.8X\n", Process->UniqueProcessId, Address,
+              MmGetPfnForProcess(Process, Address) << PAGE_SHIFT,
+              Page << PAGE_SHIFT);
+      KEBUGCHECK(0);
+   }
+
+   ExAcquireFastMutex(&RmapListLock);
+   current_entry = MmGetRmapListHeadPage(Page);
+   new_entry->Next = current_entry;
+#ifdef DBG
+   while (current_entry)
+   {
+      if (current_entry->Address == new_entry->Address && current_entry->Process == new_entry->Process)
+      {
+          DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n    current caller ", 
+                   current_entry->Address);
+          KeRosPrintAddress(new_entry->Caller);
+          DbgPrint("\n    previous caller ");
+          KeRosPrintAddress(current_entry->Caller);
+          DbgPrint("\n");
+          KeBugCheck(0);
+      }
+      current_entry = current_entry->Next;
+   }
+#endif
+   MmSetRmapListHeadPage(Page, new_entry);
+   ExReleaseFastMutex(&RmapListLock);
+   if (Process == NULL)
+   {
+      Process = PsInitialSystemProcess;
+   }
+   if (Process)
+   {
+      PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE);
+      if (PrevSize >= Process->Vm.PeakWorkingSetSize)
+      {
+         Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE;
+      }
+   }
 }
 
 VOID
-MmDeleteAllRmaps(ULONG_PTR PhysicalAddress, PVOID Context,
-                VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
-                                      PVOID Address))
+NTAPI
+MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context,
+                 VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
+                                       PVOID Address))
 {
-  PMM_RMAP_ENTRY current_entry;
-  PMM_RMAP_ENTRY previous_entry;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-  current_entry = MmGetRmapListHeadPage(PhysicalAddress);
-  if (current_entry == NULL)
-    {
+   PMM_RMAP_ENTRY current_entry;
+   PMM_RMAP_ENTRY previous_entry;
+   PEPROCESS Process;
+
+   ExAcquireFastMutex(&RmapListLock);
+   current_entry = MmGetRmapListHeadPage(Page);
+   if (current_entry == NULL)
+   {
       DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
-      KeBugCheck(0);
-    }
-  while (current_entry != NULL)
-    {
+      KEBUGCHECK(0);
+   }
+   MmSetRmapListHeadPage(Page, NULL);
+   ExReleaseFastMutex(&RmapListLock);
+   while (current_entry != NULL)
+   {
       previous_entry = current_entry;
       current_entry = current_entry->Next;
       if (DeleteMapping)
-       {
-         DeleteMapping(Context, previous_entry->Process,
-                       previous_entry->Address);
-       }
-      ExFreePool(previous_entry);
-    }
-  MmSetRmapListHeadPage(PhysicalAddress, NULL);
-  ExReleaseFastMutex(&MiRmapListLock);
+      {
+         DeleteMapping(Context, previous_entry->Process,
+                       previous_entry->Address);
+      }
+      Process = previous_entry->Process;
+      ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
+      if (Process == NULL)
+      {
+         Process = PsInitialSystemProcess;
+      }
+      if (Process)
+      {
+         InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
+      }
+   }
 }
 
-
 VOID
-MmDeleteRmap(IN ULONG_PTR  PhysicalAddress,
-  IN PEPROCESS  Process,
-  IN PVOID  Address)
+NTAPI
+MmDeleteRmap(PFN_TYPE Page, PEPROCESS Process,
+             PVOID Address)
 {
-  PMM_RMAP_ENTRY Current;
-  PMM_RMAP_ENTRY Previous;
-
-  ExAcquireFastMutex(&MiRmapListLock);
-  Previous = NULL;
-  Current = MmGetRmapListHeadPage(PhysicalAddress);
-  while (Current != NULL)
-    {
-      if (Current->Process == Process && Current->Address == Address)
-        {
-          Current->ReferenceCount--;
-                                 assertmsg(Current->ReferenceCount == 0, ("Rmap has outstanding references (%d) for Page (0x%.08x)  "
-            "Process (0x%.08x)  Addresss (0x%.08x)\n",
-            Current->ReferenceCount, PhysicalAddress, Process, Address));
-
-                                 if (Previous == NULL)
-                                   {
-                                     MmSetRmapListHeadPage(PhysicalAddress, Current->Next);
-                                     ExReleaseFastMutex(&MiRmapListLock);
-                                     ExFreePool(Current);
-                                   }
-                                 else
-                                   {
-                                     Previous->Next = Current->Next;
-                                     ExReleaseFastMutex(&MiRmapListLock);
-                                     ExFreePool(Current);
-                                   }
-                                 return;
-             }
-      Previous = Current;
-      Current = Current->Next;
-    }
-  assertmsg(FALSE, ("No rmap entry for Page (0x%.08x) Process (0x%.08x)  Addresss (0x%.08x)\n",
-    PhysicalAddress, Process, Address));
+   PMM_RMAP_ENTRY current_entry, previous_entry;
+
+   ExAcquireFastMutex(&RmapListLock);
+   previous_entry = NULL;
+   current_entry = MmGetRmapListHeadPage(Page);
+   while (current_entry != NULL)
+   {
+      if (current_entry->Process == Process &&
+            current_entry->Address == Address)
+      {
+         if (previous_entry == NULL)
+         {
+            MmSetRmapListHeadPage(Page, current_entry->Next);
+         }
+         else
+         {
+            previous_entry->Next = current_entry->Next;
+         }
+         ExReleaseFastMutex(&RmapListLock);
+         ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
+        if (Process == NULL)
+        {
+           Process = PsInitialSystemProcess;
+        }
+        if (Process)
+        {
+            InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
+        }
+         return;
+      }
+      previous_entry = current_entry;
+      current_entry = current_entry->Next;
+   }
+   KEBUGCHECK(0);
 }