Author: jgardou
Date: Thu Jan 28 21:17:28 2016
New Revision: 70649
URL:
http://svn.reactos.org/svn/reactos?rev=70649&view=rev
Log:
[BRANCHES/TRANSITIONPTE]
- Make the thing build
Modified:
branches/TransitionPte/ntoskrnl/mm/balance.c
branches/TransitionPte/ntoskrnl/mm/pagefile.c
Modified: branches/TransitionPte/ntoskrnl/mm/balance.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/balan…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/balance.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/balance.c [iso-8859-1] Thu Jan 28 21:17:28 2016
@@ -24,14 +24,7 @@
#define TEST_PAGING
-/* TYPES ********************************************************************/
-typedef struct _MM_ALLOCATION_REQUEST
-{
- PFN_NUMBER Page;
- LIST_ENTRY ListEntry;
- KEVENT Event;
-}
-MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
+
/* GLOBALS ******************************************************************/
MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
@@ -51,15 +44,13 @@
NTAPI
MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
{
- memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
- InitializeListHead(&AllocationListHead);
- KeInitializeSpinLock(&AllocationListLock);
-
- MiNrTotalPages = NrAvailablePages;
-
- /* Set up targets. */
- MiMinimumAvailablePages = 128;
- MiMinimumPagesPerRun = 256;
+ memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
+
+ MiNrTotalPages = NrAvailablePages;
+
+ /* Set up targets. */
+ MiMinimumAvailablePages = 128;
+ MiMinimumPagesPerRun = 256;
if ((NrAvailablePages + NrSystemPages) >= 8192)
{
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3;
@@ -72,54 +63,42 @@
{
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 8;
}
- MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages - MiMinimumAvailablePages;
+ MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages - MiMinimumAvailablePages;
}
VOID
INIT_FUNCTION
NTAPI
-MmInitializeMemoryConsumer(
- ULONG Consumer,
- NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed))
-{
- MiMemoryConsumers[Consumer].Trim = Trim;
+MmInitializeMemoryConsumer(ULONG Consumer,
+ NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
+ PULONG NrFreed))
+{
+ MiMemoryConsumers[Consumer].Trim = Trim;
}
NTSTATUS
NTAPI
MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
{
- PMM_ALLOCATION_REQUEST Request;
- PLIST_ENTRY Entry;
-
- if (Page == 0)
- {
- DPRINT1("Tried to release page zero.\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- if (MmGetReferenceCountPage(Page) == 1)
- {
- if(Consumer == MC_USER) MmRemoveLRUUserPage(Page);
- (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
- if ((Entry = ExInterlockedRemoveHeadList(&AllocationListHead,
&AllocationListLock)) == NULL)
- {
- MmDereferencePage(Page);
- }
- else
- {
- Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry);
- MiZeroPhysicalPage(Page);
- Request->Page = Page;
- KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE);
- }
- }
- else
- {
- MmDereferencePage(Page);
- }
-
- return(STATUS_SUCCESS);
+ KIRQL OldIrql;
+
+ if (Page == 0)
+ {
+ DPRINT1("Tried to release page zero.\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ if (MmGetReferenceCountPage(Page) == 1)
+ {
+ if(Consumer == MC_USER) MmRemoveLRUUserPage(Page);
+ (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
+ }
+
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ MmDereferencePage(Page);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ return(STATUS_SUCCESS);
}
ULONG
@@ -214,8 +193,8 @@
static BOOLEAN
MiIsBalancerThread(VOID)
{
- return (MiBalancerThreadHandle != NULL) &&
- (PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
+ return (MiBalancerThreadHandle != NULL) &&
+ (PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
}
VOID
@@ -234,97 +213,52 @@
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
PPFN_NUMBER AllocatedPage)
{
- ULONG PagesUsed;
- PFN_NUMBER Page;
-
- /*
- * Make sure we don't exceed our individual target.
- */
- PagesUsed = InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
- if (PagesUsed > MiMemoryConsumers[Consumer].PagesTarget &&
- !MiIsBalancerThread())
- {
- MmRebalanceMemoryConsumers();
- }
-
- /*
- * Allocate always memory for the non paged pool and for the pager thread.
- */
- if ((Consumer == MC_SYSTEM) || MiIsBalancerThread())
- {
- Page = MmAllocPage(Consumer);
- if (Page == 0)
- {
- KeBugCheck(NO_PAGES_AVAILABLE);
- }
- if (Consumer == MC_USER) MmInsertLRULastUserPage(Page);
- *AllocatedPage = Page;
- if (MmAvailablePages < MiMinimumAvailablePages)
- MmRebalanceMemoryConsumers();
- return(STATUS_SUCCESS);
- }
-
- /*
- * Make sure we don't exceed global targets.
- */
- if (MmAvailablePages < MiMinimumAvailablePages)
- {
- MM_ALLOCATION_REQUEST Request;
-
- if (!CanWait)
- {
- (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
- MmRebalanceMemoryConsumers();
- return(STATUS_NO_MEMORY);
- }
-
- /* Insert an allocation request. */
- Request.Page = 0;
- KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
-
- ExInterlockedInsertTailList(&AllocationListHead, &Request.ListEntry,
&AllocationListLock);
- MmRebalanceMemoryConsumers();
-
- KeWaitForSingleObject(&Request.Event,
- 0,
- KernelMode,
- FALSE,
- NULL);
-
- Page = Request.Page;
- if (Page == 0)
- {
- KeBugCheck(NO_PAGES_AVAILABLE);
- }
-
- if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
- *AllocatedPage = Page;
-
- if (MmAvailablePages < MiMinimumAvailablePages)
- {
- MmRebalanceMemoryConsumers();
- }
-
- return(STATUS_SUCCESS);
- }
-
- /*
- * Actually allocate the page.
- */
- Page = MmAllocPage(Consumer);
- if (Page == 0)
- {
- KeBugCheck(NO_PAGES_AVAILABLE);
- }
- if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
- *AllocatedPage = Page;
-
- if (MmAvailablePages < MiMinimumAvailablePages)
- {
- MmRebalanceMemoryConsumers();
- }
-
- return(STATUS_SUCCESS);
+ ULONG PagesUsed;
+ PFN_NUMBER Page;
+ KIRQL OldIrql;
+
+ /*
+ * Make sure we don't exceed our individual target.
+ */
+ PagesUsed = InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
+ if ((PagesUsed > MiMemoryConsumers[Consumer].PagesTarget) &&
+ !MiIsBalancerThread() &&
+ (MmNumberOfPagingFiles == 0))
+ {
+ MmRebalanceMemoryConsumers();
+ }
+
+ /*
+ * Allocate always memory for the non paged pool and for the pager thread.
+ */
+ if ((Consumer == MC_SYSTEM) || MiIsBalancerThread())
+ {
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ Page = MmAllocPage(Consumer);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ if (Page == 0)
+ {
+ KeBugCheck(NO_PAGES_AVAILABLE);
+ }
+ if (Consumer == MC_USER) MmInsertLRULastUserPage(Page);
+ *AllocatedPage = Page;
+ return(STATUS_SUCCESS);
+ }
+
+ /*
+ * Actually allocate the page.
+ */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ Page = MmAllocPage(Consumer);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ if (Page == 0)
+ {
+ KeBugCheck(NO_PAGES_AVAILABLE);
+ }
+ if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
+ *AllocatedPage = Page;
+
+ return(STATUS_SUCCESS);
}
/* Old implementation of the balancer thread */
@@ -388,50 +322,146 @@
PVOID WaitObjects[2];
NTSTATUS Status;
ULONG i;
-
- WaitObjects[0] = &MiBalancerEvent;
- WaitObjects[1] = &MiBalancerTimer;
+ PVOID LastPagedPoolAddress = MmPagedPoolStart;
+#ifdef TEST_PAGING
+ PULONG PagingTestBuffer;
+ BOOLEAN TestPage = FALSE;
+#endif
+
+ WaitObjects[0] = &MiBalancerTimer;
+ WaitObjects[1] = &MiBalancerEvent;
+
+#ifdef TEST_PAGING
+ PagingTestBuffer = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'tseT');
+ DPRINT1("PagingTestBuffer: %p, PTE %p\n", PagingTestBuffer,
MiAddressToPte(PagingTestBuffer));
+ for (i = 0; i < (PAGE_SIZE / sizeof(ULONG)); i++)
+ PagingTestBuffer[i] = i;
+#endif
while (1)
{
- Status = KeWaitForMultipleObjects(2,
- WaitObjects,
- WaitAny,
- Executive,
- KernelMode,
- FALSE,
- NULL,
- NULL);
-
- if (Status == STATUS_WAIT_0 || Status == STATUS_WAIT_1)
- {
- ULONG InitialTarget = 0;
-
-#if (_MI_PAGING_LEVELS == 2)
- if (!MiIsBalancerThread())
- {
- /* Clean up the unused PDEs */
- ULONG_PTR Address;
- PEPROCESS Process = PsGetCurrentProcess();
-
- /* Acquire PFN lock */
- KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- PMMPDE pointerPde;
- for (Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS;
- Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
- Address += (PAGE_SIZE * PTE_COUNT))
+ /* For now, we only age the paged pool, with 100 pages per run. */
+ LONG Count = 100;
+ PVOID Address = LastPagedPoolAddress;
+ KIRQL OldIrql;
+ PMMPTE PointerPte;
+ PMMPDE PointerPde;
+ ULONG PdeIndex;
+ MMPTE TempPte;
+ PMMPFN Pfn1;
+ BOOLEAN Flush;
+
+ Status = KeWaitForMultipleObjects(
+ 2,
+ WaitObjects,
+ WaitAny,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ DPRINT("MM Balancer: Starting to loop.\n");
+
+ while (Count-- > 0)
+ {
+ Address = (PVOID)((ULONG_PTR) Address + PAGE_SIZE);
+
+ /* Acquire PFN lock while we are cooking */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ if (Address > MmPagedPoolEnd)
+ {
+ Address = MmPagedPoolStart;
+ }
+
+ PointerPde = MiAddressToPde(Address);
+ PointerPte = MiAddressToPte(Address);
+
+ PdeIndex = ((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) /
sizeof(MMPTE);
+
+ if (MmSystemPagePtes[PdeIndex].u.Hard.Valid == 0)
+ TempPte.u.Long = 0;
+ else
+ TempPte = *PointerPte;
+
+ if (TempPte.u.Hard.Valid == 0)
+ {
+ /* Bad luck, not a paged-in address */
+#ifdef TEST_PAGING
+ if (PointerPte == MiAddressToPte(PagingTestBuffer))
{
- if (MiQueryPageTableReferences((PVOID)Address) == 0)
+ /* Of course it should not magically become a prototype pte */
+ ASSERT(TempPte.u.Soft.Prototype == 0);
+ if (TempPte.u.Soft.Transition == 0)
{
- pointerPde = MiAddressToPde(Address);
- if (pointerPde->u.Hard.Valid)
- MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process,
NULL);
- ASSERT(pointerPde->u.Hard.Valid == 0);
+ /* It was paged out! */
+ ASSERT(TempPte.u.Soft.PageFileHigh != 0);
+ TestPage = TRUE;
}
}
- /* Release lock */
+#endif
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
- }
+ continue;
+ }
+
+ Flush = FALSE;
+
+ /* Get the Pfn */
+ Pfn1 = MI_PFN_ELEMENT(PFN_FROM_PTE(&TempPte));
+ ASSERT(Pfn1->PteAddress == PointerPte);
+ ASSERT(Pfn1->u3.e1.PrototypePte == 0);
+
+ /* First check if it was written to */
+ if (TempPte.u.Hard.Dirty)
+ Pfn1->u3.e1.Modified = 1;
+
+ /* See if it was accessed since the last time we looked */
+ if (TempPte.u.Hard.Accessed)
+ {
+ /* Yes! Mark the page as young and fresh again */
+ Pfn1->Wsle.u1.e1.Age = 0;
+ /* Tell the CPU we want to know for the next time */
+ TempPte.u.Hard.Accessed = 0;
+ MI_UPDATE_VALID_PTE(PointerPte, TempPte);
+ Flush = TRUE;
+ }
+ else if (Pfn1->Wsle.u1.e1.Age == 3)
+ {
+ /* Page is getting old: Mark the PTE as transition */
+ DPRINT1("MM Balancer: putting %p (page %x) as transition.\n",
PointerPte,
+ PFN_FROM_PTE(&TempPte));
+ TempPte.u.Hard.Valid = 0;
+ TempPte.u.Soft.Transition = 1;
+ TempPte.u.Trans.Protection = MM_READWRITE;
+ MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&TempPte));
+ MI_WRITE_INVALID_PTE(PointerPte, TempPte);
+ Flush = TRUE;
+ }
+ else
+ {
+ /* The page is just getting older */
+ Pfn1->Wsle.u1.e1.Age++;
+ }
+
+ /* Flush the TLB entry if we have to */
+ if (Flush)
+ {
+#ifdef CONFIG_SMP
+ // FIXME: Should invalidate entry in every CPU TLB
+ ASSERT(FALSE);
+#endif
+ KeInvalidateTlbEntry(Address);
+ }
+
+ /* Unlock, we're done for this address */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ }
DPRINT("MM Balancer: End of the loop.\n");
@@ -452,30 +482,20 @@
TestPage = FALSE;
}
#endif
- do
- {
- ULONG OldTarget = InitialTarget;
-
- /* Trim each consumer */
- for (i = 0; i < MC_MAXIMUM; i++)
- {
- InitialTarget = MiTrimMemoryConsumer(i, InitialTarget);
- }
-
- /* No pages left to swap! */
- if (InitialTarget != 0 &&
- InitialTarget == OldTarget)
- {
- /* Game over */
- KeBugCheck(NO_PAGES_AVAILABLE);
- }
- }
- while (InitialTarget != 0);
- }
- else
- {
- DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
+ /* Remember this for the next run */
+ LastPagedPoolAddress = Address;
+
+ if (Status == STATUS_WAIT_1)
+ {
+ /* Balancer thread was woken up by legacy MM
+ * This means we are really starving. Let's see if this still a problem
*/
+ if ((MmAvailablePages >= MmMinimumFreePages) &&
(MmNumberOfPagingFiles != 0))
+ {
+ /* Yay! No need to trust the old balancer */
+ continue;
+ }
+
+ MiRosBalancerThread();
}
}
}
@@ -485,44 +505,44 @@
NTAPI
MiInitBalancerThread(VOID)
{
- KPRIORITY Priority;
- NTSTATUS Status;
+ KPRIORITY Priority;
+ NTSTATUS Status;
#if !defined(__GNUC__)
- LARGE_INTEGER dummyJunkNeeded;
- dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
- ;
-#endif
-
-
- KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
- KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
- KeSetTimerEx(&MiBalancerTimer,
+ LARGE_INTEGER dummyJunkNeeded;
+ dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
+ ;
+#endif
+
+
+ KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
+ KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
+ KeSetTimerEx(&MiBalancerTimer,
#if defined(__GNUC__)
- (LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
+ (LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
#else
- dummyJunkNeeded,
-#endif
- 2000, /* 2 sec */
- NULL);
-
- Status = PsCreateSystemThread(&MiBalancerThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
- NULL,
- &MiBalancerThreadId,
- MiBalancerThread,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- Priority = LOW_REALTIME_PRIORITY + 1;
- NtSetInformationThread(MiBalancerThreadHandle,
- ThreadPriority,
- &Priority,
- sizeof(Priority));
+ dummyJunkNeeded,
+#endif
+ 2000, /* 2 sec */
+ NULL);
+
+ Status = PsCreateSystemThread(&MiBalancerThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ &MiBalancerThreadId,
+ MiBalancerThread,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ Priority = LOW_REALTIME_PRIORITY + 1;
+ NtSetInformationThread(MiBalancerThreadHandle,
+ ThreadPriority,
+ &Priority,
+ sizeof(Priority));
}
Modified: branches/TransitionPte/ntoskrnl/mm/pagefile.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/pagef…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/pagefile.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/pagefile.c [iso-8859-1] Thu Jan 28 21:17:28 2016
@@ -44,23 +44,24 @@
typedef struct _PAGINGFILE
{
- LIST_ENTRY PagingFileListEntry;
- PFILE_OBJECT FileObject;
- LARGE_INTEGER MaximumSize;
- LARGE_INTEGER CurrentSize;
- PFN_NUMBER FreePages;
- PFN_NUMBER UsedPages;
- PULONG AllocMap;
- KSPIN_LOCK AllocMapLock;
- ULONG AllocMapSize;
- PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
+ LIST_ENTRY PagingFileListEntry;
+ PFILE_OBJECT FileObject;
+ ULONG_PTR MaximumSize;
+ ULONG_PTR CurrentSize;
+ PFN_NUMBER FreePages;
+ PFN_NUMBER UsedPages;
+ PVOID AllocMap;
+ RTL_BITMAP AllocBitMap;
+ ULONG_PTR AllocBitMapHint;
+ KSPIN_LOCK AllocMapLock;
+ PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
}
PAGINGFILE, *PPAGINGFILE;
typedef struct _RETRIEVEL_DESCRIPTOR_LIST
{
- struct _RETRIEVEL_DESCRIPTOR_LIST* Next;
- RETRIEVAL_POINTERS_BUFFER RetrievalPointers;
+ struct _RETRIEVEL_DESCRIPTOR_LIST* Next;
+ RETRIEVAL_POINTERS_BUFFER RetrievalPointers;
}
RETRIEVEL_DESCRIPTOR_LIST, *PRETRIEVEL_DESCRIPTOR_LIST;
@@ -150,67 +151,67 @@
NTAPI
MmShowOutOfSpaceMessagePagingFile(VOID)
{
- if (!MmSwapSpaceMessage)
- {
- DPRINT1("MM: Out of swap space.\n");
- MmSwapSpaceMessage = TRUE;
- }
+ if (!MmSwapSpaceMessage)
+ {
+ DPRINT1("MM: Out of swap space.\n");
+ MmSwapSpaceMessage = TRUE;
+ }
}
static LARGE_INTEGER
MmGetOffsetPageFile(PRETRIEVAL_POINTERS_BUFFER RetrievalPointers, LARGE_INTEGER Offset)
{
- /* Simple binary search */
- ULONG first, last, mid;
- first = 0;
- last = RetrievalPointers->ExtentCount - 1;
- while (first <= last)
- {
- mid = (last - first) / 2 + first;
- if (Offset.QuadPart < RetrievalPointers->Extents[mid].NextVcn.QuadPart)
- {
- if (mid == 0)
+ /* Simple binary search */
+ ULONG first, last, mid;
+ first = 0;
+ last = RetrievalPointers->ExtentCount - 1;
+ while (first <= last)
+ {
+ mid = (last - first) / 2 + first;
+ if (Offset.QuadPart < RetrievalPointers->Extents[mid].NextVcn.QuadPart)
+ {
+ if (mid == 0)
+ {
+ Offset.QuadPart += RetrievalPointers->Extents[0].Lcn.QuadPart -
RetrievalPointers->StartingVcn.QuadPart;
+ return Offset;
+ }
+ else
+ {
+ if (Offset.QuadPart >=
RetrievalPointers->Extents[mid-1].NextVcn.QuadPart)
{
- Offset.QuadPart += RetrievalPointers->Extents[0].Lcn.QuadPart -
RetrievalPointers->StartingVcn.QuadPart;
- return Offset;
+ Offset.QuadPart += RetrievalPointers->Extents[mid].Lcn.QuadPart -
RetrievalPointers->Extents[mid-1].NextVcn.QuadPart;
+ return Offset;
}
- else
- {
- if (Offset.QuadPart >=
RetrievalPointers->Extents[mid-1].NextVcn.QuadPart)
- {
- Offset.QuadPart += RetrievalPointers->Extents[mid].Lcn.QuadPart -
RetrievalPointers->Extents[mid-1].NextVcn.QuadPart;
- return Offset;
- }
- last = mid - 1;
- }
- }
- else
- {
- if (mid == RetrievalPointers->ExtentCount - 1)
- {
- break;
- }
- if (Offset.QuadPart <
RetrievalPointers->Extents[mid+1].NextVcn.QuadPart)
- {
- Offset.QuadPart += RetrievalPointers->Extents[mid+1].Lcn.QuadPart -
RetrievalPointers->Extents[mid].NextVcn.QuadPart;
- return Offset;
- }
- first = mid + 1;
- }
- }
- KeBugCheck(MEMORY_MANAGEMENT);
+ last = mid - 1;
+ }
+ }
+ else
+ {
+ if (mid == RetrievalPointers->ExtentCount - 1)
+ {
+ break;
+ }
+ if (Offset.QuadPart < RetrievalPointers->Extents[mid+1].NextVcn.QuadPart)
+ {
+ Offset.QuadPart += RetrievalPointers->Extents[mid+1].Lcn.QuadPart -
RetrievalPointers->Extents[mid].NextVcn.QuadPart;
+ return Offset;
+ }
+ first = mid + 1;
+ }
+ }
+ KeBugCheck(MEMORY_MANAGEMENT);
#if defined(__GNUC__)
- return (LARGE_INTEGER)0LL;
+ return (LARGE_INTEGER)0LL;
#else
- {
- const LARGE_INTEGER dummy =
- {
+ {
+ const LARGE_INTEGER dummy =
+ {
0
- };
- return dummy;
- }
+ };
+ return dummy;
+ }
#endif
}
@@ -218,57 +219,12 @@
NTAPI
MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
{
- ULONG i;
- ULONG_PTR offset;
- LARGE_INTEGER file_offset;
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
- KEVENT Event;
- UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
- PMDL Mdl = (PMDL)MdlBase;
-
- DPRINT("MmWriteToSwapPage\n");
-
- if (SwapEntry == 0)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- return(STATUS_UNSUCCESSFUL);
- }
-
- i = FILE_FROM_ENTRY(SwapEntry);
- offset = OFFSET_FROM_ENTRY(SwapEntry);
-
- if (PagingFileList[i]->FileObject == NULL ||
- PagingFileList[i]->FileObject->DeviceObject == NULL)
- {
- DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
- MmBuildMdlFromPages(Mdl, &Page);
- Mdl->MdlFlags |= MDL_PAGES_LOCKED;
-
- file_offset.QuadPart = offset * PAGE_SIZE;
- file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers,
file_offset);
-
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Status = IoSynchronousPageWrite(PagingFileList[i]->FileObject,
- Mdl,
- &file_offset,
- &Event,
- &Iosb);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- Status = Iosb.Status;
- }
-
- if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
- {
- MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
- }
- return(Status);
+ MMPTE TempPte;
+
+ TempPte.u.Long = 0;
+ TempPte.u.Soft.PageFileHigh = OFFSET_FROM_ENTRY(SwapEntry);
+ TempPte.u.Soft.PageFileLow = FILE_FROM_ENTRY(SwapEntry);
+ return MiWritePageFile(Page, &TempPte);
}
@@ -276,65 +232,75 @@
NTAPI
MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
{
- return MiReadPageFile(Page, FILE_FROM_ENTRY(SwapEntry),
OFFSET_FROM_ENTRY(SwapEntry));
+ MMPTE TempPte;
+
+ TempPte.u.Long = 0;
+ TempPte.u.Soft.PageFileHigh = OFFSET_FROM_ENTRY(SwapEntry);
+ TempPte.u.Soft.PageFileLow = FILE_FROM_ENTRY(SwapEntry);
+ return MiReadPageFile(Page, &TempPte);
}
NTSTATUS
NTAPI
MiReadPageFile(
- _In_ PFN_NUMBER Page,
- _In_ ULONG PageFileIndex,
- _In_ ULONG_PTR PageFileOffset)
-{
- LARGE_INTEGER file_offset;
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
- KEVENT Event;
- UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
- PMDL Mdl = (PMDL)MdlBase;
- PPAGINGFILE PagingFile;
-
- DPRINT("MiReadSwapFile\n");
-
- if (PageFileOffset == 0)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- return(STATUS_UNSUCCESSFUL);
- }
-
- ASSERT(PageFileIndex < MAX_PAGING_FILES);
-
- PagingFile = PagingFileList[PageFileIndex];
-
- if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject
== NULL)
- {
- DPRINT1("Bad paging file %u\n", PageFileIndex);
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
- MmBuildMdlFromPages(Mdl, &Page);
- Mdl->MdlFlags |= MDL_PAGES_LOCKED;
-
- file_offset.QuadPart = PageFileOffset * PAGE_SIZE;
- file_offset = MmGetOffsetPageFile(PagingFile->RetrievalPointers, file_offset);
-
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Status = IoPageRead(PagingFile->FileObject,
- Mdl,
- &file_offset,
- &Event,
- &Iosb);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
- Status = Iosb.Status;
- }
- if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
- {
- MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
- }
- return(Status);
+ _In_ PFN_NUMBER Page,
+ _In_ const MMPTE* PointerPte
+)
+{
+ LARGE_INTEGER FileOffset;
+ IO_STATUS_BLOCK Iosb;
+ ULONG PageFileIndex = PointerPte->u.Soft.PageFileLow;
+ ULONG_PTR PageFileOffset = PointerPte->u.Soft.PageFileHigh;
+ NTSTATUS Status;
+ KEVENT Event;
+ UCHAR MdlBase[sizeof(MDL) + sizeof(PFN_NUMBER)];
+ PMDL Mdl = (PMDL)MdlBase;
+ PPAGINGFILE PagingFile;
+
+ DPRINT("MiReadPageFile\n");
+
+ if (PageFileOffset == 0)
+ {
+ KeBugCheck(MEMORY_MANAGEMENT);
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /* Normalize it */
+ PageFileOffset--;
+
+ ASSERT(PageFileIndex < MAX_PAGING_FILES);
+
+ PagingFile = PagingFileList[PageFileIndex];
+
+ if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject ==
NULL)
+ {
+ DPRINT1("Bad paging file %u\n", PageFileIndex);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+
+ MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
+ MmBuildMdlFromPages(Mdl, &Page);
+ Mdl->MdlFlags |= MDL_PAGES_LOCKED;
+
+ FileOffset.QuadPart = PageFileOffset * PAGE_SIZE;
+ FileOffset = MmGetOffsetPageFile(PagingFile->RetrievalPointers, FileOffset);
+
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Status = IoPageRead(PagingFile->FileObject,
+ Mdl,
+ &FileOffset,
+ &Event,
+ &Iosb);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = Iosb.Status;
+ }
+ if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
+ {
+ MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
+ }
+ return(Status);
}
NTSTATUS
@@ -411,19 +377,47 @@
_In_ PMMPTE PointerPte
)
{
- ULONG i;
-
- KeInitializeSpinLock(&PagingFileListLock);
-
- MiFreeSwapPages = 0;
- MiUsedSwapPages = 0;
- MiReservedSwapPages = 0;
-
- for (i = 0; i < MAX_PAGING_FILES; i++)
- {
- PagingFileList[i] = NULL;
- }
- MmNumberOfPagingFiles = 0;
+ ULONG PageFileIndex;
+ ULONG_PTR PageFileOffset;
+ PPAGINGFILE PageFile;
+
+ /* Some sanity checks */
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+ ASSERT(PointerPte->u.Soft.Transition == 0);
+ ASSERT(PointerPte->u.Soft.Prototype == 0);
+
+ /* We must hold the PFN lock */
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ PageFileIndex = PointerPte->u.Soft.PageFileLow;
+ PageFileOffset = PointerPte->u.Soft.PageFileHigh;
+
+ /* Fix up the value */
+ ASSERT(PageFileOffset != 0);
+ PageFileOffset--;
+
+ DPRINT1("Releasing page file entry %u, %lu\n", PageFileIndex,
PageFileOffset);
+
+ ASSERT(PageFileIndex < MAX_PAGING_FILES);
+
+ PageFile = PagingFileList[PageFileIndex];
+
+ /* And also lock this pagefile */
+ KeAcquireSpinLockAtDpcLevel(&PageFile->AllocMapLock);
+
+ /* It must be already in use */
+ ASSERT(RtlTestBit(&PageFile->AllocBitMap, PageFileOffset));
+ RtlClearBit(&PageFile->AllocBitMap, PageFileOffset);
+
+ /* One more */
+ PageFile->FreePages++;
+ PageFile->UsedPages--;
+
+ MiFreeSwapPages++;
+ MiUsedSwapPages--;
+
+ /* Done */
+ KeReleaseSpinLockFromDpcLevel(&PageFile->AllocMapLock);
}
NTSTATUS
@@ -432,28 +426,51 @@
_Out_ PMMPTE PointerPte
)
{
- KIRQL oldIrql;
- ULONG i, j;
-
- KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql);
-
- for (i = 0; i < PagingFile->AllocMapSize; i++)
+ ULONG PageFileIndex;
+ ULONG_PTR PageFileOffset;
+ PPAGINGFILE PageFile;
+
+ /* We must hold the PFN lock */
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ for (PageFileIndex = 0; PageFileIndex < MAX_PAGING_FILES; PageFileIndex++)
{
- for (j = 0; j < 32; j++)
- {
- if (!(PagingFile->AllocMap[i] & (1 << j)))
- {
- PagingFile->AllocMap[i] |= (1 << j);
- PagingFile->UsedPages++;
- PagingFile->FreePages--;
- KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
- return((i * 32) + j);
- }
- }
+ if (PagingFileList[PageFileIndex] == NULL)
+ continue;
+ if (PagingFileList[PageFileIndex]->FreePages != 0)
+ break;
}
- KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
- return(0xFFFFFFFF);
+ if (PageFileIndex == MAX_PAGING_FILES)
+ {
+ DPRINT1("Pagefiles are full!\n");
+ return STATUS_PAGEFILE_QUOTA;
+ }
+
+ PointerPte->u.Long = 0;
+
+ PageFile = PagingFileList[PageFileIndex];
+
+ /* And also lock this page file */
+ KeAcquireSpinLockAtDpcLevel(&PageFile->AllocMapLock);
+
+ /* Find a free entry in this page file */
+ PageFileOffset = RtlFindClearBitsAndSet(&PageFile->AllocBitMap, 1,
PageFile->AllocBitMapHint);
+
+ /* We must have found something as the file was marked as having free entries */
+ ASSERT(PageFileOffset != ~((ULONG_PTR)0));
+ PageFile->AllocBitMapHint = PageFileOffset & ~((PageFile->MaximumSize /
PAGE_SIZE) - 1);
+
+ DPRINT1("Reserving page file entry %lu, %Iu\n", PageFileIndex,
PageFileOffset);
+
+ /* Done */
+ KeReleaseSpinLockFromDpcLevel(&PageFile->AllocMapLock);
+
+ /* We rely on PageFileHigh being != 0 */
+ PointerPte->u.Soft.PageFileHigh = PageFileOffset + 1;
+ PointerPte->u.Soft.PageFileLow = PageFileIndex;
+
+ return STATUS_SUCCESS;
}
VOID
@@ -461,89 +478,70 @@
NTAPI
MmInitPagingFile(VOID)
{
- ULONG i;
- ULONG_PTR off;
- KIRQL oldIrql;
-
- i = FILE_FROM_ENTRY(Entry);
- off = OFFSET_FROM_ENTRY(Entry);
-
- KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
- if (PagingFileList[i] == NULL)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- }
- KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock);
-
- PagingFileList[i]->AllocMap[off >> 5] &= (~(1 << (off % 32)));
-
- PagingFileList[i]->FreePages++;
- PagingFileList[i]->UsedPages--;
-
- MiFreeSwapPages++;
- MiUsedSwapPages--;
-
- KeReleaseSpinLockFromDpcLevel(&PagingFileList[i]->AllocMapLock);
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+ ULONG i;
+
+ MiFreeSwapPages = 0;
+ MiUsedSwapPages = 0;
+ MiReservedSwapPages = 0;
+
+ for (i = 0; i < MAX_PAGING_FILES; i++)
+ {
+ PagingFileList[i] = NULL;
+ }
+ MmNumberOfPagingFiles = 0;
+}
+
+VOID
+NTAPI
+MmFreeSwapPage(SWAPENTRY Entry)
+{
+ MMPTE TempPte;
+ KIRQL OldIrql;
+
+ TempPte.u.Long = 0;
+ TempPte.u.Soft.PageFileLow = FILE_FROM_ENTRY(Entry);
+ TempPte.u.Soft.PageFileHigh = OFFSET_FROM_ENTRY(Entry);
+
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ MiFreePageFileEntry(&TempPte);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
SWAPENTRY
NTAPI
MmAllocSwapPage(VOID)
{
- KIRQL oldIrql;
- ULONG i;
- ULONG off;
+ MMPTE TempPte;
SWAPENTRY entry;
-
- KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
-
- if (MiFreeSwapPages == 0)
- {
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
- return(0);
- }
-
- for (i = 0; i < MAX_PAGING_FILES; i++)
- {
- if (PagingFileList[i] != NULL &&
- PagingFileList[i]->FreePages >= 1)
- {
- off = MiAllocPageFromPagingFile(PagingFileList[i]);
- if (off == 0xFFFFFFFF)
- {
- KeBugCheck(MEMORY_MANAGEMENT);
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
- return(STATUS_UNSUCCESSFUL);
- }
- MiUsedSwapPages++;
- MiFreeSwapPages--;
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-
- entry = ENTRY_FROM_FILE_OFFSET(i, off);
- return(entry);
- }
- }
-
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
- KeBugCheck(MEMORY_MANAGEMENT);
- return(0);
+ NTSTATUS Status;
+ KIRQL OldIrql;
+
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ Status = MiReservePageFileEntry(&TempPte);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ if (!NT_SUCCESS(Status))
+ return 0;
+
+ entry = ENTRY_FROM_FILE_OFFSET(TempPte.u.Soft.PageFileLow,
TempPte.u.Soft.PageFileHigh);
+
+ return entry;
}
static PRETRIEVEL_DESCRIPTOR_LIST FASTCALL
MmAllocRetrievelDescriptorList(ULONG Pairs)
{
- ULONG Size;
- PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
-
- Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * 2 * sizeof(LARGE_INTEGER);
- RetDescList = ExAllocatePool(NonPagedPool, Size);
- if (RetDescList)
- {
- RtlZeroMemory(RetDescList, Size);
- }
-
- return RetDescList;
+ ULONG Size;
+ PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
+
+ Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * 2 * sizeof(LARGE_INTEGER);
+ RetDescList = ExAllocatePool(NonPagedPool, Size);
+ if (RetDescList)
+ {
+ RtlZeroMemory(RetDescList, Size);
+ }
+
+ return RetDescList;
}
NTSTATUS NTAPI
@@ -552,340 +550,341 @@
IN PLARGE_INTEGER MaximumSize,
IN ULONG Reserved)
{
- NTSTATUS Status;
- OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE FileHandle;
- IO_STATUS_BLOCK IoStatus;
- PFILE_OBJECT FileObject;
- PPAGINGFILE PagingFile;
- KIRQL oldIrql;
- ULONG AllocMapSize;
- FILE_FS_SIZE_INFORMATION FsSizeInformation;
- PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
- PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList;
- ULONG i;
- ULONG BytesPerAllocationUnit;
- LARGE_INTEGER Vcn;
- ULONG ExtentCount;
- LARGE_INTEGER MaxVcn;
- ULONG Count;
- ULONG Size;
- KPROCESSOR_MODE PreviousMode;
- UNICODE_STRING CapturedFileName;
- LARGE_INTEGER SafeInitialSize, SafeMaximumSize;
-
- DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
- FileName, InitialSize->QuadPart);
-
- if (MmNumberOfPagingFiles >= MAX_PAGING_FILES)
- {
- return(STATUS_TOO_MANY_PAGING_FILES);
- }
-
- PreviousMode = ExGetPreviousMode();
-
- if (PreviousMode != KernelMode)
- {
- _SEH2_TRY
- {
- SafeInitialSize = ProbeForReadLargeInteger(InitialSize);
- SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
- else
- {
- SafeInitialSize = *InitialSize;
- SafeMaximumSize = *MaximumSize;
- }
-
- /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be
- smaller than the maximum */
- if (0 != SafeInitialSize.u.HighPart)
- {
- return STATUS_INVALID_PARAMETER_2;
- }
- if (0 != SafeMaximumSize.u.HighPart)
- {
- return STATUS_INVALID_PARAMETER_3;
- }
- if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart)
- {
- return STATUS_INVALID_PARAMETER_MIX;
- }
-
- Status = ProbeAndCaptureUnicodeString(&CapturedFileName,
- PreviousMode,
- FileName);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- InitializeObjectAttributes(&ObjectAttributes,
- &CapturedFileName,
- OBJ_KERNEL_HANDLE,
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE FileHandle;
+ IO_STATUS_BLOCK IoStatus;
+ PFILE_OBJECT FileObject;
+ PPAGINGFILE PagingFile;
+ KIRQL OldIrql;
+ ULONG AllocMapSize;
+ FILE_FS_SIZE_INFORMATION FsSizeInformation;
+ PRETRIEVEL_DESCRIPTOR_LIST RetDescList;
+ PRETRIEVEL_DESCRIPTOR_LIST CurrentRetDescList;
+ ULONG i;
+ ULONG BytesPerAllocationUnit;
+ LARGE_INTEGER Vcn;
+ ULONG ExtentCount;
+ LARGE_INTEGER MaxVcn;
+ ULONG Count;
+ ULONG Size;
+ KPROCESSOR_MODE PreviousMode;
+ UNICODE_STRING CapturedFileName;
+ LARGE_INTEGER SafeInitialSize, SafeMaximumSize;
+
+ DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
+ FileName, InitialSize->QuadPart);
+
+ if (MmNumberOfPagingFiles >= MAX_PAGING_FILES)
+ {
+ return(STATUS_TOO_MANY_PAGING_FILES);
+ }
+
+ PreviousMode = ExGetPreviousMode();
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ SafeInitialSize = ProbeForReadLargeInteger(InitialSize);
+ SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ SafeInitialSize = *InitialSize;
+ SafeMaximumSize = *MaximumSize;
+ }
+
+ /* Pagefiles can't be larger than 4GB and ofcourse the minimum should be
+ smaller than the maximum */
+ if (0 != SafeInitialSize.u.HighPart)
+ {
+ return STATUS_INVALID_PARAMETER_2;
+ }
+ if (0 != SafeMaximumSize.u.HighPart)
+ {
+ return STATUS_INVALID_PARAMETER_3;
+ }
+ if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart)
+ {
+ return STATUS_INVALID_PARAMETER_MIX;
+ }
+
+ Status = ProbeAndCaptureUnicodeString(&CapturedFileName,
+ PreviousMode,
+ FileName);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &CapturedFileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = IoCreateFile(&FileHandle,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatus,
+ NULL,
+ 0,
+ 0,
+ FILE_OPEN_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0,
+ CreateFileTypeNone,
+ NULL,
+ SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
+
+ ReleaseCapturedUnicodeString(&CapturedFileName,
+ PreviousMode);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Status = ZwQueryVolumeInformationFile(FileHandle,
+ &IoStatus,
+ &FsSizeInformation,
+ sizeof(FILE_FS_SIZE_INFORMATION),
+ FileFsSizeInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwClose(FileHandle);
+ return Status;
+ }
+
+ BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit *
+ FsSizeInformation.BytesPerSector;
+ /* FIXME: If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is
+ * a problem if the paging file is fragmented. Suppose the first cluster
+ * of the paging file is cluster 3042 but cluster 3043 is NOT part of the
+ * paging file but of another file. We can't write a complete page (4096
+ * bytes) to the physical location of cluster 3042 then. */
+ if (BytesPerAllocationUnit % PAGE_SIZE)
+ {
+ DPRINT1("BytesPerAllocationUnit %lu is not a multiple of PAGE_SIZE
%d\n",
+ BytesPerAllocationUnit, PAGE_SIZE);
+ ZwClose(FileHandle);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = ZwSetInformationFile(FileHandle,
+ &IoStatus,
+ &SafeInitialSize,
+ sizeof(LARGE_INTEGER),
+ FileAllocationInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwClose(FileHandle);
+ return(Status);
+ }
+
+ Status = ObReferenceObjectByHandle(FileHandle,
+ FILE_ALL_ACCESS,
+ IoFileObjectType,
+ PreviousMode,
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwClose(FileHandle);
+ return(Status);
+ }
+
+ CurrentRetDescList = RetDescList = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
+
+ if (CurrentRetDescList == NULL)
+ {
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ return(STATUS_NO_MEMORY);
+ }
+
+#if defined(__GNUC__)
+ Vcn.QuadPart = 0LL;
+#else
+ Vcn.QuadPart = 0;
+#endif
+
+ ExtentCount = 0;
+ MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) /
BytesPerAllocationUnit;
+ while(1)
+ {
+ Status = ZwFsControlFile(FileHandle,
+ 0,
NULL,
- NULL);
-
- Status = IoCreateFile(&FileHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &IoStatus,
- NULL,
- 0,
- 0,
- FILE_OPEN_IF,
- FILE_SYNCHRONOUS_IO_NONALERT,
- NULL,
- 0,
- CreateFileTypeNone,
- NULL,
- SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING);
-
- ReleaseCapturedUnicodeString(&CapturedFileName,
- PreviousMode);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- Status = ZwQueryVolumeInformationFile(FileHandle,
- &IoStatus,
- &FsSizeInformation,
- sizeof(FILE_FS_SIZE_INFORMATION),
- FileFsSizeInformation);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(FileHandle);
- return Status;
- }
-
- BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit *
- FsSizeInformation.BytesPerSector;
- /* FIXME: If we have 2048 BytesPerAllocationUnit (FAT16 < 128MB) there is
- * a problem if the paging file is fragmented. Suppose the first cluster
- * of the paging file is cluster 3042 but cluster 3043 is NOT part of the
- * paging file but of another file. We can't write a complete page (4096
- * bytes) to the physical location of cluster 3042 then. */
- if (BytesPerAllocationUnit % PAGE_SIZE)
- {
- DPRINT1("BytesPerAllocationUnit %lu is not a multiple of PAGE_SIZE
%d\n",
- BytesPerAllocationUnit, PAGE_SIZE);
- ZwClose(FileHandle);
- return STATUS_UNSUCCESSFUL;
- }
-
- Status = ZwSetInformationFile(FileHandle,
- &IoStatus,
- &SafeInitialSize,
- sizeof(LARGE_INTEGER),
- FileAllocationInformation);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(FileHandle);
- return(Status);
- }
-
- Status = ObReferenceObjectByHandle(FileHandle,
- FILE_ALL_ACCESS,
- IoFileObjectType,
- KernelMode,
- (PVOID*)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(FileHandle);
- return(Status);
- }
-
- CurrentRetDescList = RetDescList = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
-
- if (CurrentRetDescList == NULL)
- {
- ObDereferenceObject(FileObject);
- ZwClose(FileHandle);
- return(STATUS_NO_MEMORY);
- }
-
-#if defined(__GNUC__)
- Vcn.QuadPart = 0LL;
-#else
- Vcn.QuadPart = 0;
-#endif
-
- ExtentCount = 0;
- MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) /
BytesPerAllocationUnit;
- while(1)
- {
- Status = ZwFsControlFile(FileHandle,
- 0,
- NULL,
- NULL,
- &IoStatus,
- FSCTL_GET_RETRIEVAL_POINTERS,
- &Vcn,
- sizeof(LARGE_INTEGER),
- &CurrentRetDescList->RetrievalPointers,
- sizeof(RETRIEVAL_POINTERS_BUFFER) + PAIRS_PER_RUN * 2 *
sizeof(LARGE_INTEGER));
- if (!NT_SUCCESS(Status))
- {
+ NULL,
+ &IoStatus,
+ FSCTL_GET_RETRIEVAL_POINTERS,
+ &Vcn,
+ sizeof(LARGE_INTEGER),
+ &CurrentRetDescList->RetrievalPointers,
+ sizeof(RETRIEVAL_POINTERS_BUFFER) + PAIRS_PER_RUN * 2 *
sizeof(LARGE_INTEGER));
+ if (!NT_SUCCESS(Status))
+ {
+ while (RetDescList)
+ {
+ CurrentRetDescList = RetDescList;
+ RetDescList = RetDescList->Next;
+ ExFreePool(CurrentRetDescList);
+ }
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ return(Status);
+ }
+ ExtentCount += CurrentRetDescList->RetrievalPointers.ExtentCount;
+ if
(CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn.QuadPart
< MaxVcn.QuadPart)
+ {
+ CurrentRetDescList->Next = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
+ if (CurrentRetDescList->Next == NULL)
+ {
while (RetDescList)
{
- CurrentRetDescList = RetDescList;
- RetDescList = RetDescList->Next;
- ExFreePool(CurrentRetDescList);
+ CurrentRetDescList = RetDescList;
+ RetDescList = RetDescList->Next;
+ ExFreePool(CurrentRetDescList);
}
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
- return(Status);
- }
- ExtentCount += CurrentRetDescList->RetrievalPointers.ExtentCount;
- if
(CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn.QuadPart
< MaxVcn.QuadPart)
- {
- CurrentRetDescList->Next = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN);
- if (CurrentRetDescList->Next == NULL)
- {
- while (RetDescList)
- {
- CurrentRetDescList = RetDescList;
- RetDescList = RetDescList->Next;
- ExFreePool(CurrentRetDescList);
- }
- ObDereferenceObject(FileObject);
- ZwClose(FileHandle);
- return(STATUS_NO_MEMORY);
- }
- Vcn =
CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn;
- CurrentRetDescList = CurrentRetDescList->Next;
- }
- else
- {
- break;
- }
- }
-
- PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile));
- if (PagingFile == NULL)
- {
- while (RetDescList)
- {
- CurrentRetDescList = RetDescList;
- RetDescList = RetDescList->Next;
- ExFreePool(CurrentRetDescList);
- }
- ObDereferenceObject(FileObject);
- ZwClose(FileHandle);
- return(STATUS_NO_MEMORY);
- }
-
- RtlZeroMemory(PagingFile, sizeof(*PagingFile));
-
- PagingFile->FileObject = FileObject;
- PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart;
- PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart;
- PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE);
- PagingFile->UsedPages = 0;
- KeInitializeSpinLock(&PagingFile->AllocMapLock);
-
- AllocMapSize = (PagingFile->FreePages / 32) + 1;
- PagingFile->AllocMap = ExAllocatePool(NonPagedPool,
- AllocMapSize * sizeof(ULONG));
- PagingFile->AllocMapSize = AllocMapSize;
-
- if (PagingFile->AllocMap == NULL)
- {
- while (RetDescList)
- {
- CurrentRetDescList = RetDescList;
- RetDescList = RetDescList->Next;
- ExFreePool(CurrentRetDescList);
- }
- ExFreePool(PagingFile);
- ObDereferenceObject(FileObject);
- ZwClose(FileHandle);
- return(STATUS_NO_MEMORY);
- }
- DPRINT("ExtentCount: %lu\n", ExtentCount);
- Size = sizeof(RETRIEVAL_POINTERS_BUFFER) + ExtentCount * 2 * sizeof(LARGE_INTEGER);
- PagingFile->RetrievalPointers = ExAllocatePool(NonPagedPool, Size);
- if (PagingFile->RetrievalPointers == NULL)
- {
- while (RetDescList)
- {
- CurrentRetDescList = RetDescList;
- RetDescList = RetDescList->Next;
- ExFreePool(CurrentRetDescList);
- }
- ExFreePool(PagingFile->AllocMap);
- ExFreePool(PagingFile);
- ObDereferenceObject(FileObject);
- ZwClose(FileHandle);
- return(STATUS_NO_MEMORY);
- }
-
- RtlZeroMemory(PagingFile->AllocMap, AllocMapSize * sizeof(ULONG));
- RtlZeroMemory(PagingFile->RetrievalPointers, Size);
-
- Count = 0;
- PagingFile->RetrievalPointers->ExtentCount = ExtentCount;
- PagingFile->RetrievalPointers->StartingVcn =
RetDescList->RetrievalPointers.StartingVcn;
- CurrentRetDescList = RetDescList;
- while (CurrentRetDescList)
- {
- memcpy(&PagingFile->RetrievalPointers->Extents[Count],
- CurrentRetDescList->RetrievalPointers.Extents,
- CurrentRetDescList->RetrievalPointers.ExtentCount * 2 *
sizeof(LARGE_INTEGER));
- Count += CurrentRetDescList->RetrievalPointers.ExtentCount;
- RetDescList = CurrentRetDescList;
- CurrentRetDescList = CurrentRetDescList->Next;
- ExFreePool(RetDescList);
- }
-
- if (PagingFile->RetrievalPointers->ExtentCount != ExtentCount ||
- PagingFile->RetrievalPointers->Extents[ExtentCount -
1].NextVcn.QuadPart != MaxVcn.QuadPart)
- {
- ExFreePool(PagingFile->RetrievalPointers);
- ExFreePool(PagingFile->AllocMap);
- ExFreePool(PagingFile);
- ObDereferenceObject(FileObject);
- ZwClose(FileHandle);
- return(STATUS_UNSUCCESSFUL);
- }
-
- /*
- * Change the entries from lcn's to volume offset's.
- */
- PagingFile->RetrievalPointers->StartingVcn.QuadPart *= BytesPerAllocationUnit;
- for (i = 0; i < ExtentCount; i++)
- {
- PagingFile->RetrievalPointers->Extents[i].Lcn.QuadPart *=
BytesPerAllocationUnit;
- PagingFile->RetrievalPointers->Extents[i].NextVcn.QuadPart *=
BytesPerAllocationUnit;
- }
-
- KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
- for (i = 0; i < MAX_PAGING_FILES; i++)
- {
- if (PagingFileList[i] == NULL)
- {
- PagingFileList[i] = PagingFile;
- break;
- }
- }
- MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
- MmNumberOfPagingFiles++;
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
-
- ZwClose(FileHandle);
-
- MmSwapSpaceMessage = FALSE;
-
- return(STATUS_SUCCESS);
+ return(STATUS_NO_MEMORY);
+ }
+ Vcn =
CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn;
+ CurrentRetDescList = CurrentRetDescList->Next;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile));
+ if (PagingFile == NULL)
+ {
+ while (RetDescList)
+ {
+ CurrentRetDescList = RetDescList;
+ RetDescList = RetDescList->Next;
+ ExFreePool(CurrentRetDescList);
+ }
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ return(STATUS_NO_MEMORY);
+ }
+
+ RtlZeroMemory(PagingFile, sizeof(*PagingFile));
+
+ PagingFile->FileObject = FileObject;
+ PagingFile->MaximumSize = SafeMaximumSize.LowPart;
+ PagingFile->CurrentSize = SafeInitialSize.LowPart;
+ PagingFile->FreePages = (ULONG)(SafeMaximumSize.LowPart / PAGE_SIZE);
+ PagingFile->UsedPages = 0;
+ KeInitializeSpinLock(&PagingFile->AllocMapLock);
+
+ AllocMapSize = (PagingFile->FreePages / 32) + 1;
+ PagingFile->AllocMap = ExAllocatePool(NonPagedPool,
+ AllocMapSize * sizeof(ULONG));
+
+ if (PagingFile->AllocMap == NULL)
+ {
+ while (RetDescList)
+ {
+ CurrentRetDescList = RetDescList;
+ RetDescList = RetDescList->Next;
+ ExFreePool(CurrentRetDescList);
+ }
+ ExFreePool(PagingFile);
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ return(STATUS_NO_MEMORY);
+ }
+ DPRINT("ExtentCount: %lu\n", ExtentCount);
+ Size = sizeof(RETRIEVAL_POINTERS_BUFFER) + ExtentCount * 2 * sizeof(LARGE_INTEGER);
+ PagingFile->RetrievalPointers = ExAllocatePool(NonPagedPool, Size);
+ if (PagingFile->RetrievalPointers == NULL)
+ {
+ while (RetDescList)
+ {
+ CurrentRetDescList = RetDescList;
+ RetDescList = RetDescList->Next;
+ ExFreePool(CurrentRetDescList);
+ }
+ ExFreePool(PagingFile->AllocMap);
+ ExFreePool(PagingFile);
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ return(STATUS_NO_MEMORY);
+ }
+
+ RtlZeroMemory(PagingFile->RetrievalPointers, Size);
+
+ RtlInitializeBitMap(&PagingFile->AllocBitMap, PagingFile->AllocMap,
AllocMapSize * 32);
+ RtlClearAllBits(&PagingFile->AllocBitMap);
+
+ Count = 0;
+ PagingFile->RetrievalPointers->ExtentCount = ExtentCount;
+ PagingFile->RetrievalPointers->StartingVcn =
RetDescList->RetrievalPointers.StartingVcn;
+ CurrentRetDescList = RetDescList;
+ while (CurrentRetDescList)
+ {
+ memcpy(&PagingFile->RetrievalPointers->Extents[Count],
+ CurrentRetDescList->RetrievalPointers.Extents,
+ CurrentRetDescList->RetrievalPointers.ExtentCount * 2 *
sizeof(LARGE_INTEGER));
+ Count += CurrentRetDescList->RetrievalPointers.ExtentCount;
+ RetDescList = CurrentRetDescList;
+ CurrentRetDescList = CurrentRetDescList->Next;
+ ExFreePool(RetDescList);
+ }
+
+ if (PagingFile->RetrievalPointers->ExtentCount != ExtentCount ||
+ PagingFile->RetrievalPointers->Extents[ExtentCount - 1].NextVcn.QuadPart
!= MaxVcn.QuadPart)
+ {
+ ExFreePool(PagingFile->RetrievalPointers);
+ ExFreePool(PagingFile->AllocMap);
+ ExFreePool(PagingFile);
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /*
+ * Change the entries from lcn's to volume offset's.
+ */
+ PagingFile->RetrievalPointers->StartingVcn.QuadPart *= BytesPerAllocationUnit;
+ for (i = 0; i < ExtentCount; i++)
+ {
+ PagingFile->RetrievalPointers->Extents[i].Lcn.QuadPart *=
BytesPerAllocationUnit;
+ PagingFile->RetrievalPointers->Extents[i].NextVcn.QuadPart *=
BytesPerAllocationUnit;
+ }
+
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ for (i = 0; i < MAX_PAGING_FILES; i++)
+ {
+ if (PagingFileList[i] == NULL)
+ {
+ PagingFileList[i] = PagingFile;
+ break;
+ }
+ }
+ MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
+ MmNumberOfPagingFiles++;
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ ZwClose(FileHandle);
+
+ MmSwapSpaceMessage = FALSE;
+
+ return(STATUS_SUCCESS);
}
/* EOF */