Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

modwrite.c File Reference

#include "mi.h"

Go to the source code of this file.

Classes

struct  _MMWORK_CONTEXT
struct  _MM_WRITE_CLUSTER

Defines

#define ONEMB_IN_PAGES   ((1024 * 1024) / PAGE_SIZE)
#define MI_PAGEFILE_FULL_CHARGE   100
#define MINIMUM_PAGE_FILE_SIZE   ((ULONG)(256*PAGE_SIZE))
#define ROUND_UP(VALUE, ROUND)

Typedefs

typedef enum _MODIFIED_WRITER_OBJECT MODIFIED_WRITER_OBJECT
typedef _MMWORK_CONTEXT MMWORK_CONTEXT
typedef _MMWORK_CONTEXTPMMWORK_CONTEXT
typedef _MM_WRITE_CLUSTER MM_WRITE_CLUSTER
typedef _MM_WRITE_CLUSTERPMM_WRITE_CLUSTER

Enumerations

enum  _MODIFIED_WRITER_OBJECT { NormalCase, MappedPagesNeedWriting, ModifiedWriterMaximumObject }

Functions

NTSTATUS MiCheckForCrashDump (PFILE_OBJECT File, IN ULONG FileNumber)
VOID MiCrashDumpWorker (IN PVOID Context)
VOID MiClusterWritePages (IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex, IN PMM_WRITE_CLUSTER WriteCluster, IN ULONG Size)
VOID MiExtendPagingFileMaximum (IN ULONG PageFileNumber, IN PRTL_BITMAP NewBitmap)
NTSTATUS MiCheckPageFileMapping (IN PFILE_OBJECT File)
VOID MiInsertPageFileInList (VOID)
VOID MiGatherMappedPages (IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
VOID MiGatherPagefilePages (IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
VOID MiPageFileFull (VOID)
LOGICAL MiCauseOverCommitPopup (IN SIZE_T NumberOfPages, IN ULONG Extension)
VOID MiModifiedPageWriterWorker (VOID)
SIZE_T MiAttemptPageFileExtension (IN ULONG PageFileNumber, IN SIZE_T ExtendSize, IN SIZE_T Maximum)
NTSTATUS MiCheckPageFilePath (PFILE_OBJECT FileObject)
VOID MiReleaseModifiedWriter (VOID)
NTSTATUS NtCreatePagingFile (IN PUNICODE_STRING PageFileName, IN PLARGE_INTEGER MinimumSize, IN PLARGE_INTEGER MaximumSize, IN ULONG Priority OPTIONAL)
NTSTATUS MmGetCrashDumpInformation (IN PSYSTEM_CRASH_DUMP_INFORMATION CrashInfo)
NTSTATUS MmGetCrashDumpStateInformation (IN PSYSTEM_CRASH_STATE_INFORMATION CrashInfo)
SIZE_T MiExtendPagingFiles (IN PMMPAGE_FILE_EXPANSION PageExpand)
VOID MiContractPagingFiles (VOID)
VOID MiAttemptPageFileReduction (VOID)
VOID MiWriteComplete (IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus, IN ULONG Reserved)
LOGICAL MiCancelWriteOfMappedPfn (IN PFN_NUMBER PageToStop)
VOID MiModifiedPageWriter (IN PVOID StartContext)
VOID MiModifiedPageWriterTimerDispatch (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
VOID MiMappedPageWriter (IN PVOID StartContext)
BOOLEAN MmDisableModifiedWriteOfSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer)
NTSTATUS MmGetPageFileInformation (OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG Length)
VOID MiPageFileFull ()
VOID MiFlushAllPages (VOID)
LOGICAL MiIssuePageExtendRequest (IN PMMPAGE_FILE_EXPANSION PageExtend)
VOID MiIssuePageExtendRequestNoWait (IN PFN_NUMBER SizeInPages)

Variables

ULONG MmWriteAllModifiedPages
LOGICAL MiFirstPageFileCreatedAndReady = FALSE
PSECTION MmCrashDumpSection
POBJECT_TYPE IoFileObjectType
HANDLE PspInitialSystemProcessHandle
LIST_ENTRY MmMappedPageWriterList
KEVENT MmMappedPageWriterEvent
KEVENT MmMappedFileIoComplete
ULONG MmSystemShutdown
SIZE_T MmOverCommit2
SIZE_T MmPageFileFullExtendPages
ULONG MmPageFileFullExtendCount
SIZE_T MiPageFileFullCharge
LOGICAL MmPageFileFullPopupShown = FALSE
ULONG MmModNoWriteInsert
BOOLEAN MmSystemPageFileLocated
PFN_NUMBER MmMoreThanEnoughFreePages


Define Documentation

#define MI_PAGEFILE_FULL_CHARGE   100
 

Definition at line 102 of file modwrite.c.

Referenced by MiPageFileFull().

#define MINIMUM_PAGE_FILE_SIZE   ((ULONG)(256*PAGE_SIZE))
 

Definition at line 151 of file modwrite.c.

Referenced by NtCreatePagingFile().

#define ONEMB_IN_PAGES   ((1024 * 1024) / PAGE_SIZE)
 

Definition at line 45 of file modwrite.c.

Referenced by MiIssuePageExtendRequestNoWait().

#define ROUND_UP VALUE,
ROUND   ) 
 

Value:

((ULONG)(((ULONG)VALUE + \ ((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L))))

Definition at line 4463 of file modwrite.c.


Typedef Documentation

typedef struct _MM_WRITE_CLUSTER MM_WRITE_CLUSTER
 

typedef struct _MMWORK_CONTEXT MMWORK_CONTEXT
 

typedef enum _MODIFIED_WRITER_OBJECT MODIFIED_WRITER_OBJECT
 

typedef struct _MM_WRITE_CLUSTER * PMM_WRITE_CLUSTER
 

typedef struct _MMWORK_CONTEXT * PMMWORK_CONTEXT
 

Referenced by MiCrashDumpWorker().


Enumeration Type Documentation

enum _MODIFIED_WRITER_OBJECT
 

Enumeration values:
NormalCase 
MappedPagesNeedWriting 
ModifiedWriterMaximumObject 

Definition at line 24 of file modwrite.c.


Function Documentation

SIZE_T MiAttemptPageFileExtension IN ULONG  PageFileNumber,
IN SIZE_T  ExtendSize,
IN SIZE_T  Maximum
 

Definition at line 1485 of file modwrite.c.

References ASSERT, DISPATCH_LEVEL, FALSE, File, _MMPAGING_FILE::FreeSpace, IoQueryVolumeInformation(), IoSetInformation(), LOCK_PFN, _MMPAGING_FILE::MaximumSize, MiUpdateModifiedWriterMdls(), MmMinimumFreeDiskSpace, MmPageFileExtension, MmPagingFile, NT_SUCCESS, NTSTATUS(), PAGE_SHIFT, PAGE_SIZE, RtlClearBits(), RtlExtendedIntegerMultiply(), Size, _MMPAGING_FILE::Size, and UNLOCK_PFN.

Referenced by MiExtendPagingFiles().

01493 : 01494 01495 This routine attempts to extend the specified page file by 01496 ExtendSize. 01497 01498 Arguments: 01499 01500 PageFileNumber - Supplies the page file number to attempt to extend. 01501 01502 ExtendSize - Supplies the number of pages to extend the file by. 01503 01504 Maximum - Supplies TRUE if the page file should be extended 01505 by the maximum size possible, but not to exceed 01506 ExtendSize. 01507 01508 Return Value: 01509 01510 Returns the size of the extension. Zero if the page file cannot 01511 be extended. 01512 01513 --*/ 01514 01515 { 01516 01517 NTSTATUS status; 01518 FILE_FS_SIZE_INFORMATION FileInfo; 01519 FILE_END_OF_FILE_INFORMATION EndOfFileInformation; 01520 KIRQL OldIrql; 01521 ULONG AllocSize; 01522 PFN_NUMBER AdditionalAllocation; 01523 ULONG ReturnedLength; 01524 PFN_NUMBER PagesAvailable; 01525 SIZE_T SizeToExtend; 01526 LARGE_INTEGER BytesAvailable; 01527 01528 // 01529 // Check to see if this page file is at the maximum. 01530 // 01531 01532 if (MmPagingFile[PageFileNumber]->Size == 01533 MmPagingFile[PageFileNumber]->MaximumSize) { 01534 return 0; 01535 } 01536 01537 // 01538 // Find out how much free space is on this volume. 01539 // 01540 01541 status = IoQueryVolumeInformation ( MmPagingFile[PageFileNumber]->File, 01542 FileFsSizeInformation, 01543 sizeof(FileInfo), 01544 &FileInfo, 01545 &ReturnedLength 01546 ); 01547 01548 if (!NT_SUCCESS (status)) { 01549 01550 // 01551 // The volume query did not succeed - return 0 indicating 01552 // the paging file was not extended. 01553 // 01554 01555 return 0; 01556 } 01557 01558 // 01559 // Always attempt to extend by at least megabyte. 01560 // 01561 01562 SizeToExtend = ExtendSize; 01563 if (ExtendSize < MmPageFileExtension) { 01564 SizeToExtend = MmPageFileExtension; 01565 } 01566 01567 // 01568 // Don't go over the maximum size for the paging file. 01569 // 01570 01571 if ((SizeToExtend + MmPagingFile[PageFileNumber]->Size) > 01572 MmPagingFile[PageFileNumber]->MaximumSize) { 01573 SizeToExtend = (MmPagingFile[PageFileNumber]->MaximumSize - 01574 MmPagingFile[PageFileNumber]->Size); 01575 } 01576 01577 if ((Maximum == FALSE) && (SizeToExtend < ExtendSize)) { 01578 01579 // 01580 // Can't meet the requirement. 01581 // 01582 01583 return 0; 01584 } 01585 // 01586 // See if there is enough space on the volume for the extension. 01587 // 01588 01589 AllocSize = FileInfo.SectorsPerAllocationUnit * FileInfo.BytesPerSector; 01590 01591 BytesAvailable = RtlExtendedIntegerMultiply ( 01592 FileInfo.AvailableAllocationUnits, 01593 AllocSize); 01594 01595 if ((UINT64)BytesAvailable.QuadPart > (UINT64)MmMinimumFreeDiskSpace) { 01596 01597 BytesAvailable.QuadPart = BytesAvailable.QuadPart - 01598 (LONGLONG)MmMinimumFreeDiskSpace; 01599 01600 if ((UINT64)BytesAvailable.QuadPart > (UINT64)(SizeToExtend << PAGE_SHIFT)) { 01601 BytesAvailable.QuadPart = (LONGLONG)(SizeToExtend << PAGE_SHIFT); 01602 } 01603 01604 PagesAvailable = (PFN_NUMBER)(BytesAvailable.QuadPart >> PAGE_SHIFT); 01605 01606 if ((Maximum == FALSE) && (PagesAvailable < ExtendSize)) { 01607 01608 // 01609 // Can't satisfy this requirement. 01610 // 01611 01612 return 0; 01613 } 01614 01615 } else { 01616 01617 // 01618 // Not enough space is available. 01619 // 01620 01621 return 0; 01622 } 01623 01624 #if defined (_WIN64) || defined (_X86PAE_) 01625 EndOfFileInformation.EndOfFile.QuadPart = 01626 ((ULONG64)MmPagingFile[PageFileNumber]->Size + PagesAvailable) * PAGE_SIZE; 01627 #else 01628 EndOfFileInformation.EndOfFile.LowPart = 01629 (MmPagingFile[PageFileNumber]->Size + PagesAvailable) * PAGE_SIZE; 01630 01631 // 01632 // Set high part to zero as paging files are limited to 4GB. 01633 // 01634 01635 EndOfFileInformation.EndOfFile.HighPart = 0; 01636 #endif 01637 01638 // 01639 // Attempt to extend the file by setting the end-of-file position. 01640 // 01641 01642 ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL); 01643 status = IoSetInformation (MmPagingFile[PageFileNumber]->File, 01644 FileEndOfFileInformation, 01645 sizeof(FILE_END_OF_FILE_INFORMATION), 01646 &EndOfFileInformation 01647 ); 01648 01649 if (status != STATUS_SUCCESS) { 01650 KdPrint(("MM MODWRITE: page file extension failed %lx %lx\n",status)); 01651 return 0; 01652 } 01653 01654 // 01655 // Clear bits within the paging file bitmap to allow the extension 01656 // to take effect. 01657 // 01658 01659 LOCK_PFN (OldIrql); 01660 01661 ASSERT (RtlCheckBit (MmPagingFile[PageFileNumber]->Bitmap, 01662 MmPagingFile[PageFileNumber]->Size) == 1); 01663 01664 AdditionalAllocation = PagesAvailable; 01665 01666 RtlClearBits (MmPagingFile[PageFileNumber]->Bitmap, 01667 (ULONG)MmPagingFile[PageFileNumber]->Size, 01668 (ULONG)AdditionalAllocation ); 01669 01670 MmPagingFile[PageFileNumber]->Size += AdditionalAllocation; 01671 MmPagingFile[PageFileNumber]->FreeSpace += AdditionalAllocation; 01672 01673 MiUpdateModifiedWriterMdls (PageFileNumber); 01674 01675 UNLOCK_PFN (OldIrql); 01676 01677 return AdditionalAllocation; 01678 }

VOID MiAttemptPageFileReduction VOID   ) 
 

Definition at line 1940 of file modwrite.c.

References ASSERT, DbgPrint, DISPATCH_LEVEL, _MMPAGING_FILE::Entry, FALSE, File, _MMPAGING_FILE::FreeSpace, IoSetInformation(), _MMMOD_WRITER_MDL_ENTRY::LastPageToWrite, LOCK_PFN, _MMPAGING_FILE::MinimumSize, MmChargeCommitmentLock, MmMinimumPageFileReduction, MmNumberOfPagingFiles, MmPagingFile, MmTotalCommitLimit, MmTotalCommittedPages, NTSTATUS(), PAGE_SHIFT, PAGE_SIZE, RtlAreBitsClear(), RtlClearBits(), RtlSetBits(), Size, _MMPAGING_FILE::Size, TRUE, and UNLOCK_PFN.

Referenced by MiDereferenceSegmentThread().

01946 : 01947 01948 This routine attempts to reduce the size of the paging files to 01949 their minimum levels. 01950 01951 Note - Page file expansion and page file reduction are synchronized 01952 because a single thread is responsible for performing the 01953 operation. Hence, while expansion is occurring, a reduction 01954 request will be queued to the thread. 01955 01956 Arguments: 01957 01958 None. 01959 01960 Return Value: 01961 01962 None. 01963 01964 --*/ 01965 01966 { 01967 BOOLEAN Reduce; 01968 KIRQL OldIrql; 01969 ULONG i; 01970 PFN_NUMBER StartReduction; 01971 PFN_NUMBER ReductionSize; 01972 PFN_NUMBER TryBit; 01973 PFN_NUMBER TryReduction; 01974 SIZE_T MaxReduce; 01975 FILE_ALLOCATION_INFORMATION FileAllocationInfo; 01976 NTSTATUS status; 01977 01978 Reduce = FALSE; 01979 01980 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01981 01982 // 01983 // Make sure the commit limit is greater than the number of committed 01984 // pages by twice the minimum page file reduction. Keep the 01985 // difference between the two at least minimum page file reduction. 01986 // 01987 01988 if ((MmTotalCommittedPages + (2 * MmMinimumPageFileReduction)) < 01989 MmTotalCommitLimit) { 01990 01991 MaxReduce = MmTotalCommitLimit - 01992 (MmMinimumPageFileReduction + MmTotalCommittedPages); 01993 ASSERT ((LONG)MaxReduce >= 0); 01994 01995 i = 0; 01996 do { 01997 01998 if (MaxReduce < MmMinimumPageFileReduction) { 01999 02000 // 02001 // Don't reduce any more paging files. 02002 // 02003 02004 break; 02005 } 02006 02007 if (MmPagingFile[i]->MinimumSize != MmPagingFile[i]->Size) { 02008 02009 if (MmPagingFile[i]->FreeSpace > MmMinimumPageFileReduction) { 02010 02011 // 02012 // Attempt to reduce this paging file. 02013 // 02014 02015 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02016 02017 // 02018 // Lock the PFN database and check to see if ample pages 02019 // are free at the end of the paging file. 02020 // 02021 02022 TryBit = MmPagingFile[i]->Size - MmMinimumPageFileReduction; 02023 TryReduction = MmMinimumPageFileReduction; 02024 02025 if (TryBit <= MmPagingFile[i]->MinimumSize) { 02026 TryBit = MmPagingFile[i]->MinimumSize; 02027 TryReduction = MmPagingFile[i]->Size - 02028 MmPagingFile[i]->MinimumSize; 02029 } 02030 02031 StartReduction = 0; 02032 ReductionSize = 0; 02033 02034 LOCK_PFN (OldIrql); 02035 02036 while (TRUE) { 02037 02038 // 02039 // Try to reduce. 02040 // 02041 02042 if ((ReductionSize + TryReduction) > MaxReduce) { 02043 02044 // 02045 // The reduction attempt would remove more 02046 // than MaxReduce pages. 02047 // 02048 02049 break; 02050 } 02051 02052 if (RtlAreBitsClear (MmPagingFile[i]->Bitmap, 02053 (ULONG)TryBit, 02054 (ULONG)TryReduction)) { 02055 02056 // 02057 // Can reduce it by TryReduction, see if it can 02058 // be made smaller. 02059 // 02060 02061 StartReduction = TryBit; 02062 ReductionSize += TryReduction; 02063 02064 if (StartReduction == MmPagingFile[i]->MinimumSize) { 02065 break; 02066 } 02067 02068 TryBit = StartReduction - MmMinimumPageFileReduction; 02069 02070 if (TryBit <= MmPagingFile[i]->MinimumSize) { 02071 TryReduction -= 02072 MmPagingFile[i]->MinimumSize - TryBit; 02073 TryBit = MmPagingFile[i]->MinimumSize; 02074 } else { 02075 TryReduction = MmMinimumPageFileReduction; 02076 } 02077 } else { 02078 02079 // 02080 // Reduction has failed. 02081 // 02082 02083 break; 02084 } 02085 } //end while 02086 02087 // 02088 // Make sure there are no outstanding writes to 02089 // pages within the start reduction range. 02090 // 02091 02092 if (StartReduction != 0) { 02093 02094 // 02095 // There is an outstanding write past where the 02096 // new end of the paging file should be. This 02097 // is a very rare condition, so just punt shrinking 02098 // the file. 02099 // 02100 02101 if ((MmPagingFile[i]->Entry[0]->LastPageToWrite > 02102 StartReduction) || 02103 (MmPagingFile[i]->Entry[1]->LastPageToWrite > 02104 StartReduction)) { 02105 StartReduction = 0; 02106 } 02107 } 02108 02109 // 02110 // Are there any pages to remove? 02111 // 02112 02113 if (StartReduction != 0) { 02114 02115 // 02116 // Reduce the paging file's size and free space. 02117 // 02118 02119 ASSERT (ReductionSize == (MmPagingFile[i]->Size - StartReduction)); 02120 02121 MmPagingFile[i]->Size = StartReduction; 02122 MmPagingFile[i]->FreeSpace -= ReductionSize; 02123 MaxReduce -= ReductionSize; 02124 ASSERT ((LONG)MaxReduce >= 0); 02125 02126 RtlSetBits (MmPagingFile[i]->Bitmap, 02127 (ULONG)StartReduction, 02128 (ULONG)ReductionSize ); 02129 02130 // 02131 // Release the PFN lock now that the size info 02132 // has been updated. 02133 // 02134 02135 UNLOCK_PFN (OldIrql); 02136 02137 // 02138 // Change the commit limit to reflect the returned 02139 // page file space. 02140 // 02141 02142 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 02143 02144 // 02145 // Now that the commit lock is again held, recheck 02146 // the commit to ensure it is still safe to contract 02147 // the paging files. 02148 // 02149 02150 if ((MmTotalCommittedPages + (2 * MmMinimumPageFileReduction)) >= 02151 MmTotalCommitLimit) { 02152 02153 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02154 LOCK_PFN (OldIrql); 02155 02156 MmPagingFile[i]->Size = StartReduction + ReductionSize; 02157 MmPagingFile[i]->FreeSpace += ReductionSize; 02158 MaxReduce += ReductionSize; 02159 ASSERT ((LONG)MaxReduce >= 0); 02160 02161 RtlClearBits (MmPagingFile[i]->Bitmap, 02162 (ULONG)StartReduction, 02163 (ULONG)ReductionSize ); 02164 02165 UNLOCK_PFN (OldIrql); 02166 02167 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 02168 break; 02169 } 02170 02171 MmTotalCommitLimit -= ReductionSize; 02172 02173 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02174 02175 #if defined (_WIN64) || defined (_X86PAE_) 02176 FileAllocationInfo.AllocationSize.QuadPart = 02177 ((ULONG64)StartReduction << PAGE_SHIFT); 02178 02179 #else 02180 FileAllocationInfo.AllocationSize.LowPart = 02181 StartReduction * PAGE_SIZE; 02182 02183 // 02184 // Set high part to zero, paging files are 02185 // limited to 4gb. 02186 // 02187 02188 FileAllocationInfo.AllocationSize.HighPart = 0; 02189 #endif 02190 02191 // 02192 // Reduce the allocated size of the paging file 02193 // thereby actually freeing the space and 02194 // setting a new end of file. 02195 // 02196 02197 02198 ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL); 02199 status = IoSetInformation ( 02200 MmPagingFile[i]->File, 02201 FileAllocationInformation, 02202 sizeof(FILE_ALLOCATION_INFORMATION), 02203 &FileAllocationInfo 02204 ); 02205 #if DBG 02206 02207 // 02208 // Ignore errors on truncating the paging file 02209 // as we can always have less space in the bitmap 02210 // than the pagefile holds. 02211 // 02212 02213 if (status != STATUS_SUCCESS) { 02214 DbgPrint ("MM: pagefile truncate status %lx\n", 02215 status); 02216 } 02217 #endif 02218 } else { 02219 UNLOCK_PFN (OldIrql); 02220 } 02221 02222 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 02223 } 02224 } 02225 i += 1; 02226 } while (i < MmNumberOfPagingFiles); 02227 } 02228 02229 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 02230 return; 02231 }

LOGICAL MiCancelWriteOfMappedPfn IN PFN_NUMBER  PageToStop  ) 
 

Definition at line 2579 of file modwrite.c.

References APC_LEVEL, _MDL::ByteCount, FALSE, LOCK_PFN, _MMMOD_WRITER_MDL_ENTRY::Mdl, MiWriteComplete(), MmMappedPageWriterList, PAGE_SHIFT, TRUE, _MMMOD_WRITER_MDL_ENTRY::u, and UNLOCK_PFN.

Referenced by MmPurgeSection().

02585 : 02586 02587 This routine attempts to stop a pending mapped page writer write for the 02588 specified PFN. Note that if the write can be stopped, any other pages 02589 that may be clustered with the write are also stopped. 02590 02591 Arguments: 02592 02593 PageToStop - Supplies the frame number that the caller wants to stop. 02594 02595 Return Value: 02596 02597 TRUE if the write was stopped, FALSE if not. 02598 02599 Environment: 02600 02601 Kernel mode, PFN lock held. The PFN lock is released and reacquired if 02602 the write was stopped. 02603 02604 N.B. No other locks may be held as IRQL is lowered to APC_LEVEL here. 02605 02606 --*/ 02607 02608 { 02609 ULONG i; 02610 ULONG PageCount; 02611 KIRQL OldIrql; 02612 PPFN_NUMBER Page; 02613 PLIST_ENTRY NextEntry; 02614 PMDL MemoryDescriptorList; 02615 PMMMOD_WRITER_MDL_ENTRY ModWriterEntry; 02616 02617 // 02618 // Walk the MmMappedPageWriterList looking for an MDL which contains 02619 // the argument page. If found, remove it and cancel the write. 02620 // 02621 02622 NextEntry = MmMappedPageWriterList.Flink; 02623 while (NextEntry != &MmMappedPageWriterList) { 02624 02625 ModWriterEntry = CONTAINING_RECORD(NextEntry, 02626 MMMOD_WRITER_MDL_ENTRY, 02627 Links); 02628 02629 MemoryDescriptorList = &ModWriterEntry->Mdl; 02630 PageCount = (MemoryDescriptorList->ByteCount >> PAGE_SHIFT); 02631 Page = (PPFN_NUMBER)(MemoryDescriptorList + 1); 02632 02633 for (i = 0; i < PageCount; i += 1) { 02634 if (*Page == PageToStop) { 02635 RemoveEntryList (NextEntry); 02636 goto CancelWrite; 02637 } 02638 Page += 1; 02639 } 02640 02641 NextEntry = NextEntry->Flink; 02642 } 02643 02644 return FALSE; 02645 02646 CancelWrite: 02647 02648 UNLOCK_PFN (APC_LEVEL); 02649 02650 // 02651 // File lock conflict to indicate an error has occurred, 02652 // but that future I/Os should be allowed. Keep APCs disabled and 02653 // call the write completion routine. 02654 // 02655 02656 ModWriterEntry->u.IoStatus.Status = STATUS_FILE_LOCK_CONFLICT; 02657 ModWriterEntry->u.IoStatus.Information = 0; 02658 02659 MiWriteComplete ((PVOID)ModWriterEntry, 02660 &ModWriterEntry->u.IoStatus, 02661 0 ); 02662 02663 LOCK_PFN (OldIrql); 02664 02665 return TRUE; 02666 }

LOGICAL MiCauseOverCommitPopup IN SIZE_T  NumberOfPages,
IN ULONG  Extension
 

Referenced by MiChargeCommitment(), and MiPageFileFull().

NTSTATUS MiCheckForCrashDump PFILE_OBJECT  File,
IN ULONG  FileNumber
 

Definition at line 1095 of file modwrite.c.

References ASSERT, _MMPAGING_FILE::CurrentUsage, DelayedWorkQueue, _KPROCESS::DirectoryTableBase, _MMWORK_CONTEXT::Event, ExInitializeWorkItem, ExQueueWorkItem(), FALSE, File, _MMPAGING_FILE::FreeSpace, HighPagePriority, IoPageRead(), IoSynchronousPageWrite(), KeClearEvent, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _MDL::MappedSystemVa, MDL_PAGES_LOCKED, _MDL::MdlFlags, MI_PFN_ELEMENT, MI_SET_PAGING_FILE_INFO, MI_WRITE_INVALID_PTE, MiCrashDumpWorker(), MiGetPageForHeader(), MiRemoveImageHeaderPage(), MiUpdateImageHeaderPage(), MmCrashDumpSection, MmCreateMdl(), MmDynamicMemoryMutex, MmGetSystemAddressForMdlSafe, MmPagingFile, MmPagingFileDebug, MmPfnDatabase, MmPhysicalMemoryBlock, MmUnmapLockedPages(), NT_SUCCESS, NTSTATUS(), NULL, _PHYSICAL_MEMORY_DESCRIPTOR::NumberOfRuns, Offset, PAGE_SHIFT, PAGE_SIZE, _EPROCESS::Pcb, PsActiveProcessHead, PsInitialSystemProcess, PsLoadedModuleList, RtlSetBits(), _MMWORK_CONTEXT::Size, _MMPAGING_FILE::Size, Status, _MMPFN::u3, WrPageIn, and WrVirtualMemory.

Referenced by NtCreatePagingFile().

01102 : 01103 01104 This routine checks the first page of the paging file to 01105 determine if a crash dump exists. If a crash dump is found 01106 a section is created which maps the crash dump. A handle 01107 to the section is created via NtQuerySystemInformation specifying 01108 SystemCrashDumpInformation. 01109 01110 Arguments: 01111 01112 File - Supplies a pointer to the file object for the paging file. 01113 01114 FileNumber - Supplies the index into the paging file array. 01115 01116 Return Value: 01117 01118 Returns STATUS_CRASH_DUMP if a crash dump exists, success otherwise. 01119 01120 --*/ 01121 01122 { 01123 PMDL Mdl; 01124 LARGE_INTEGER Offset = {0,0}; 01125 LARGE_INTEGER DumpSpaceUsed; 01126 PFN_NUMBER DumpSpaceUsedInPages; 01127 PULONG Block; 01128 IO_STATUS_BLOCK IoStatus; 01129 NTSTATUS Status; 01130 PFN_NUMBER j; 01131 PPFN_NUMBER Page; 01132 NTSTATUS FinalStatus; 01133 PMMPTE PointerPte; 01134 PMMPFN Pfn; 01135 PFN_NUMBER MdlHack[(sizeof(MDL)/sizeof(PFN_NUMBER)) + 1]; 01136 WORK_QUEUE_ITEM WorkItem; 01137 MMWORK_CONTEXT Context; 01138 01139 FinalStatus = STATUS_SUCCESS; 01140 01141 Mdl = (PMDL)&MdlHack[0]; 01142 MmCreateMdl( Mdl, NULL, PAGE_SIZE); 01143 Mdl->MdlFlags |= MDL_PAGES_LOCKED; 01144 01145 Page = (PPFN_NUMBER)(Mdl + 1); 01146 *Page = MiGetPageForHeader (); 01147 Block = MmGetSystemAddressForMdlSafe (Mdl, HighPagePriority); 01148 01149 if (Block == NULL) { 01150 MiRemoveImageHeaderPage(*Page); 01151 return STATUS_INSUFFICIENT_RESOURCES; 01152 } 01153 01154 KeInitializeEvent (&Context.Event, NotificationEvent, FALSE); 01155 01156 Status = IoPageRead (File, 01157 Mdl, 01158 &Offset, 01159 &Context.Event, 01160 &IoStatus); 01161 01162 if (Status == STATUS_PENDING) { 01163 KeWaitForSingleObject( &Context.Event, 01164 WrPageIn, 01165 KernelMode, 01166 FALSE, 01167 (PLARGE_INTEGER)NULL); 01168 } 01169 01170 KeClearEvent (&Context.Event); 01171 01172 DumpSpaceUsed.LowPart = Block[DH_REQUIRED_DUMP_SPACE]; 01173 DumpSpaceUsed.HighPart = Block[DH_REQUIRED_DUMP_SPACE + 1]; 01174 01175 DumpSpaceUsedInPages = (PFN_NUMBER)(DumpSpaceUsed.QuadPart >> PAGE_SHIFT); 01176 01177 if ((Block[0] == 'EGAP') && 01178 (Block[1] == 'PMUD') && 01179 (DumpSpaceUsedInPages <= MmPagingFile[FileNumber]->Size)) { 01180 01181 // 01182 // A crash dump already exists, don't let pager use 01183 // it and build named section for it. 01184 // 01185 01186 Context.Size.QuadPart = DumpSpaceUsed.QuadPart; 01187 01188 ExInitializeWorkItem(&WorkItem, 01189 MiCrashDumpWorker, 01190 (PVOID)&Context); 01191 01192 ExQueueWorkItem( &WorkItem, DelayedWorkQueue ); 01193 01194 KeWaitForSingleObject( &Context.Event, 01195 WrPageIn, 01196 KernelMode, 01197 FALSE, 01198 (PLARGE_INTEGER)NULL); 01199 01200 KeClearEvent (&Context.Event); 01201 01202 if (!NT_SUCCESS(Context.Status)) { 01203 goto Failed; 01204 } 01205 01206 // 01207 // Make the section point to the paging file. 01208 // 01209 01210 PointerPte = MmCrashDumpSection->Segment->PrototypePte; 01211 MI_WRITE_INVALID_PTE (PointerPte, MmCrashDumpSection->Segment->SegmentPteTemplate); 01212 01213 Pfn = MI_PFN_ELEMENT (*Page); 01214 #if PFN_CONSISTENCY 01215 MiSetModified (Pfn, 1); 01216 #else 01217 Pfn->u3.e1.Modified = 1; 01218 #endif 01219 01220 PointerPte += 1; 01221 01222 for (j = 1; j < DumpSpaceUsedInPages; j += 1) { 01223 01224 MI_SET_PAGING_FILE_INFO (*PointerPte, 01225 MmCrashDumpSection->Segment->SegmentPteTemplate, 01226 FileNumber, 01227 j); 01228 01229 #if DBG 01230 if ((j < 8192) && (FileNumber == 0)) { 01231 ASSERT ((MmPagingFileDebug[j] & 1) == 0); 01232 MmPagingFileDebug[j] = (((ULONG_PTR)PointerPte << 3) | 1); 01233 } 01234 #endif //DBG 01235 PointerPte += 1; 01236 } 01237 01238 // 01239 // Change the original PTE contents to refer to 01240 // the paging file offset where this was written. 01241 // 01242 01243 RtlSetBits (MmPagingFile[FileNumber]->Bitmap, 01244 1, 01245 (ULONG)DumpSpaceUsedInPages - 1); 01246 01247 MmPagingFile[FileNumber]->FreeSpace -= DumpSpaceUsedInPages; 01248 MmPagingFile[FileNumber]->CurrentUsage += DumpSpaceUsedInPages; 01249 FinalStatus = STATUS_CRASH_DUMP; 01250 01251 Failed: 01252 01253 // 01254 // Indicate that no crash dump is in file so if system is 01255 // rebooted the page file is available. 01256 // 01257 01258 Block[1] = 'EGAP'; 01259 } else { 01260 01261 // 01262 // Set new pattern into file. 01263 // 01264 01265 RtlFillMemoryUlong (Block, 01266 PAGE_SIZE, 01267 'EGAP'); 01268 01269 #if !defined(_WIN64) 01270 01271 // 01272 // This bit of code does not work on Win64. Worse, it generates 01273 // alignment faults. So, until it (and the other components that 01274 // deal with crashdump blocks) is fixed, it is disabled for Win64. 01275 // 01276 01277 *(PULONG_PTR)(&Block[4]) = PsInitialSystemProcess->Pcb.DirectoryTableBase[0]; 01278 *(PULONG *)(&Block[5]) = (PULONG)MmPfnDatabase; 01279 *(PLIST_ENTRY *)(&Block[6]) = (PLIST_ENTRY)&PsLoadedModuleList; 01280 *(PLIST_ENTRY *)(&Block[7]) = (PLIST_ENTRY)&PsActiveProcessHead; 01281 #endif 01282 Block[8] = 01283 #ifdef _X86_ 01284 IMAGE_FILE_MACHINE_I386; 01285 #endif //_X86_ 01286 01287 #ifdef _ALPHA_ 01288 IMAGE_FILE_MACHINE_ALPHA; 01289 #endif //_ALPHA_ 01290 01291 #ifdef _IA64_ 01292 IMAGE_FILE_MACHINE_IA64; 01293 #endif //_IA64_ 01294 01295 ExAcquireFastMutex (&MmDynamicMemoryMutex); 01296 01297 RtlCopyMemory (&Block[DH_PHYSICAL_MEMORY_BLOCK], 01298 MmPhysicalMemoryBlock, 01299 (sizeof(PHYSICAL_MEMORY_DESCRIPTOR) + 01300 (sizeof(PHYSICAL_MEMORY_RUN) * 01301 (MmPhysicalMemoryBlock->NumberOfRuns - 1)))); 01302 01303 ExReleaseFastMutex (&MmDynamicMemoryMutex); 01304 } 01305 01306 Status = IoSynchronousPageWrite ( 01307 File, 01308 Mdl, 01309 &Offset, 01310 &Context.Event, 01311 &IoStatus ); 01312 01313 KeWaitForSingleObject (&Context.Event, 01314 WrVirtualMemory, 01315 KernelMode, 01316 FALSE, 01317 (PLARGE_INTEGER)NULL); 01318 01319 MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); 01320 if (FinalStatus == STATUS_CRASH_DUMP) { 01321 01322 // 01323 // Set the first page to point to the page that was just operated 01324 // upon. 01325 // 01326 01327 MiUpdateImageHeaderPage (MmCrashDumpSection->Segment->PrototypePte, 01328 *Page, 01329 MmCrashDumpSection->Segment->ControlArea); 01330 } else { 01331 MiRemoveImageHeaderPage(*Page); 01332 } 01333 return FinalStatus; 01334 }

NTSTATUS MiCheckPageFileMapping IN PFILE_OBJECT  File  ) 
 

Definition at line 4563 of file modwrite.c.

References File, LOCK_PFN, NULL, and UNLOCK_PFN.

Referenced by NtCreatePagingFile().

04569 : 04570 04571 Non-pagable routine to check to see if a given file has 04572 no sections and therefore is eligible to become a paging file. 04573 04574 Arguments: 04575 04576 File - Supplies a pointer to the file object. 04577 04578 Return Value: 04579 04580 Returns STATUS_SUCCESS if the file can be used as a paging file. 04581 04582 --*/ 04583 04584 { 04585 KIRQL OldIrql; 04586 04587 LOCK_PFN (OldIrql); 04588 04589 if (File->SectionObjectPointer == NULL) { 04590 UNLOCK_PFN (OldIrql); 04591 return STATUS_SUCCESS; 04592 } 04593 04594 if ((File->SectionObjectPointer->DataSectionObject != NULL) || 04595 (File->SectionObjectPointer->ImageSectionObject != NULL)) { 04596 04597 UNLOCK_PFN (OldIrql); 04598 return STATUS_INCOMPATIBLE_FILE_MAP; 04599 } 04600 UNLOCK_PFN (OldIrql); 04601 return STATUS_SUCCESS; 04602 04603 }

NTSTATUS MiCheckPageFilePath PFILE_OBJECT  FileObject  ) 
 

Definition at line 166 of file modwrite.c.

References ASSERT, _IRP::AssociatedIrp, DeviceUsageTypePaging, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IoQueueThreadIrp(), _IRP::IoStatus, IRP_MJ_PNP, IRP_MN_DEVICE_USAGE_NOTIFICATION, IRP_SYNCHRONOUS_API, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, ObReferenceObject, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by MiLoadSystemImage(), and NtCreatePagingFile().

00169 { 00170 PIRP irp; 00171 NTSTATUS status; 00172 PDEVICE_OBJECT deviceObject; 00173 KEVENT event; 00174 PIO_STACK_LOCATION irpSp; 00175 IO_STATUS_BLOCK localIoStatus; 00176 00177 PAGED_CODE(); 00178 00179 // 00180 // Reference the file object here so that no special checks need be made 00181 // in I/O completion to determine whether or not to dereference the file 00182 // object. 00183 // 00184 00185 ObReferenceObject( FileObject ); 00186 00187 // 00188 // Initialize the local event. 00189 // 00190 00191 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 00192 00193 // 00194 // Get the address of the target device object. 00195 // 00196 00197 deviceObject = IoGetRelatedDeviceObject( FileObject ); 00198 00199 // 00200 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00201 // 00202 00203 irp = IoAllocateIrp( deviceObject->StackSize, FALSE ); 00204 ASSERT( irp != NULL ); 00205 00206 if (irp == NULL) { 00207 00208 // 00209 // Don't dereference the file object, our caller will take care of that. 00210 // 00211 00212 return STATUS_NO_MEMORY; 00213 } 00214 00215 irp->Tail.Overlay.OriginalFileObject = FileObject; 00216 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00217 irp->RequestorMode = KernelMode; 00218 00219 // 00220 // Fill in the service independent parameters in the IRP. 00221 // 00222 00223 irp->UserEvent = &event; 00224 irp->Flags = IRP_SYNCHRONOUS_API; 00225 irp->UserIosb = &localIoStatus; 00226 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 00227 00228 // 00229 // Get a pointer to the stack location for the first driver. This will be 00230 // used to pass the original function codes and parameters. 00231 // 00232 00233 irpSp = IoGetNextIrpStackLocation( irp ); 00234 irpSp->MajorFunction = IRP_MJ_PNP; 00235 irpSp->MinorFunction = IRP_MN_DEVICE_USAGE_NOTIFICATION; 00236 irpSp->FileObject = FileObject; 00237 irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 00238 irp->AssociatedIrp.SystemBuffer = NULL; 00239 // irp->Flags = 0; 00240 00241 irpSp->Parameters.UsageNotification.InPath = TRUE; 00242 irpSp->Parameters.UsageNotification.Type = DeviceUsageTypePaging; 00243 00244 // 00245 // Insert the packet at the head of the IRP list for the thread. 00246 // 00247 00248 IoQueueThreadIrp( irp ); 00249 00250 // 00251 // Now simply invoke the driver at its dispatch entry with the IRP. 00252 // 00253 00254 status = IoCallDriver( deviceObject, irp ); 00255 00256 // 00257 // Wait for the local event and copy the final status information 00258 // back to the caller. 00259 // 00260 00261 if (status == STATUS_PENDING) { 00262 (VOID) KeWaitForSingleObject( &event, 00263 Executive, 00264 KernelMode, 00265 FALSE, 00266 (PLARGE_INTEGER) NULL ); 00267 status = localIoStatus.Status; 00268 } 00269 00270 return status; 00271 }

VOID MiClusterWritePages IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex,
IN PMM_WRITE_CLUSTER  WriteCluster,
IN ULONG  Size
 

Referenced by MiGatherPagefilePages().

VOID MiContractPagingFiles VOID   ) 
 

Definition at line 1864 of file modwrite.c.

References _MMPAGE_FILE_EXPANSION::DereferenceList, ExAllocatePoolWithTag, FALSE, _MMPAGING_FILE::FreeSpace, KeReleaseSemaphore(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, _MMPAGING_FILE::MinimumSize, MmChargeCommitmentLock, MmDereferenceSegmentHeader, MmMinimumPageFileReduction, MmNumberOfPagingFiles, MmPagingFile, MmTotalCommitLimit, MmTotalCommittedPages, NonPagedPool, NULL, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, _MMPAGE_FILE_EXPANSION::Segment, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, _MMPAGING_FILE::Size, and TRUE.

Referenced by MmDeleteProcessAddressSpace().

01870 : 01871 01872 This routine checks to see if ample space is no longer committed 01873 and if so, does enough free space exist in any paging file. IF 01874 the answer to both these is affirmative, a reduction in the 01875 paging file size(s) is attempted. 01876 01877 Arguments: 01878 01879 None. 01880 01881 Return Value: 01882 01883 None. 01884 01885 --*/ 01886 01887 { 01888 BOOLEAN Reduce; 01889 PMMPAGE_FILE_EXPANSION PageReduce; 01890 KIRQL OldIrql; 01891 ULONG i; 01892 01893 Reduce = FALSE; 01894 01895 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01896 01897 if ((MmTotalCommitLimit - MmMinimumPageFileReduction) > 01898 MmTotalCommittedPages) { 01899 01900 for (i = 0;i < MmNumberOfPagingFiles; i += 1) { 01901 if (MmPagingFile[i]->Size != MmPagingFile[i]->MinimumSize) { 01902 if (MmPagingFile[i]->FreeSpace > MmMinimumPageFileReduction) { 01903 Reduce = TRUE; 01904 break; 01905 } 01906 } 01907 } 01908 01909 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01910 01911 if (!Reduce) { 01912 return; 01913 } 01914 01915 PageReduce = ExAllocatePoolWithTag (NonPagedPool, 01916 sizeof(MMPAGE_FILE_EXPANSION), 01917 ' mM'); 01918 01919 if (PageReduce == NULL) { 01920 return; 01921 } 01922 01923 PageReduce->Segment = NULL; 01924 PageReduce->RequestedExpansionSize = 0xFFFFFFFF; 01925 01926 ExAcquireSpinLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 01927 InsertTailList ( &MmDereferenceSegmentHeader.ListHead, 01928 &PageReduce->DereferenceList); 01929 ExReleaseSpinLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 01930 01931 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 0L, 1L, FALSE); 01932 return; 01933 } 01934 01935 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01936 return; 01937 }

VOID MiCrashDumpWorker IN PVOID  Context  ) 
 

Definition at line 1338 of file modwrite.c.

References _MMWORK_CONTEXT::Event, FALSE, KeSetEvent(), MmCrashDumpSection, MmCreateSection(), NULL, ObjectAttributes, PAGED_CODE, PMMWORK_CONTEXT, _MMWORK_CONTEXT::Size, and _MMWORK_CONTEXT::Status.

Referenced by MiCheckForCrashDump().

01344 : 01345 01346 This function is called in the context of a delayed worker thread. 01347 Its function is to create a section which will be used to map the 01348 crash dump in the paging file. 01349 01350 Arguments: 01351 01352 Context - Supplies the context record which contains the section's 01353 size, an event to set at completion and a status value 01354 to be returned. 01355 01356 Return Value: 01357 01358 None. 01359 01360 --*/ 01361 01362 { 01363 PMMWORK_CONTEXT Work; 01364 OBJECT_ATTRIBUTES ObjectAttributes; 01365 01366 PAGED_CODE(); 01367 01368 Work = (PMMWORK_CONTEXT)Context; 01369 01370 InitializeObjectAttributes( &ObjectAttributes, 01371 NULL, 01372 0, 01373 NULL, 01374 NULL ); 01375 01376 01377 Work->Status = MmCreateSection ( &MmCrashDumpSection, 01378 SECTION_MAP_READ, 01379 &ObjectAttributes, 01380 &Work->Size, 01381 PAGE_READONLY, 01382 SEC_COMMIT, 01383 NULL, 01384 NULL ); 01385 01386 KeSetEvent (&Work->Event, 0, FALSE); 01387 return; 01388 }

VOID MiExtendPagingFileMaximum IN ULONG  PageFileNumber,
IN PRTL_BITMAP  NewBitmap
 

Definition at line 1031 of file modwrite.c.

References _MMPAGING_FILE::Bitmap, LOCK_PFN, _MMPAGING_FILE::MaximumSize, MiUpdateModifiedWriterMdls(), MmFreePagingSpaceLow, MmPagingFile, MmTotalCommitLimitMaximum, RtlSetAllBits(), and UNLOCK_PFN.

Referenced by NtCreatePagingFile().

01038 : 01039 01040 This routine switches from the old bitmap to the new (larger) bitmap. 01041 01042 Arguments: 01043 01044 PageFileNumber - Supplies the paging file number to be extended. 01045 01046 NewBitmap - Supplies the new bitmap to use. 01047 01048 Return Value: 01049 01050 None. 01051 01052 Environment: 01053 01054 Kernel mode, APC_LEVEL, MmPageFileCreationLock held. 01055 01056 --*/ 01057 01058 { 01059 KIRQL OldIrql; 01060 PRTL_BITMAP OldBitmap; 01061 01062 OldBitmap = MmPagingFile[PageFileNumber]->Bitmap; 01063 01064 RtlSetAllBits (NewBitmap); 01065 01066 LOCK_PFN (OldIrql); 01067 01068 // 01069 // Copy the bits from the existing map. 01070 // 01071 01072 RtlCopyMemory (NewBitmap->Buffer, 01073 OldBitmap->Buffer, 01074 ((OldBitmap->SizeOfBitMap + 31) / 32) * sizeof (ULONG)); 01075 01076 MmTotalCommitLimitMaximum += (NewBitmap->SizeOfBitMap - OldBitmap->SizeOfBitMap); 01077 01078 MmPagingFile[PageFileNumber]->MaximumSize = NewBitmap->SizeOfBitMap; 01079 01080 MmPagingFile[PageFileNumber]->Bitmap = NewBitmap; 01081 01082 // 01083 // If any MDLs are waiting for space, get them up now. 01084 // 01085 01086 if (!IsListEmpty (&MmFreePagingSpaceLow)) { 01087 MiUpdateModifiedWriterMdls (PageFileNumber); 01088 } 01089 01090 UNLOCK_PFN (OldIrql); 01091 }

SIZE_T MiExtendPagingFiles IN PMMPAGE_FILE_EXPANSION  PageExpand  ) 
 

Definition at line 1681 of file modwrite.c.

References ASSERT, FALSE, _MMPAGING_FILE::MaximumSize, MI_EXTEND_ANY_PAGEFILE, MiAttemptPageFileExtension(), MmChargeCommitmentLock, MmNumberOfPagingFiles, MmPageFileFullExtendPages, MmPagingFile, MmTotalCommitLimit, MmTotalCommittedPages, _MMPAGING_FILE::Size, and TRUE.

Referenced by MiDereferenceSegmentThread().

01687 : 01688 01689 This routine attempts to extend the paging files to provide 01690 ExtendSize bytes. 01691 01692 Note - Page file expansion and page file reduction are synchronized 01693 because a single thread is responsible for performing the 01694 operation. Hence, while expansion is occurring, a reduction 01695 request will be queued to the thread. 01696 01697 Arguments: 01698 01699 DesiredQuota - Supplies the quota in pages desired. 01700 01701 PageFileNumber - Supplies the page file number to extend. 01702 MI_EXTEND_ANY_PAGFILE indicates to extend any page file. 01703 01704 Return Value: 01705 01706 Returns the size of the extension. Zero if the page file(s) cannot 01707 be extended. 01708 01709 --*/ 01710 01711 { 01712 SIZE_T DesiredQuota; 01713 ULONG PageFileNumber; 01714 SIZE_T ExtendedSize; 01715 SIZE_T ExtendSize; 01716 ULONG i; 01717 KIRQL OldIrql; 01718 LOGICAL LockHeld; 01719 LOGICAL RealExpansion; 01720 01721 RealExpansion = TRUE; 01722 LockHeld = FALSE; 01723 ExtendedSize = 0; 01724 DesiredQuota = PageExpand->RequestedExpansionSize; 01725 PageFileNumber = PageExpand->PageFileNumber; 01726 01727 PageExpand->ActualExpansion = 0; 01728 01729 ASSERT (PageFileNumber < MmNumberOfPagingFiles || PageFileNumber == MI_EXTEND_ANY_PAGEFILE); 01730 01731 if (MmNumberOfPagingFiles == 0) { 01732 goto alldone; 01733 } 01734 01735 if (PageFileNumber < MmNumberOfPagingFiles) { 01736 i = PageFileNumber; 01737 ExtendedSize = MmPagingFile[i]->MaximumSize - MmPagingFile[i]->Size; 01738 if (ExtendedSize < DesiredQuota) { 01739 ExtendedSize = 0; 01740 } 01741 else { 01742 ExtendedSize = MiAttemptPageFileExtension (i, DesiredQuota, FALSE); 01743 } 01744 goto alldone; 01745 } 01746 01747 LockHeld = TRUE; 01748 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01749 01750 // 01751 // Check to see if ample space already exists now that we have 01752 // the spinlock. 01753 // 01754 01755 ExtendSize = DesiredQuota + MmTotalCommittedPages; 01756 01757 if (MmTotalCommitLimit >= ExtendSize) { 01758 ExtendedSize = 1; 01759 RealExpansion = FALSE; 01760 goto alldone; 01761 } 01762 01763 // 01764 // Calculate the additional pages needed. 01765 // 01766 01767 ExtendSize -= MmTotalCommitLimit; 01768 01769 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01770 LockHeld = FALSE; 01771 01772 // 01773 // Make sure ample space exists within the paging files. 01774 // 01775 01776 i = 0; 01777 01778 do { 01779 ExtendedSize += MmPagingFile[i]->MaximumSize - MmPagingFile[i]->Size; 01780 i += 1; 01781 } while (i < MmNumberOfPagingFiles); 01782 01783 if (ExtendedSize < ExtendSize) { 01784 ExtendedSize = 0; 01785 goto alldone; 01786 } 01787 01788 // 01789 // Attempt to extend only one of the paging files. 01790 // 01791 01792 i = 0; 01793 do { 01794 ExtendedSize = MiAttemptPageFileExtension (i, ExtendSize, FALSE); 01795 if (ExtendedSize != 0) { 01796 goto alldone; 01797 } 01798 i += 1; 01799 } while (i < MmNumberOfPagingFiles); 01800 01801 ASSERT (ExtendedSize == 0); 01802 01803 if (MmNumberOfPagingFiles == 1) { 01804 01805 // 01806 // If the attempt didn't succeed for one (not enough disk space free) - 01807 // don't try to set it to the maximum size. 01808 // 01809 01810 goto alldone; 01811 } 01812 01813 // 01814 // Attempt to extend all paging files. 01815 // 01816 01817 i = 0; 01818 do { 01819 ASSERT (ExtendSize > ExtendedSize); 01820 ExtendedSize += MiAttemptPageFileExtension (i, 01821 ExtendSize - ExtendedSize, 01822 TRUE); 01823 if (ExtendedSize >= ExtendSize) { 01824 goto alldone; 01825 } 01826 i += 1; 01827 } while (i < MmNumberOfPagingFiles); 01828 01829 // 01830 // Not enough space is available. 01831 // 01832 01833 ExtendedSize = 0; 01834 01835 alldone: 01836 01837 if (LockHeld == FALSE) { 01838 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 01839 } 01840 01841 if ((ExtendedSize != 0) && (RealExpansion == TRUE)) { 01842 MmTotalCommitLimit += ExtendedSize; 01843 } 01844 01845 // 01846 // If commit allotments have been temporarily blocked then unblock now. 01847 // 01848 01849 if (MmPageFileFullExtendPages) { 01850 ASSERT (MmTotalCommittedPages >= MmPageFileFullExtendPages); 01851 MmTotalCommittedPages -= MmPageFileFullExtendPages; 01852 MmPageFileFullExtendPages = 0; 01853 } 01854 01855 PageExpand->InProgress = FALSE; 01856 PageExpand->ActualExpansion = ExtendedSize; 01857 01858 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 01859 01860 return ExtendedSize; 01861 }

VOID MiFlushAllPages VOID   ) 
 

Definition at line 4870 of file modwrite.c.

References FALSE, KeDelayExecutionThread(), KernelMode, KeSetEvent(), Mm30Milliseconds, MmModifiedPageListHead, MmModifiedPageWriterEvent, MmWriteAllModifiedPages, _MMPFNLIST::Total, and TRUE.

Referenced by MiAllocateContiguousMemory(), MmGatherMemoryForHibernate(), and MmRemovePhysicalMemory().

04876 : 04877 04878 Forces a write of all modified pages. 04879 04880 Arguments: 04881 04882 None. 04883 04884 Return Value: 04885 04886 None. 04887 04888 Environment: 04889 04890 Kernel mode. No locks held. APC_LEVEL or less. 04891 04892 --*/ 04893 04894 { 04895 ULONG j = 0xff; 04896 04897 MmWriteAllModifiedPages = TRUE; 04898 KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE); 04899 04900 do { 04901 KeDelayExecutionThread (KernelMode, FALSE, &Mm30Milliseconds); 04902 j -= 1; 04903 } while ((MmModifiedPageListHead.Total > 50) && (j > 0)); 04904 04905 MmWriteAllModifiedPages = FALSE; 04906 return; 04907 }

VOID MiGatherMappedPages IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex
 

Definition at line 3198 of file modwrite.c.

References APC_LEVEL, ASSERT, BYTE_OFFSET, _MDL::ByteCount, BYTES_TO_PAGES, _MMMOD_WRITER_MDL_ENTRY::ControlArea, _SUBSECTION::ControlArea, DbgPrint, FALSE, _MMMOD_WRITER_MDL_ENTRY::File, _CONTROL_AREA::FilePointer, _MMMOD_WRITER_MDL_ENTRY::FileResource, FsRtlAcquireFileForModWrite(), IoAsynchronousPageWrite(), _MMMOD_WRITER_MDL_ENTRY::IoStatus, KeLowerIrql(), KeRaiseIrql(), KeSetEvent(), _MMMOD_WRITER_MDL_ENTRY::Links, _MMMOD_WRITER_LISTHEAD::ListHead, LOCK_PFN, _MMINFO_COUNTERS::MappedPagesWriteCount, _MMINFO_COUNTERS::MappedWriteIoCount, _MMMOD_WRITER_MDL_ENTRY::Mdl, MDL_PAGES_LOCKED, _MDL::MdlFlags, MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MiGetSubsectionAddress, MiInsertFrontModifiedNoWrite(), MiInsertPageInList(), MiMapPageInHyperSpace(), MiStartingOffset(), MiUnlinkPageFromList(), MiUnmapPageInHyperSpace, MiWriteComplete(), MmAvailablePages, MmEnoughMemoryForWrite, MmFreeGoal, MmInfoCounters, MmInitializeMdl, MmIsAddressValid(), MmMappedFileHeader, MmMappedPageWriterEvent, MmMappedPageWriterList, MmModifiedWriteClusterSize, MmModNoWriteInsert, MmPageLocationList, ModifiedNoWritePageList, ModifiedPageList, _CONTROL_AREA::ModifiedWriteCount, NT_ERROR, NULL, _CONTROL_AREA::NumberOfMappedViews, _CONTROL_AREA::NumberOfPfnReferences, _CONTROL_AREA::NumberOfSectionReferences, _MMMOD_WRITER_MDL_ENTRY::Page, PAGE_ALIGN, PAGE_SHIFT, PAGE_SIZE, _MMPFN::PteAddress, _SUBSECTION::PtesInSubsection, _MDL::Size, Status, _SUBSECTION::SubsectionBase, TRUE, _MMMOD_WRITER_MDL_ENTRY::u, _MMPTE::u, _CONTROL_AREA::u, _MMPFN::u3, UNLOCK_PFN, and _MMMOD_WRITER_MDL_ENTRY::WriteOffset.

Referenced by MiModifiedPageWriterWorker().

03205 : 03206 03207 This routine processes the specified modified page by examining 03208 the prototype PTE for that page and the adjacent prototype PTEs 03209 building a cluster of modified pages destined for a mapped file. 03210 Once the cluster is built, it is sent to the mapped writer thread 03211 to be processed. 03212 03213 Arguments: 03214 03215 Pfn1 - Supplies a pointer to the PFN element for the corresponding 03216 page. 03217 03218 PageFrameIndex - Supplies the physical page frame to write. 03219 03220 Return Value: 03221 03222 None. 03223 03224 Environment: 03225 03226 PFN lock held. 03227 03228 --*/ 03229 03230 { 03231 PMMPFN Pfn2; 03232 PMMMOD_WRITER_MDL_ENTRY ModWriterEntry; 03233 PSUBSECTION Subsection; 03234 PCONTROL_AREA ControlArea; 03235 PPFN_NUMBER Page; 03236 PMMPTE LastPte; 03237 PMMPTE BasePte; 03238 PMMPTE NextPte; 03239 PMMPTE PointerPte; 03240 PMMPTE StartingPte; 03241 MMPTE PteContents; 03242 KIRQL OldIrql = 0; 03243 KIRQL OldIrql2; 03244 03245 // 03246 // This page is destined for a mapped file, check to see if 03247 // there are any physically adjacent pages are also in the 03248 // modified page list and write them out at the same time. 03249 // 03250 03251 Subsection = MiGetSubsectionAddress (&Pfn1->OriginalPte); 03252 ControlArea = Subsection->ControlArea; 03253 03254 if (ControlArea->u.Flags.NoModifiedWriting) { 03255 03256 // 03257 // This page should not be written out, add it to the 03258 // tail of the modified NO WRITE list and get the next page. 03259 // 03260 03261 MiUnlinkPageFromList (Pfn1); 03262 MiInsertPageInList (MmPageLocationList[ModifiedNoWritePageList], 03263 PageFrameIndex); 03264 return; 03265 } 03266 03267 if (ControlArea->u.Flags.Image) { 03268 03269 #if 0 03270 // 03271 // Assert that there are no dangling shared global pages 03272 // for an image section that is not being used. 03273 // 03274 // This assert can be re-enabled when the segment dereference 03275 // thread list re-insertion is fixed. Note the recovery code is 03276 // fine, so disabling the assert is benign. 03277 // 03278 03279 ASSERT ((ControlArea->NumberOfMappedViews != 0) || 03280 (ControlArea->NumberOfSectionReferences != 0) || 03281 (ControlArea->u.Flags.FloppyMedia != 0)); 03282 #endif 03283 03284 // 03285 // This is an image section, writes are not 03286 // allowed to an image section. 03287 // 03288 03289 // 03290 // Change page contents to look like it's a demand zero 03291 // page and put it back into the modified list. 03292 // 03293 03294 // 03295 // Decrement the count for PfnReferences to the 03296 // segment as paging file pages are not counted as 03297 // "image" references. 03298 // 03299 03300 ControlArea->NumberOfPfnReferences -= 1; 03301 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 03302 MiUnlinkPageFromList (Pfn1); 03303 03304 Pfn1->OriginalPte.u.Soft.PageFileHigh = 0; 03305 Pfn1->OriginalPte.u.Soft.Prototype = 0; 03306 Pfn1->OriginalPte.u.Soft.Transition = 0; 03307 03308 // 03309 // Insert the page at the tail of the list and get 03310 // color update performed. 03311 // 03312 03313 MiInsertPageInList (MmPageLocationList[ModifiedPageList], 03314 PageFrameIndex); 03315 return; 03316 } 03317 03318 if ((ControlArea->u.Flags.HadUserReference == 0) && 03319 (MmAvailablePages > (MmFreeGoal + 40)) && 03320 (MmEnoughMemoryForWrite())) { 03321 03322 // 03323 // This page was modified via the cache manager. Don't 03324 // write it out at this time as there are ample pages. 03325 // 03326 03327 MiUnlinkPageFromList (Pfn1); 03328 MiInsertFrontModifiedNoWrite (PageFrameIndex); 03329 MmModNoWriteInsert = TRUE; 03330 return; 03331 } 03332 03333 // 03334 // Look at backwards at previous prototype PTEs to see if 03335 // this can be clustered into a larger write operation. 03336 // 03337 03338 PointerPte = Pfn1->PteAddress; 03339 NextPte = PointerPte - (MmModifiedWriteClusterSize - 1); 03340 03341 // 03342 // Make sure NextPte is in the same page. 03343 // 03344 03345 if (NextPte < (PMMPTE)PAGE_ALIGN (PointerPte)) { 03346 NextPte = (PMMPTE)PAGE_ALIGN (PointerPte); 03347 } 03348 03349 // 03350 // Make sure NextPte is within the subsection. 03351 // 03352 03353 if (NextPte < Subsection->SubsectionBase) { 03354 NextPte = Subsection->SubsectionBase; 03355 } 03356 03357 // 03358 // If the prototype PTEs are not currently mapped, 03359 // map them via hyperspace. BasePte refers to the 03360 // prototype PTEs for nonfaulting references. 03361 // 03362 03363 OldIrql2 = 99; 03364 if (MmIsAddressValid (PointerPte)) { 03365 BasePte = PointerPte; 03366 } else { 03367 BasePte = MiMapPageInHyperSpace (Pfn1->PteFrame, &OldIrql2); 03368 BasePte = (PMMPTE)((PCHAR)BasePte + 03369 BYTE_OFFSET (PointerPte)); 03370 } 03371 03372 ASSERT (MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (BasePte) == PageFrameIndex); 03373 03374 PointerPte -= 1; 03375 BasePte -= 1; 03376 03377 // 03378 // Don't go before the start of the subsection nor cross 03379 // a page boundary. 03380 // 03381 03382 while (PointerPte >= NextPte) { 03383 03384 PteContents = *BasePte; 03385 03386 // 03387 // If the page is not in transition, exit loop. 03388 // 03389 03390 if ((PteContents.u.Hard.Valid == 1) || 03391 (PteContents.u.Soft.Transition == 0) || 03392 (PteContents.u.Soft.Prototype == 1)) { 03393 03394 break; 03395 } 03396 03397 Pfn2 = MI_PFN_ELEMENT (PteContents.u.Trans.PageFrameNumber); 03398 03399 // 03400 // Make sure page is modified and on the modified list. 03401 // 03402 03403 if ((Pfn2->u3.e1.Modified == 0 ) || 03404 (Pfn2->u3.e2.ReferenceCount != 0)) { 03405 break; 03406 } 03407 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents); 03408 PointerPte -= 1; 03409 BasePte -= 1; 03410 } 03411 03412 StartingPte = PointerPte + 1; 03413 BasePte = BasePte + 1; 03414 03415 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03416 ASSERT (StartingPte == Pfn1->PteAddress); 03417 MiUnlinkPageFromList (Pfn1); 03418 03419 // 03420 // Get an entry from the list and fill it in. 03421 // 03422 03423 ModWriterEntry = (PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList ( 03424 &MmMappedFileHeader.ListHead); 03425 03426 ModWriterEntry->File = ControlArea->FilePointer; 03427 ModWriterEntry->ControlArea = ControlArea; 03428 03429 // 03430 // Calculate the offset to read into the file. 03431 // offset = base + ((thispte - basepte) << PAGE_SHIFT) 03432 // 03433 03434 ModWriterEntry->WriteOffset.QuadPart = MiStartingOffset (Subsection, 03435 Pfn1->PteAddress); 03436 03437 MmInitializeMdl(&ModWriterEntry->Mdl, 03438 (PVOID)ULongToPtr(Pfn1->u3.e1.PageColor << PAGE_SHIFT), 03439 PAGE_SIZE); 03440 03441 ModWriterEntry->Mdl.MdlFlags |= MDL_PAGES_LOCKED; 03442 03443 ModWriterEntry->Mdl.Size = (CSHORT)(sizeof(MDL) + 03444 (sizeof(PFN_NUMBER) * MmModifiedWriteClusterSize)); 03445 03446 Page = &ModWriterEntry->Page[0]; 03447 03448 // 03449 // Up the reference count for the physical page as there 03450 // is I/O in progress. 03451 // 03452 03453 MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 14); 03454 Pfn1->u3.e2.ReferenceCount += 1; 03455 03456 // 03457 // Clear the modified bit for the page and set the write 03458 // in progress bit. 03459 // 03460 03461 Pfn1->u3.e1.Modified = 0; 03462 Pfn1->u3.e1.WriteInProgress = 1; 03463 03464 // 03465 // Put this physical page into the MDL. 03466 // 03467 03468 *Page = PageFrameIndex; 03469 03470 // 03471 // See if any adjacent pages are also modified and in 03472 // the transition state and if so, write them out at 03473 // the same time. 03474 // 03475 03476 03477 // 03478 // Look at the previous PTE, ensuring a page boundary is 03479 // not crossed. 03480 // 03481 03482 LastPte = StartingPte + MmModifiedWriteClusterSize; 03483 03484 // 03485 // If BasePte is not in the same page as LastPte, 03486 // set last pte to be the last PTE in this page. 03487 // 03488 03489 if (StartingPte < (PMMPTE)PAGE_ALIGN(LastPte)) { 03490 LastPte = ((PMMPTE)PAGE_ALIGN(LastPte)) - 1; 03491 } 03492 03493 // 03494 // Make sure LastPte is within the subsection. 03495 // 03496 03497 if (LastPte > &Subsection->SubsectionBase[ 03498 Subsection->PtesInSubsection]) { 03499 LastPte = &Subsection->SubsectionBase[ 03500 Subsection->PtesInSubsection]; 03501 } 03502 03503 // 03504 // Look forwards. 03505 // 03506 03507 NextPte = BasePte + 1; 03508 PointerPte = StartingPte + 1; 03509 03510 // 03511 // Loop until an MDL is filled, the end of a subsection 03512 // is reached, or a page boundary is reached. 03513 // Note, PointerPte points to the PTE. NextPte points 03514 // to where it is mapped in hyperspace (if required). 03515 // 03516 03517 while (PointerPte < LastPte) { 03518 03519 PteContents = *NextPte; 03520 03521 // 03522 // If the page is not in transition, exit loop. 03523 // 03524 03525 if ((PteContents.u.Hard.Valid == 1) || 03526 (PteContents.u.Soft.Transition == 0) || 03527 (PteContents.u.Soft.Prototype == 1)) { 03528 03529 break; 03530 } 03531 03532 Pfn2 = MI_PFN_ELEMENT (PteContents.u.Trans.PageFrameNumber); 03533 03534 if ((Pfn2->u3.e1.Modified == 0 ) || 03535 (Pfn2->u3.e2.ReferenceCount != 0)) { 03536 03537 // 03538 // Page is not dirty or not on the modified list, 03539 // end clustering operation. 03540 // 03541 03542 break; 03543 } 03544 Page += 1; 03545 03546 // 03547 // Add physical page to MDL. 03548 // 03549 03550 *Page = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents); 03551 ASSERT (PointerPte == Pfn2->PteAddress); 03552 MiUnlinkPageFromList (Pfn2); 03553 03554 // 03555 // Up the reference count for the physical page as there 03556 // is I/O in progress. 03557 // 03558 03559 MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn2, 14); 03560 Pfn2->u3.e2.ReferenceCount += 1; 03561 03562 // 03563 // Clear the modified bit for the page and set the 03564 // write in progress bit. 03565 // 03566 03567 Pfn2->u3.e1.Modified = 0; 03568 Pfn2->u3.e1.WriteInProgress = 1; 03569 03570 ModWriterEntry->Mdl.ByteCount += PAGE_SIZE; 03571 03572 NextPte += 1; 03573 PointerPte += 1; 03574 03575 } //end while 03576 03577 if (OldIrql2 != 99) { 03578 MiUnmapPageInHyperSpace (OldIrql2); 03579 } 03580 03581 ASSERT (BYTES_TO_PAGES (ModWriterEntry->Mdl.ByteCount) <= MmModifiedWriteClusterSize); 03582 03583 ModWriterEntry->u.LastByte.QuadPart = ModWriterEntry->WriteOffset.QuadPart + 03584 ModWriterEntry->Mdl.ByteCount; 03585 03586 ASSERT (Subsection->ControlArea->u.Flags.Image == 0); 03587 03588 #if DBG 03589 if ((ULONG)ModWriterEntry->Mdl.ByteCount > 03590 ((1+MmModifiedWriteClusterSize)*PAGE_SIZE)) { 03591 DbgPrint("Mdl %p, MDL End Offset %lx %lx Subsection %p\n", 03592 ModWriterEntry->Mdl, 03593 ModWriterEntry->u.LastByte.LowPart, 03594 ModWriterEntry->u.LastByte.HighPart, 03595 Subsection); 03596 DbgBreakPoint(); 03597 } 03598 #endif //DBG 03599 03600 MmInfoCounters.MappedWriteIoCount += 1; 03601 MmInfoCounters.MappedPagesWriteCount += 03602 (ModWriterEntry->Mdl.ByteCount >> PAGE_SHIFT); 03603 03604 // 03605 // Increment the count of modified page writes outstanding 03606 // in the control area. 03607 // 03608 03609 ControlArea->ModifiedWriteCount += 1; 03610 03611 // 03612 // Increment the number of PFN references. This allows the file 03613 // system to purge (i.e. call MmPurgeSection) modified writes. 03614 // 03615 03616 ControlArea->NumberOfPfnReferences += 1; 03617 03618 ModWriterEntry->FileResource = NULL; 03619 03620 if (ControlArea->u.Flags.BeingPurged == 1) { 03621 UNLOCK_PFN (OldIrql); 03622 ModWriterEntry->u.IoStatus.Status = STATUS_FILE_LOCK_CONFLICT; 03623 ModWriterEntry->u.IoStatus.Information = 0; 03624 KeRaiseIrql (APC_LEVEL, &OldIrql); 03625 MiWriteComplete ((PVOID)ModWriterEntry, 03626 &ModWriterEntry->u.IoStatus, 03627 0 ); 03628 KeLowerIrql (OldIrql); 03629 LOCK_PFN (OldIrql); 03630 return; 03631 } 03632 03633 // 03634 // Send the entry for the MappedPageWriter. 03635 // 03636 03637 InsertTailList (&MmMappedPageWriterList, 03638 &ModWriterEntry->Links); 03639 03640 KeSetEvent (&MmMappedPageWriterEvent, 0, FALSE); 03641 03642 03643 #if 0 03644 03645 UNLOCK_PFN (OldIrql); 03646 03647 ModWriterEntry->FileResource = NULL; 03648 03649 if (ModWriterEntry->ControlArea->u.Flags.FailAllIo == 1) { 03650 Status = STATUS_UNSUCCESSFUL; 03651 03652 } else if (FsRtlAcquireFileForModWrite (ModWriterEntry->File, 03653 &ModWriterEntry->u.LastByte, 03654 &ModWriterEntry->FileResource)) { 03655 03656 // 03657 // Issue the write request. 03658 // 03659 03660 Status = IoAsynchronousPageWrite ( 03661 ModWriterEntry->File, 03662 &ModWriterEntry->Mdl, 03663 &ModWriterEntry->WriteOffset, 03664 MiWriteComplete, 03665 (PVOID)ModWriterEntry, 03666 &ModWriterEntry->IoStatus, 03667 &ModWriterEntry->Irp ); 03668 } else { 03669 03670 // 03671 // Unable to get the file system resources, set error status 03672 // to lock conflict (ignored by MiWriteComplete) so the APC 03673 // routine is explicitly called. 03674 // 03675 03676 Status = STATUS_FILE_LOCK_CONFLICT; 03677 } 03678 03679 if (NT_ERROR(Status)) { 03680 03681 // 03682 // An error has occurred, disable APCs and 03683 // call the write completion routine. 03684 // 03685 03686 ModWriterEntry->IoStatus.Status = Status; 03687 ModWriterEntry->IoStatus.Information = 0; 03688 KeRaiseIrql (APC_LEVEL, &OldIrql); 03689 MiWriteComplete ((PVOID)ModWriterEntry, 03690 &ModWriterEntry->IoStatus, 03691 0 ); 03692 KeLowerIrql (OldIrql); 03693 } 03694 03695 LOCK_PFN (OldIrql); 03696 #endif //0 03697 return; 03698 }

VOID MiGatherPagefilePages IN PMMPFN  Pfn1,
IN PFN_NUMBER  PageFrameIndex
 

Definition at line 3701 of file modwrite.c.

References APC_LEVEL, ASSERT, _MMPAGING_FILE::Bitmap, _MDL::ByteCount, _MMMOD_WRITER_MDL_ENTRY::CurrentList, _MMPAGING_FILE::CurrentUsage, DbgPrint, _MMINFO_COUNTERS::DirtyPagesWriteCount, _MMINFO_COUNTERS::DirtyWriteIoCount, _MMMOD_WRITER_LISTHEAD::Event, FALSE, _MMPAGING_FILE::File, File, _MMPAGING_FILE::FreeSpace, _MMPAGING_FILE::Hint, _MMPAGING_FILE::HintSetToZero, IoAsynchronousPageWrite(), KeClearEvent, KeLowerIrql(), KeRaiseIrql(), KernelMode, KeSetEvent(), KeWaitForSingleObject(), _MMMOD_WRITER_MDL_ENTRY::LastPageToWrite, _MMMOD_WRITER_MDL_ENTRY::Links, _MMMOD_WRITER_LISTHEAD::ListHead, LOCK_PFN, _MMMOD_WRITER_MDL_ENTRY::Mdl, MDL_PAGES_LOCKED, _MDL::MdlFlags, MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE, MI_GET_MODIFIED_PAGE_BY_COLOR, MI_GET_NEXT_COLOR, MI_PFN_ELEMENT, MI_SET_PAGING_FILE_INFO, MiClusterWritePages(), _MMPAGING_FILE::MinimumSize, MiPageFileFull(), MiUnlinkPageFromList(), MiWriteComplete(), Mm30Milliseconds, MM_DBG_MOD_WRITE, MM_EMPTY_LIST, MM_IO_IN_PROGRESS, MmFreePagingSpaceLow, MmInfoCounters, MmInitializeMdl, MmModifiedWriteClusterSize, MmNumberOfActiveMdlEntries, MmPagingFileDebug, MmPagingFileHeader, NT_ERROR, NTSTATUS(), _MMMOD_WRITER_MDL_ENTRY::Page, PAGE_SHIFT, PAGE_SIZE, _MMPAGING_FILE::PageFileNumber, _MMMOD_WRITER_MDL_ENTRY::PagingFile, _MMMOD_WRITER_MDL_ENTRY::PagingListHead, _MMPAGING_FILE::PeakUsage, RtlClearBits(), RtlFindClearBitsAndSet(), _MDL::Size, Status, TRUE, _MMMOD_WRITER_MDL_ENTRY::u, UNLOCK_PFN, and WrPageOut.

Referenced by MiModifiedPageWriterWorker().

03708 : 03709 03710 This routine processes the specified modified page by getting 03711 that page and gather any other pages on the modified list destined 03712 for the paging file in a large write cluster. This cluster is 03713 then written to the paging file. 03714 03715 Arguments: 03716 03717 Pfn1 - Supplies a pointer to the PFN element for the corresponding page. 03718 03719 PageFrameIndex - Supplies the physical page frame to write. 03720 03721 Return Value: 03722 03723 None. 03724 03725 Environment: 03726 03727 PFN lock held. 03728 03729 --*/ 03730 03731 { 03732 PFILE_OBJECT File; 03733 PMMMOD_WRITER_MDL_ENTRY ModWriterEntry; 03734 PMMPAGING_FILE CurrentPagingFile; 03735 NTSTATUS Status; 03736 PPFN_NUMBER Page; 03737 ULONG StartBit; 03738 LARGE_INTEGER StartingOffset; 03739 PFN_NUMBER ClusterSize; 03740 PFN_NUMBER ThisCluster; 03741 MMPTE LongPte; 03742 KIRQL OldIrql; 03743 ULONG NextColor; 03744 LOGICAL PageFileFull; 03745 //MM_WRITE_CLUSTER WriteCluster; 03746 03747 OldIrql = 0; 03748 03749 if (IsListEmpty(&MmPagingFileHeader.ListHead)) { 03750 03751 // 03752 // Reset the event indicating no paging files MDLs in 03753 // the list, drop the PFN lock and wait for an 03754 // I/O operation to complete. 03755 // 03756 03757 KeClearEvent (&MmPagingFileHeader.Event); 03758 UNLOCK_PFN (OldIrql); 03759 KeWaitForSingleObject( &MmPagingFileHeader.Event, 03760 WrPageOut, 03761 KernelMode, 03762 FALSE, 03763 &Mm30Milliseconds); 03764 LOCK_PFN (OldIrql); 03765 03766 // 03767 // Don't go on as the old PageFrameIndex at the 03768 // top of the ModifiedList may have changed states. 03769 // 03770 03771 return; 03772 } 03773 03774 // 03775 // Page is destined for the paging file. 03776 // Find the paging file with the most free space and get a cluster. 03777 // 03778 03779 NextColor = Pfn1->u3.e1.PageColor; 03780 03781 ModWriterEntry = (PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList ( 03782 &MmPagingFileHeader.ListHead); 03783 #if DBG 03784 ModWriterEntry->Links.Flink = MM_IO_IN_PROGRESS; 03785 #endif 03786 CurrentPagingFile = ModWriterEntry->PagingFile; 03787 03788 File = ModWriterEntry->PagingFile->File; 03789 ThisCluster = MmModifiedWriteClusterSize; 03790 03791 PageFileFull = FALSE; 03792 03793 do { 03794 // 03795 // Attempt to cluster MmModifiedWriteClusterSize pages 03796 // together. Reduce by one half until we succeed or 03797 // can't find a single page free in the paging file. 03798 // 03799 03800 if (((CurrentPagingFile->Hint + MmModifiedWriteClusterSize) > 03801 CurrentPagingFile->MinimumSize) 03802 && 03803 (CurrentPagingFile->HintSetToZero == FALSE)) { 03804 03805 CurrentPagingFile->HintSetToZero = TRUE; 03806 CurrentPagingFile->Hint = 0; 03807 } 03808 03809 StartBit = RtlFindClearBitsAndSet (CurrentPagingFile->Bitmap, 03810 (ULONG)ThisCluster, 03811 (ULONG)CurrentPagingFile->Hint); 03812 03813 if (StartBit != 0xFFFFFFFF) { 03814 break; 03815 } 03816 if (CurrentPagingFile->Hint != 0) { 03817 03818 // 03819 // Start looking from front of the file. 03820 // 03821 03822 CurrentPagingFile->Hint = 0; 03823 } else { 03824 ThisCluster = ThisCluster >> 1; 03825 PageFileFull = TRUE; 03826 } 03827 03828 } while (ThisCluster != 0); 03829 03830 if (StartBit == 0xFFFFFFFF) { 03831 03832 // 03833 // Paging file must be full. 03834 // 03835 03836 KdPrint(("MM MODWRITE: page file full\n")); 03837 ASSERT(CurrentPagingFile->FreeSpace == 0); 03838 03839 // 03840 // Move this entry to the not enough space list, 03841 // and try again. 03842 // 03843 03844 InsertTailList (&MmFreePagingSpaceLow, 03845 &ModWriterEntry->Links); 03846 ModWriterEntry->CurrentList = &MmFreePagingSpaceLow; 03847 MmNumberOfActiveMdlEntries -= 1; 03848 MiPageFileFull (); 03849 return; 03850 } 03851 03852 CurrentPagingFile->FreeSpace -= ThisCluster; 03853 CurrentPagingFile->CurrentUsage += ThisCluster; 03854 if (CurrentPagingFile->FreeSpace < 32) { 03855 PageFileFull = TRUE; 03856 } 03857 03858 StartingOffset.QuadPart = (UINT64)StartBit << PAGE_SHIFT; 03859 03860 MmInitializeMdl(&ModWriterEntry->Mdl, 03861 (PVOID)ULongToPtr(Pfn1->u3.e1.PageColor << PAGE_SHIFT), 03862 PAGE_SIZE); 03863 03864 ModWriterEntry->Mdl.MdlFlags |= MDL_PAGES_LOCKED; 03865 03866 ModWriterEntry->Mdl.Size = (CSHORT)(sizeof(MDL) + 03867 sizeof(PFN_NUMBER) * MmModifiedWriteClusterSize); 03868 03869 Page = &ModWriterEntry->Page[0]; 03870 03871 ClusterSize = 0; 03872 03873 // 03874 // Search through the modified page list looking for other 03875 // pages destined for the paging file and build a cluster. 03876 // 03877 03878 while (ClusterSize != ThisCluster) { 03879 03880 // 03881 // Is this page destined for a paging file? 03882 // 03883 03884 if (Pfn1->OriginalPte.u.Soft.Prototype == 0) { 03885 03886 #if 0 //********* commented out 03887 03888 MiClusterWritePages (Pfn1, 03889 PageFrameIndex, 03890 &WriteCluster, 03891 ThisCluster - ClusterSize); 03892 do { 03893 03894 PageFrameIndex = WriteCluster.Cluster[WriteCluster.StartIndex]; 03895 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03896 #endif //0 03897 *Page = PageFrameIndex; 03898 03899 // 03900 // Remove the page from the modified list. Note that 03901 // write-in-progress marks the state. 03902 // 03903 03904 // 03905 // Unlink the page so the same page won't be found 03906 // on the modified page list by color. 03907 // 03908 03909 MiUnlinkPageFromList (Pfn1); 03910 NextColor = MI_GET_NEXT_COLOR(NextColor); 03911 03912 MI_GET_MODIFIED_PAGE_BY_COLOR (PageFrameIndex, 03913 NextColor); 03914 03915 // 03916 // Up the reference count for the physical page as there 03917 // is I/O in progress. 03918 // 03919 03920 MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 16); 03921 Pfn1->u3.e2.ReferenceCount += 1; 03922 03923 // 03924 // Clear the modified bit for the page and set the 03925 // write in progress bit. 03926 // 03927 03928 Pfn1->u3.e1.Modified = 0; 03929 Pfn1->u3.e1.WriteInProgress = 1; 03930 ASSERT (Pfn1->OriginalPte.u.Soft.PageFileHigh == 0); 03931 03932 MI_SET_PAGING_FILE_INFO (LongPte, 03933 Pfn1->OriginalPte, 03934 CurrentPagingFile->PageFileNumber, 03935 StartBit); 03936 03937 #if DBG 03938 if ((StartBit < 8192) && 03939 (CurrentPagingFile->PageFileNumber == 0)) { 03940 ASSERT ((MmPagingFileDebug[StartBit] & 1) == 0); 03941 MmPagingFileDebug[StartBit] = 03942 (((ULONG_PTR)Pfn1->PteAddress << 3) | 03943 ((ClusterSize & 0xf) << 1) | 1); 03944 } 03945 #endif //DBG 03946 03947 // 03948 // Change the original PTE contents to refer to 03949 // the paging file offset where this was written. 03950 // 03951 03952 Pfn1->OriginalPte = LongPte; 03953 03954 ClusterSize += 1; 03955 Page += 1; 03956 StartBit += 1; 03957 #if 0 // COMMENTED OUT 03958 WriteCluster.Count -= 1; 03959 WriteCluster.StartIndex += 1; 03960 03961 } while (WriteCluster.Count != 0); 03962 #endif //0 03963 } else { 03964 03965 // 03966 // This page was not destined for a paging file, 03967 // get another page. 03968 // 03969 // Get a page of the same color as the one which 03970 // was not usable. 03971 // 03972 03973 MI_GET_MODIFIED_PAGE_BY_COLOR (PageFrameIndex, 03974 NextColor); 03975 } 03976 03977 if (PageFrameIndex == MM_EMPTY_LIST) { 03978 break; 03979 } 03980 03981 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03982 03983 } //end while 03984 03985 if (ClusterSize != ThisCluster) { 03986 03987 // 03988 // A complete cluster could not be located, free the 03989 // excess page file space that was reserved and adjust 03990 // the size of the packet. 03991 // 03992 03993 RtlClearBits (CurrentPagingFile->Bitmap, 03994 StartBit, 03995 (ULONG)(ThisCluster - ClusterSize)); 03996 03997 CurrentPagingFile->FreeSpace += ThisCluster - ClusterSize; 03998 CurrentPagingFile->CurrentUsage -= ThisCluster - ClusterSize; 03999 04000 // 04001 // If their are no pages to write, don't issue a write 04002 // request and restart the scan loop. 04003 // 04004 04005 if (ClusterSize == 0) { 04006 04007 // 04008 // No pages to write. Inset the entry back in the 04009 // list. 04010 // 04011 04012 if (IsListEmpty (&ModWriterEntry->PagingListHead->ListHead)) { 04013 KeSetEvent (&ModWriterEntry->PagingListHead->Event, 04014 0, 04015 FALSE); 04016 } 04017 04018 InsertTailList (&ModWriterEntry->PagingListHead->ListHead, 04019 &ModWriterEntry->Links); 04020 04021 return; 04022 } 04023 } 04024 04025 if (CurrentPagingFile->PeakUsage < 04026 CurrentPagingFile->CurrentUsage) { 04027 CurrentPagingFile->PeakUsage = 04028 CurrentPagingFile->CurrentUsage; 04029 } 04030 04031 ModWriterEntry->Mdl.ByteCount = (ULONG)(ClusterSize * PAGE_SIZE); 04032 ModWriterEntry->LastPageToWrite = StartBit - 1; 04033 04034 MmInfoCounters.DirtyWriteIoCount += 1; 04035 MmInfoCounters.DirtyPagesWriteCount += (ULONG)ClusterSize; 04036 04037 // 04038 // For now release the PFN lock and wait for the write to complete. 04039 // 04040 04041 UNLOCK_PFN (OldIrql); 04042 04043 #if DBG 04044 if (MmDebug & MM_DBG_MOD_WRITE) { 04045 DbgPrint("MM MODWRITE: modified page write begun @ %08lx by %08lx\n", 04046 StartingOffset.LowPart, ModWriterEntry->Mdl.ByteCount); 04047 } 04048 #endif 04049 04050 // 04051 // Issue the write request. 04052 // 04053 04054 Status = IoAsynchronousPageWrite ( File, 04055 &ModWriterEntry->Mdl, 04056 &StartingOffset, 04057 MiWriteComplete, 04058 (PVOID)ModWriterEntry, 04059 &ModWriterEntry->u.IoStatus, 04060 &ModWriterEntry->Irp ); 04061 04062 if (NT_ERROR(Status)) { 04063 KdPrint(("MM MODWRITE: modified page write failed %lx\n", Status)); 04064 04065 // 04066 // An error has occurred, disable APCs and 04067 // call the write completion routine. 04068 // 04069 04070 ModWriterEntry->u.IoStatus.Status = Status; 04071 ModWriterEntry->u.IoStatus.Information = 0; 04072 KeRaiseIrql (APC_LEVEL, &OldIrql); 04073 MiWriteComplete ((PVOID)ModWriterEntry, 04074 &ModWriterEntry->u.IoStatus, 04075 0 ); 04076 KeLowerIrql (OldIrql); 04077 } 04078 04079 LOCK_PFN (OldIrql); 04080 04081 if (PageFileFull == TRUE) { 04082 MiPageFileFull (); 04083 } 04084 04085 return; 04086 }

VOID MiInsertPageFileInList VOID   ) 
 

Definition at line 4607 of file modwrite.c.

References Count, _MMMOD_WRITER_MDL_ENTRY::CurrentList, _MMPAGING_FILE::Entry, _MMMOD_WRITER_LISTHEAD::Event, FALSE, _MMPAGING_FILE::FreeSpace, KeSetEvent(), _MMMOD_WRITER_LISTHEAD::ListHead, LOCK_PFN, _MMPAGING_FILE::MaximumSize, MmChargeCommitmentLock, MmNumberOfActiveMdlEntries, MmNumberOfPagingFiles, MmOverCommit, MmOverCommit2, MmPagingFile, MmPagingFileHeader, MmTotalCommitLimit, MmTotalCommitLimitMaximum, and UNLOCK_PFN.

Referenced by NtCreatePagingFile().

04613 : 04614 04615 Non-pagable routine to add a page file into the list 04616 of system wide page files. 04617 04618 Arguments: 04619 04620 None, implicitly found through page file structures. 04621 04622 Return Value: 04623 04624 None. Operation cannot fail. 04625 04626 --*/ 04627 04628 { 04629 KIRQL OldIrql; 04630 ULONG Count; 04631 04632 LOCK_PFN (OldIrql); 04633 04634 MmNumberOfPagingFiles += 1; 04635 Count = MmNumberOfPagingFiles; 04636 04637 if (IsListEmpty (&MmPagingFileHeader.ListHead)) { 04638 KeSetEvent (&MmPagingFileHeader.Event, 0, FALSE); 04639 } 04640 04641 InsertTailList (&MmPagingFileHeader.ListHead, 04642 &MmPagingFile[MmNumberOfPagingFiles - 1]->Entry[0]->Links); 04643 04644 MmPagingFile[MmNumberOfPagingFiles - 1]->Entry[0]->CurrentList = 04645 &MmPagingFileHeader.ListHead; 04646 04647 InsertTailList (&MmPagingFileHeader.ListHead, 04648 &MmPagingFile[MmNumberOfPagingFiles - 1]->Entry[1]->Links); 04649 04650 MmPagingFile[MmNumberOfPagingFiles - 1]->Entry[1]->CurrentList = 04651 &MmPagingFileHeader.ListHead; 04652 04653 MmNumberOfActiveMdlEntries += 2; 04654 04655 UNLOCK_PFN (OldIrql); 04656 04657 04658 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 04659 04660 if (Count == 1) { 04661 04662 // 04663 // We have just created the first paging file. Start the 04664 // modified page writer. 04665 // 04666 04667 MmTotalCommitLimit = 04668 MmPagingFile[MmNumberOfPagingFiles - 1]->FreeSpace + MmOverCommit; 04669 04670 MmTotalCommitLimitMaximum = 04671 MmPagingFile[MmNumberOfPagingFiles - 1]->MaximumSize + MmOverCommit; 04672 04673 // 04674 // Keep commit limit above 20mb so we can boot with a small paging 04675 // file and clean things up. 04676 // 04677 04678 if (MmTotalCommitLimit < 5500) { 04679 MmOverCommit2 = 5500 - MmTotalCommitLimit; 04680 MmTotalCommitLimit = 5500; 04681 } 04682 04683 if (MmTotalCommitLimitMaximum < 5500) { 04684 MmTotalCommitLimitMaximum = MmTotalCommitLimit; 04685 } 04686 04687 } else { 04688 04689 // 04690 // Balance overcommitment in the case an extension was granted. 04691 // 04692 04693 if (MmOverCommit2 > MmPagingFile[MmNumberOfPagingFiles - 1]->FreeSpace) { 04694 MmOverCommit2 -= MmPagingFile[MmNumberOfPagingFiles - 1]->FreeSpace; 04695 } else { 04696 MmTotalCommitLimit += 04697 MmPagingFile[MmNumberOfPagingFiles - 1]->FreeSpace - MmOverCommit2; 04698 MmTotalCommitLimitMaximum += 04699 MmPagingFile[MmNumberOfPagingFiles - 1]->MaximumSize - MmOverCommit2; 04700 MmOverCommit2 = 0; 04701 } 04702 } 04703 04704 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 04705 return; 04706 }

LOGICAL MiIssuePageExtendRequest IN PMMPAGE_FILE_EXPANSION  PageExtend  ) 
 

Definition at line 4911 of file modwrite.c.

References Executive, FALSE, KeReleaseSemaphore(), KernelMode, KeWaitForSingleObject(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, MmDereferenceSegmentHeader, MmOneSecond, MmTwentySeconds, NTSTATUS(), NULL, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, and TRUE.

Referenced by MiChargeCommitment(), and NtCreatePagingFile().

04917 : 04918 04919 Queue a message to the segment dereferencing / pagefile extending 04920 thread to see if the page file can be extended. Extension is done 04921 in the context of a system thread due to mutexes which the current 04922 thread may be holding. 04923 04924 Arguments: 04925 04926 PageExtend - Supplies a pointer to the page file extension request. 04927 04928 Return Value: 04929 04930 TRUE indicates the request completed. FALSE indicates the request timed 04931 out and was removed. 04932 04933 Environment: 04934 04935 Kernel mode. No locks held. APC level or less. 04936 04937 --*/ 04938 04939 { 04940 KIRQL OldIrql; 04941 NTSTATUS status; 04942 PLIST_ENTRY NextEntry; 04943 04944 ExAcquireFastLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 04945 InsertTailList ( &MmDereferenceSegmentHeader.ListHead, 04946 &PageExtend->DereferenceList); 04947 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 04948 04949 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 04950 0L, 04951 1L, 04952 TRUE); 04953 04954 // 04955 // Wait for the thread to extend the paging file. 04956 // 04957 04958 status = KeWaitForSingleObject (&PageExtend->Event, 04959 Executive, 04960 KernelMode, 04961 FALSE, 04962 (PageExtend->RequestedExpansionSize < 10) ? 04963 &MmOneSecond : &MmTwentySeconds); 04964 04965 if (status == STATUS_TIMEOUT) { 04966 04967 // 04968 // The wait has timed out, if this request has not 04969 // been processed, remove it from the list and check 04970 // to see if we should allow this request to succeed. 04971 // This prevents a deadlock between the file system 04972 // trying to allocate memory in the FSP and the 04973 // segment dereferencing thread trying to close a 04974 // file object, and waiting in the file system. 04975 // 04976 04977 KdPrint(("MiIssuePageExtendRequest: wait timed out, page-extend= %lx, quota = %lx\n", 04978 PageExtend, PageExtend->RequestedExpansionSize)); 04979 04980 ExAcquireFastLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 04981 04982 NextEntry = MmDereferenceSegmentHeader.ListHead.Flink; 04983 04984 while (NextEntry != &MmDereferenceSegmentHeader.ListHead) { 04985 04986 // 04987 // Check to see if this is the entry we are waiting for. 04988 // 04989 04990 if (NextEntry == &PageExtend->DereferenceList) { 04991 04992 // 04993 // Remove this entry. 04994 // 04995 04996 RemoveEntryList (&PageExtend->DereferenceList); 04997 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 04998 return FALSE; 04999 } 05000 NextEntry = NextEntry->Flink; 05001 } 05002 05003 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 05004 05005 // 05006 // Entry is being processed, wait for completion. 05007 // 05008 05009 KdPrint (("MiIssuePageExtendRequest: rewaiting...\n")); 05010 05011 KeWaitForSingleObject (&PageExtend->Event, 05012 Executive, 05013 KernelMode, 05014 FALSE, 05015 NULL); 05016 } 05017 05018 return TRUE; 05019 }

VOID MiIssuePageExtendRequestNoWait IN PFN_NUMBER  SizeInPages  ) 
 

Definition at line 5023 of file modwrite.c.

References ASSERT, _MMPAGE_FILE_EXPANSION::DereferenceList, DISPATCH_LEVEL, FALSE, _MMPAGE_FILE_EXPANSION::InProgress, KeReleaseSemaphore(), L, _MMDEREFERENCE_SEGMENT_HEADER::ListHead, _MMDEREFERENCE_SEGMENT_HEADER::Lock, MmAttemptForCantExtend, MmChargeCommitmentLock, MmDereferenceSegmentHeader, NTSTATUS(), ONEMB_IN_PAGES, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, _MMDEREFERENCE_SEGMENT_HEADER::Semaphore, and TRUE.

Referenced by MiAllocatePoolPages(), and MmResourcesAvailable().

05029 : 05030 05031 Queue a message to the segment dereferencing / pagefile extending 05032 thread to see if the page file can be extended. Extension is done 05033 in the context of a system thread due to mutexes which the current 05034 thread may be holding. 05035 05036 Arguments: 05037 05038 SizeInPages - Supplies the size in pages to increase the page file(s) by. 05039 This is rounded up to a 1MB multiple by this routine. 05040 05041 Return Value: 05042 05043 TRUE indicates the request completed. FALSE indicates the request timed 05044 out and was removed. 05045 05046 Environment: 05047 05048 Kernel mode. No locks held. APC level or less. 05049 05050 Note this routine must be very careful to not use any paged 05051 pool as the only reason it is being called is because pool is depleted. 05052 05053 --*/ 05054 05055 { 05056 KIRQL OldIrql; 05057 NTSTATUS status; 05058 PLIST_ENTRY NextEntry; 05059 05060 ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL); 05061 05062 ExAcquireFastLock (&MmChargeCommitmentLock, &OldIrql); 05063 05064 if (MmAttemptForCantExtend.InProgress != FALSE) { 05065 05066 // 05067 // An expansion request is already in progress, assume 05068 // it will help enough (another can always be issued later) and 05069 // that it will succeed. 05070 // 05071 05072 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 05073 return; 05074 } 05075 05076 MmAttemptForCantExtend.InProgress = TRUE; 05077 ExReleaseFastLock (&MmChargeCommitmentLock, OldIrql); 05078 05079 SizeInPages = (SizeInPages + ONEMB_IN_PAGES - 1) & ~(ONEMB_IN_PAGES - 1); 05080 05081 MmAttemptForCantExtend.RequestedExpansionSize = SizeInPages; 05082 05083 ExAcquireFastLock (&MmDereferenceSegmentHeader.Lock, &OldIrql); 05084 05085 InsertTailList ( &MmDereferenceSegmentHeader.ListHead, 05086 &MmAttemptForCantExtend.DereferenceList); 05087 05088 ExReleaseFastLock (&MmDereferenceSegmentHeader.Lock, OldIrql); 05089 05090 KeReleaseSemaphore (&MmDereferenceSegmentHeader.Semaphore, 05091 0L, 05092 1L, 05093 FALSE); 05094 05095 return; 05096 } }

VOID MiMappedPageWriter IN PVOID  StartContext  ) 
 

Definition at line 4239 of file modwrite.c.

References APC_LEVEL, _MMMOD_WRITER_MDL_ENTRY::ControlArea, FALSE, _MMMOD_WRITER_MDL_ENTRY::File, _MMMOD_WRITER_MDL_ENTRY::FileResource, FsRtlAcquireFileForModWrite(), FsRtlSetTopLevelIrpForModWriter, IoAsynchronousPageWrite(), _MMMOD_WRITER_MDL_ENTRY::IoStatus, IoSynchronousPageWrite(), KeClearEvent, KeInitializeEvent, KeLowerIrql(), KeRaiseIrql(), KernelMode, KeSetPriorityThread(), KeWaitForSingleObject(), LOCK_PFN, _MMMOD_WRITER_MDL_ENTRY::Mdl, MiWriteComplete(), MmMappedPageWriterEvent, MmMappedPageWriterList, NT_ERROR, NTSTATUS(), NULL, PsGetCurrentThread, Status, TRUE, _MMMOD_WRITER_MDL_ENTRY::u, _CONTROL_AREA::u, UNLOCK_PFN, VOID(), _MMMOD_WRITER_MDL_ENTRY::WriteOffset, and WrVirtualMemory.

Referenced by MiModifiedPageWriter().

04245 : 04246 04247 Implements the NT secondary modified page writer thread. 04248 Requests for writes to mapped files are sent to this thread. 04249 This is required as the writing of mapped file pages could cause 04250 page faults resulting in requests for free pages. But there 04251 could be no free pages - hence a dead lock. Rather than deadlock 04252 the whole system waiting on the modified page writer, creating 04253 a secondary thread allows that thread to block without affecting 04254 on going page file writes. 04255 04256 Arguments: 04257 04258 StartContext - not used. 04259 04260 Return Value: 04261 04262 None. 04263 04264 Environment: 04265 04266 Kernel mode. 04267 04268 --*/ 04269 04270 { 04271 PMMMOD_WRITER_MDL_ENTRY ModWriterEntry; 04272 KIRQL OldIrql = 0; 04273 NTSTATUS Status; 04274 KEVENT TempEvent; 04275 04276 UNREFERENCED_PARAMETER (StartContext); 04277 04278 // 04279 // Make this a real time thread. 04280 // 04281 04282 (VOID) KeSetPriorityThread (&PsGetCurrentThread()->Tcb, 04283 LOW_REALTIME_PRIORITY + 1); 04284 04285 // 04286 // Let the file system know that we are getting resources. 04287 // 04288 04289 FsRtlSetTopLevelIrpForModWriter(); 04290 04291 KeInitializeEvent (&TempEvent, NotificationEvent, FALSE); 04292 04293 while (TRUE) { 04294 KeWaitForSingleObject (&MmMappedPageWriterEvent, 04295 WrVirtualMemory, 04296 KernelMode, 04297 FALSE, 04298 (PLARGE_INTEGER)NULL); 04299 04300 LOCK_PFN (OldIrql); 04301 if (IsListEmpty (&MmMappedPageWriterList)) { 04302 KeClearEvent (&MmMappedPageWriterEvent); 04303 UNLOCK_PFN (OldIrql); 04304 } else { 04305 04306 ModWriterEntry = (PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList ( 04307 &MmMappedPageWriterList); 04308 04309 UNLOCK_PFN (OldIrql); 04310 04311 04312 if (ModWriterEntry->ControlArea->u.Flags.FailAllIo == 1) { 04313 Status = STATUS_UNSUCCESSFUL; 04314 04315 } else if (FsRtlAcquireFileForModWrite (ModWriterEntry->File, 04316 &ModWriterEntry->u.LastByte, 04317 &ModWriterEntry->FileResource)) { 04318 04319 // 04320 // Issue the write request. 04321 // 04322 04323 Status = IoAsynchronousPageWrite ( 04324 ModWriterEntry->File, 04325 &ModWriterEntry->Mdl, 04326 &ModWriterEntry->WriteOffset, 04327 MiWriteComplete, 04328 (PVOID)ModWriterEntry, 04329 &ModWriterEntry->u.IoStatus, 04330 &ModWriterEntry->Irp ); 04331 } else { 04332 04333 // 04334 // Unable to get the file system resources, set error status 04335 // to lock conflict (ignored by MiWriteComplete) so the APC 04336 // routine is explicitly called. 04337 // 04338 04339 Status = STATUS_FILE_LOCK_CONFLICT; 04340 } 04341 04342 if (NT_ERROR(Status)) { 04343 04344 // 04345 // An error has occurred, disable APC's and 04346 // call the write completion routine. 04347 // 04348 04349 ModWriterEntry->u.IoStatus.Status = Status; 04350 ModWriterEntry->u.IoStatus.Information = 0; 04351 KeRaiseIrql (APC_LEVEL, &OldIrql); 04352 MiWriteComplete ((PVOID)ModWriterEntry, 04353 &ModWriterEntry->u.IoStatus, 04354 0 ); 04355 KeLowerIrql (OldIrql); 04356 } 04357 #if 0 04358 //TEMPORARY code to use synchronous I/O here. 04359 04360 // 04361 // Issue the write request. 04362 // 04363 04364 Status = IoSynchronousPageWrite ( 04365 ModWriterEntry->File, 04366 &ModWriterEntry->Mdl, 04367 &ModWriterEntry->WriteOffset, 04368 &TempEvent, 04369 &ModWriterEntry->u.IoStatus ); 04370 04371 if (NT_ERROR(Status)) { 04372 ModWriterEntry->u.IoStatus.Status = Status; 04373 ModWriterEntry->u.IoStatus.Information = 0; 04374 } 04375 04376 if (NT_ERROR(ModWriterEntry->u.IoStatus.Status)) { 04377 KdPrint(("MM MODWRITE: modified page write failed %lx\n", Status)); 04378 } 04379 04380 // 04381 // Call the write completion routine. 04382 // 04383 04384 KeRaiseIrql (APC_LEVEL, &OldIrql); 04385 MiWriteComplete ((PVOID)ModWriterEntry, 04386 &ModWriterEntry->IoStatus, 04387 0 ); 04388 KeLowerIrql (OldIrql); 04389 #endif //0 04390 04391 } 04392 04393 } 04394 }

VOID MiModifiedPageWriter IN PVOID  StartContext  ) 
 

Definition at line 2669 of file modwrite.c.

References _MMMOD_WRITER_LISTHEAD::Event, ExAllocatePoolWithTag, FALSE, KeDelayExecutionThread(), KeInitializeEvent, KernelMode, KeSetPriorityThread(), L, _MMMOD_WRITER_MDL_ENTRY::Links, _MMMOD_WRITER_LISTHEAD::ListHead, MiMappedPageWriter(), MiModifiedPageWriterWorker(), MM_MAPPED_FILE_MDLS, MmFreePagingSpaceLow, MmMappedFileHeader, MmMappedFileMdl, MmMappedPageWriterEvent, MmMappedPageWriterList, MmModifiedWriteClusterSize, MmPagingFileHeader, MmSystemShutdown, NonPagedPoolMustSucceed, NULL, ObjectAttributes, PAGED_CODE, _MMMOD_WRITER_MDL_ENTRY::PagingFile, _MMMOD_WRITER_MDL_ENTRY::PagingListHead, PsCreateSystemThread(), PsGetCurrentThread, ThreadHandle, and VOID().

Referenced by MmInitSystem().

02675 : 02676 02677 Implements the NT modified page writer thread. When the modified 02678 page threshold is reached, or memory becomes overcommitted the 02679 modified page writer event is set, and this thread becomes active. 02680 02681 Arguments: 02682 02683 StartContext - not used. 02684 02685 Return Value: 02686 02687 None. 02688 02689 Environment: 02690 02691 Kernel mode. 02692 02693 --*/ 02694 02695 { 02696 HANDLE ThreadHandle; 02697 OBJECT_ATTRIBUTES ObjectAttributes; 02698 ULONG i; 02699 02700 PAGED_CODE(); 02701 02702 StartContext; //avoid compiler warning. 02703 02704 // 02705 // Initialize listheads as empty. 02706 // 02707 02708 MmSystemShutdown = 0; 02709 KeInitializeEvent (&MmPagingFileHeader.Event, NotificationEvent, FALSE); 02710 KeInitializeEvent (&MmMappedFileHeader.Event, NotificationEvent, FALSE); 02711 02712 InitializeListHead(&MmPagingFileHeader.ListHead); 02713 InitializeListHead(&MmMappedFileHeader.ListHead); 02714 InitializeListHead(&MmFreePagingSpaceLow); 02715 02716 for (i = 0; i < MM_MAPPED_FILE_MDLS; i += 1) { 02717 MmMappedFileMdl[i] = ExAllocatePoolWithTag (NonPagedPoolMustSucceed, 02718 sizeof(MMMOD_WRITER_MDL_ENTRY) + 02719 MmModifiedWriteClusterSize * 02720 sizeof(PFN_NUMBER), 02721 ' mM'); 02722 02723 MmMappedFileMdl[i]->PagingFile = NULL; 02724 MmMappedFileMdl[i]->PagingListHead = &MmMappedFileHeader; 02725 02726 InsertTailList (&MmMappedFileHeader.ListHead, 02727 &MmMappedFileMdl[i]->Links); 02728 } 02729 02730 // 02731 // Make this a real time thread. 02732 // 02733 02734 (VOID) KeSetPriorityThread (&PsGetCurrentThread()->Tcb, 02735 LOW_REALTIME_PRIORITY + 1); 02736 02737 // 02738 // Start a secondary thread for writing mapped file pages. This 02739 // is required as the writing of mapped file pages could cause 02740 // page faults resulting in requests for free pages. But there 02741 // could be no free pages - hence a dead lock. Rather than deadlock 02742 // the whole system waiting on the modified page writer, creating 02743 // a secondary thread allows that thread to block without affecting 02744 // on going page file writes. 02745 // 02746 02747 KeInitializeEvent (&MmMappedPageWriterEvent, NotificationEvent, FALSE); 02748 InitializeListHead(&MmMappedPageWriterList); 02749 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL ); 02750 02751 PsCreateSystemThread (&ThreadHandle, 02752 THREAD_ALL_ACCESS, 02753 &ObjectAttributes, 02754 0L, 02755 NULL, 02756 MiMappedPageWriter, 02757 NULL ); 02758 ZwClose (ThreadHandle); 02759 MiModifiedPageWriterWorker(); 02760 02761 // 02762 // Shutdown in progress, wait forever. 02763 // 02764 02765 { 02766 LARGE_INTEGER Forever; 02767 02768 // 02769 // System has shutdown, go into LONG wait. 02770 // 02771 02772 Forever.LowPart = 0; 02773 Forever.HighPart = 0xF000000; 02774 KeDelayExecutionThread (KernelMode, FALSE, &Forever); 02775 } 02776 02777 return; 02778 }

VOID MiModifiedPageWriterTimerDispatch IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 2782 of file modwrite.c.

References FALSE, KeSetEvent(), LOCK_PFN2, MiMappedPagesTooOldEvent, MiTimerPending, TRUE, and UNLOCK_PFN2.

Referenced by MmInitSystem().

02791 : 02792 02793 This routine is executed whenever modified mapped pages are waiting to 02794 be written. Its job is to signal the Modified Page Writer to write 02795 these out. 02796 02797 Arguments: 02798 02799 Dpc - Supplies a pointer to a control object of type DPC. 02800 02801 DeferredContext - Optional deferred context; not used. 02802 02803 SystemArgument1 - Optional argument 1; not used. 02804 02805 SystemArgument2 - Optional argument 2; not used. 02806 02807 Return Value: 02808 02809 None. 02810 02811 --*/ 02812 02813 { 02814 KIRQL OldIrql; 02815 02816 UNREFERENCED_PARAMETER (Dpc); 02817 UNREFERENCED_PARAMETER (DeferredContext); 02818 UNREFERENCED_PARAMETER (SystemArgument1); 02819 UNREFERENCED_PARAMETER (SystemArgument2); 02820 02821 LOCK_PFN2 (OldIrql); 02822 02823 MiTimerPending = TRUE; 02824 KeSetEvent (&MiMappedPagesTooOldEvent, 0, FALSE); 02825 02826 UNLOCK_PFN2 (OldIrql); 02827 }

VOID MiModifiedPageWriterWorker VOID   ) 
 

Definition at line 2831 of file modwrite.c.

References ASSERT, _SUBSECTION::ControlArea, _MMMOD_WRITER_LISTHEAD::Event, FALSE, _MMPFNLIST::Flink, _MMPAGING_FILE::HintSetToZero, KeClearEvent, KeDelayExecutionThread(), KernelMode, KeSetTimerEx(), KeWaitForMultipleObjects(), KeWaitForSingleObject(), _MMMOD_WRITER_LISTHEAD::ListHead, LOCK_PFN, MappedPagesNeedWriting, MI_GET_MODIFIED_PAGE_ANY_COLOR, MI_PFN_ELEMENT, MiFirstPageFileCreatedAndReady, MiGatherMappedPages(), MiGatherPagefilePages(), MiGetSubsectionAddress, MiInsertPageInList(), MiMappedPagesTooOldEvent, MiModifiedPageLife, MiModifiedPageWriterTimer, MiModifiedPageWriterTimerDpc, MiTimerPending, MiUnlinkPageFromList(), Mm30Milliseconds, MM_EMPTY_LIST, MmAvailablePages, MmFreeGoal, MmMappedFileHeader, MmModifiedNoWritePageListHead, MmModifiedPageListHead, MmModifiedPageWriterEvent, MmModNoWriteInsert, MmMoreThanEnoughFreePages, MmNumberOfPagingFiles, MmPagingFile, MmPagingFileHeader, MmShortTime, MmSystemShutdown, MmTotalPagesForPagingFile, MmWriteAllModifiedPages, ModifiedWriterMaximumObject, NormalCase, NTSTATUS(), NULL, _MMPFN::OriginalPte, _MMPFNLIST::Total, TRUE, _MMPTE::u, _CONTROL_AREA::u, UNLOCK_PFN, VOID(), WrFreePage, and WrPageOut.

Referenced by MiModifiedPageWriter().

02837 : 02838 02839 Implements the NT modified page writer thread. When the modified 02840 page threshold is reached, or memory becomes overcommitted the 02841 modified page writer event is set, and this thread becomes active. 02842 02843 Arguments: 02844 02845 None. 02846 02847 Return Value: 02848 02849 None. 02850 02851 Environment: 02852 02853 Kernel mode. 02854 02855 --*/ 02856 02857 { 02858 PMMPFN Pfn1; 02859 PFN_NUMBER PageFrameIndex; 02860 KIRQL OldIrql; 02861 ULONG NextColor; 02862 ULONG i; 02863 static KWAIT_BLOCK WaitBlockArray[ModifiedWriterMaximumObject]; 02864 PVOID WaitObjects[ModifiedWriterMaximumObject]; 02865 NTSTATUS WakeupStatus; 02866 02867 // 02868 // Wait for the modified page writer event or the mapped pages event. 02869 // 02870 02871 WaitObjects[NormalCase] = (PVOID)&MmModifiedPageWriterEvent; 02872 WaitObjects[MappedPagesNeedWriting] = (PVOID)&MiMappedPagesTooOldEvent; 02873 02874 for (;;) { 02875 02876 WakeupStatus = KeWaitForMultipleObjects(ModifiedWriterMaximumObject, 02877 &WaitObjects[0], 02878 WaitAny, 02879 WrFreePage, 02880 KernelMode, 02881 FALSE, 02882 NULL, 02883 &WaitBlockArray[0]); 02884 02885 // 02886 // Switch on the wait status. 02887 // 02888 02889 switch (WakeupStatus) { 02890 02891 case NormalCase: 02892 break; 02893 02894 case MappedPagesNeedWriting: 02895 02896 // 02897 // Our mapped pages DPC went off, only deal with those pages. 02898 // Write all the mapped pages (ONLY), then clear the flag 02899 // and come back to the top. 02900 // 02901 02902 break; 02903 02904 default: 02905 break; 02906 02907 } 02908 02909 // 02910 // Indicate that the hint values have not been reset in 02911 // the paging files. 02912 // 02913 02914 if (MmNumberOfPagingFiles != 0) { 02915 i = 0; 02916 do { 02917 MmPagingFile[i]->HintSetToZero = FALSE; 02918 i += 1; 02919 } while (i < MmNumberOfPagingFiles); 02920 } 02921 02922 NextColor = 0; 02923 02924 LOCK_PFN (OldIrql); 02925 02926 for (;;) { 02927 02928 // 02929 // Modified page writer was signalled. 02930 // 02931 02932 if ((MmAvailablePages < MmFreeGoal) && 02933 (MmModNoWriteInsert)) { 02934 02935 // 02936 // Remove pages from the modified no write list 02937 // that are waiting for the cache manager to flush them. 02938 // 02939 02940 i = 0; 02941 while ((MmModifiedNoWritePageListHead.Total != 0) && 02942 (i < 32)) { 02943 PSUBSECTION Subsection; 02944 PCONTROL_AREA ControlArea; 02945 02946 PageFrameIndex = MmModifiedNoWritePageListHead.Flink; 02947 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02948 Subsection = MiGetSubsectionAddress (&Pfn1->OriginalPte); 02949 ControlArea = Subsection->ControlArea; 02950 if (ControlArea->u.Flags.NoModifiedWriting) { 02951 MmModNoWriteInsert = FALSE; 02952 break; 02953 } 02954 MiUnlinkPageFromList (Pfn1); 02955 MiInsertPageInList (&MmModifiedPageListHead, 02956 PageFrameIndex); 02957 i += 1; 02958 } 02959 } 02960 02961 if (MmModifiedPageListHead.Total == 0) { 02962 02963 // 02964 // No more pages, clear the event(s) and wait again... 02965 // Note we can clear both events regardless of why we woke up 02966 // since no modified pages of any type exist. 02967 // 02968 02969 if (MiTimerPending == TRUE) { 02970 MiTimerPending = FALSE; 02971 KeClearEvent (&MiMappedPagesTooOldEvent); 02972 } 02973 02974 UNLOCK_PFN (OldIrql); 02975 02976 KeClearEvent (&MmModifiedPageWriterEvent); 02977 02978 break; 02979 } 02980 02981 // 02982 // If we didn't wake up explicitly to deal with mapped pages, 02983 // then determine which type of pages are the most popular: 02984 // page file backed pages, or mapped file backed pages. 02985 // 02986 02987 if (WakeupStatus == MappedPagesNeedWriting) { 02988 PageFrameIndex = MmModifiedPageListHead.Flink; 02989 if (PageFrameIndex == MM_EMPTY_LIST) { 02990 02991 // 02992 // No more modified mapped pages (there may still be 02993 // modified pagefile-destined pages), so clear only the 02994 // mapped pages event and check for directions at the top 02995 // again. 02996 // 02997 02998 MiTimerPending = FALSE; 02999 KeClearEvent (&MiMappedPagesTooOldEvent); 03000 03001 UNLOCK_PFN (OldIrql); 03002 03003 break; 03004 } 03005 } 03006 else if (MmTotalPagesForPagingFile >= 03007 (MmModifiedPageListHead.Total - MmTotalPagesForPagingFile)) { 03008 03009 // 03010 // More pages are destined for the paging file. 03011 // 03012 03013 MI_GET_MODIFIED_PAGE_ANY_COLOR (PageFrameIndex, NextColor); 03014 03015 } else { 03016 03017 // 03018 // More pages are destined for mapped files. 03019 // 03020 03021 PageFrameIndex = MmModifiedPageListHead.Flink; 03022 } 03023 03024 // 03025 // Check to see what type of page (section file backed or page 03026 // file backed) and write out that page and more if possible. 03027 // 03028 03029 // 03030 // Check to see if this page is destined for a paging file or 03031 // a mapped file. 03032 // 03033 03034 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03035 03036 if (Pfn1->OriginalPte.u.Soft.Prototype == 1) { 03037 if (IsListEmpty (&MmMappedFileHeader.ListHead)) { 03038 03039 // 03040 // Make sure page is destined for paging file as there 03041 // are no MDLs for mapped writes free. 03042 // 03043 03044 if (WakeupStatus != MappedPagesNeedWriting) { 03045 03046 MI_GET_MODIFIED_PAGE_ANY_COLOR (PageFrameIndex, NextColor); 03047 03048 // 03049 // No pages are destined for the paging file, get the 03050 // first page destined for a mapped file. 03051 // 03052 03053 if (PageFrameIndex == MM_EMPTY_LIST) { 03054 03055 // 03056 // Select the first page from the list anyway. 03057 // 03058 03059 PageFrameIndex = MmModifiedPageListHead.Flink; 03060 } 03061 03062 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03063 } 03064 } 03065 } else if ((IsListEmpty(&MmPagingFileHeader.ListHead)) || 03066 (MiFirstPageFileCreatedAndReady == FALSE)) { 03067 03068 // 03069 // Try for a dirty section-backed page as no paging file MDLs 03070 // are available. 03071 // 03072 03073 if (MmModifiedPageListHead.Flink != MM_EMPTY_LIST) { 03074 ASSERT (MmTotalPagesForPagingFile != MmModifiedPageListHead.Total); 03075 PageFrameIndex = MmModifiedPageListHead.Flink; 03076 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03077 } 03078 else { 03079 ASSERT (MmTotalPagesForPagingFile == MmModifiedPageListHead.Total); 03080 if ((MiFirstPageFileCreatedAndReady == FALSE) && 03081 (MmNumberOfPagingFiles != 0)) { 03082 03083 // 03084 // The first paging has been created but the reservation 03085 // checking for crashdumps has not finished yet. Delay 03086 // a bit as this will finish shortly and then restart. 03087 // 03088 03089 UNLOCK_PFN (OldIrql); 03090 KeDelayExecutionThread (KernelMode, FALSE, &MmShortTime); 03091 LOCK_PFN (OldIrql); 03092 continue; 03093 } 03094 } 03095 } 03096 03097 if (Pfn1->OriginalPte.u.Soft.Prototype == 1) { 03098 03099 if (IsListEmpty(&MmMappedFileHeader.ListHead)) { 03100 03101 if (WakeupStatus == MappedPagesNeedWriting) { 03102 03103 // 03104 // Since we woke up only to take care of mapped pages, 03105 // don't wait for an MDL below because drivers may take 03106 // an inordinate amount of time processing the 03107 // outstanding ones. We might have to wait too long, 03108 // resulting in the system running out of pages. 03109 // 03110 03111 if (MiTimerPending == TRUE) { 03112 03113 // 03114 // This should be normal case - the reason we must 03115 // first check timer pending above is for the rare 03116 // case - when this thread first ran for normal 03117 // modified page processing and took 03118 // care of all the pages including the mapped ones. 03119 // Then this thread woke up again for the mapped 03120 // reason and here we are. 03121 // 03122 03123 MiTimerPending = FALSE; 03124 KeClearEvent (&MiMappedPagesTooOldEvent); 03125 } 03126 03127 MiTimerPending = TRUE; 03128 03129 (VOID) KeSetTimerEx( &MiModifiedPageWriterTimer, MiModifiedPageLife, 0, &MiModifiedPageWriterTimerDpc ); 03130 UNLOCK_PFN (OldIrql); 03131 break; 03132 } 03133 03134 // 03135 // Reset the event indicating no mapped files in 03136 // the list, drop the PFN lock and wait for an 03137 // I/O operation to complete with a one second 03138 // timeout. 03139 // 03140 03141 KeClearEvent (&MmMappedFileHeader.Event); 03142 03143 UNLOCK_PFN (OldIrql); 03144 KeWaitForSingleObject( &MmMappedFileHeader.Event, 03145 WrPageOut, 03146 KernelMode, 03147 FALSE, 03148 &Mm30Milliseconds); 03149 LOCK_PFN (OldIrql); 03150 03151 // 03152 // Don't go on as the old PageFrameIndex at the 03153 // top of the ModifiedList may have changed states. 03154 // 03155 03156 continue; 03157 } 03158 03159 MiGatherMappedPages (Pfn1, PageFrameIndex); 03160 03161 } else { 03162 03163 MiGatherPagefilePages (Pfn1, PageFrameIndex); 03164 } 03165 03166 if (MmSystemShutdown) { 03167 03168 // 03169 // Shutdown has returned. Stop the modified page writer. 03170 // 03171 03172 UNLOCK_PFN (OldIrql); 03173 return; 03174 } 03175 03176 if (WakeupStatus != MappedPagesNeedWriting && !MmWriteAllModifiedPages) { 03177 if (((MmAvailablePages > MmFreeGoal) && 03178 (MmModifiedPageListHead.Total < MmFreeGoal)) 03179 || 03180 (MmAvailablePages > MmMoreThanEnoughFreePages)) { 03181 03182 // 03183 // There are ample pages, clear the event and wait again... 03184 // 03185 03186 UNLOCK_PFN (OldIrql); 03187 03188 KeClearEvent (&MmModifiedPageWriterEvent); 03189 break; 03190 } 03191 } 03192 } // end for 03193 03194 } // end for 03195 }

VOID MiPageFileFull  ) 
 

Definition at line 4709 of file modwrite.c.

References ASSERT, FALSE, _MMPAGING_FILE::FreeSpace, LOCK_PFN, _MMPAGING_FILE::MaximumSize, MI_PAGEFILE_FULL_CHARGE, MiCauseOverCommitPopup(), MiChargeCommitmentCantExpand(), MiPageFileFullCharge, MiReturnCommitment(), MM_DBG_COMMIT_PAGEFILE_FULL, MM_PFN_LOCK_ASSERT, MM_TRACK_COMMIT, MmChargeCommitmentLock, MmNumberOfPagingFiles, MmPageFileFullExtendCount, MmPageFileFullExtendPages, MmPageFileFullPopupShown, MmPagingFile, MmTotalCommitLimit, MmTotalCommittedPages, _MMPAGING_FILE::Size, TRUE, and UNLOCK_PFN.

Referenced by MiGatherPagefilePages().

04714 : 04715 04716 This routine is called when no space can be found in a paging file. 04717 It looks through all the paging files to see if ample space is 04718 available and if not, tries to expand the paging files. 04719 04720 If more than 90% of all paging files is used, the commitment limit 04721 is set to the total and then 100 pages are added. 04722 04723 Arguments: 04724 04725 None. 04726 04727 Return Value: 04728 04729 None. 04730 04731 --*/ 04732 04733 { 04734 ULONG i; 04735 PFN_NUMBER Total; 04736 PFN_NUMBER Free; 04737 KIRQL OldIrql; 04738 SIZE_T SizeToExpand; 04739 04740 MM_PFN_LOCK_ASSERT(); 04741 04742 Total = 0; 04743 Free = 0; 04744 OldIrql = 0; 04745 04746 i = 0; 04747 do { 04748 Total += MmPagingFile[i]->Size; 04749 Free += MmPagingFile[i]->FreeSpace; 04750 i += 1; 04751 } while (i < MmNumberOfPagingFiles); 04752 04753 // 04754 // Check to see if more than 90% of the total space has been used. 04755 // 04756 04757 if (((Total >> 5) + (Total >> 4)) >= Free) { 04758 04759 // 04760 // Try to expand the paging files. 04761 // 04762 04763 UNLOCK_PFN (OldIrql); 04764 04765 // 04766 // Check commit limits and set the limit to what is now used. 04767 // If all the pagefiles are already at their maximums, then don't 04768 // make things worse by setting commit to the maximum - this gives 04769 // systems with lots of memory a longer lease on life when they have 04770 // small pagefiles. 04771 // 04772 04773 SizeToExpand = 0; 04774 i = 0; 04775 04776 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 04777 04778 do { 04779 SizeToExpand += MmPagingFile[i]->MaximumSize - MmPagingFile[i]->Size; 04780 i += 1; 04781 } while (i < MmNumberOfPagingFiles); 04782 04783 if (SizeToExpand == 0) { 04784 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 04785 04786 // 04787 // Display a popup once. 04788 // 04789 04790 if (MmPageFileFullPopupShown == FALSE) { 04791 MmPageFileFullPopupShown = TRUE; 04792 MiCauseOverCommitPopup (1, 0); 04793 } 04794 04795 LOCK_PFN (OldIrql); 04796 return; 04797 } 04798 04799 if (MmTotalCommittedPages <= MmTotalCommitLimit + 50) { 04800 04801 // 04802 // The total commit limit is less than the number of committed 04803 // pages + 50. Reset commit limit. 04804 // 04805 04806 if (MmTotalCommittedPages < MmTotalCommitLimit) { 04807 04808 if (MmPageFileFullExtendPages) { 04809 ASSERT (MmTotalCommittedPages >= MmPageFileFullExtendPages); 04810 MmTotalCommittedPages -= MmPageFileFullExtendPages; 04811 MmPageFileFullExtendPages = 0; 04812 } 04813 04814 MmPageFileFullExtendPages = MmTotalCommitLimit - MmTotalCommittedPages; 04815 MmPageFileFullExtendCount += 1; 04816 04817 MmTotalCommittedPages = MmTotalCommitLimit; 04818 } 04819 04820 // 04821 // Charge 100 pages against the commitment. 04822 // 04823 04824 MiPageFileFullCharge += MI_PAGEFILE_FULL_CHARGE; 04825 04826 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 04827 04828 MiChargeCommitmentCantExpand (MI_PAGEFILE_FULL_CHARGE, TRUE); 04829 04830 MM_TRACK_COMMIT (MM_DBG_COMMIT_PAGEFILE_FULL, 100); 04831 04832 // 04833 // Display a popup once. 04834 // 04835 04836 if (MmPageFileFullPopupShown == FALSE) { 04837 MmPageFileFullPopupShown = TRUE; 04838 MiCauseOverCommitPopup (1, 0); 04839 } 04840 04841 // 04842 // Delay a bit before returning the commitment so the segment 04843 // dereference thread gets a chance to actually grow the pagefile. 04844 // 04845 04846 if (MiPageFileFullCharge >= 5 * MI_PAGEFILE_FULL_CHARGE) { 04847 ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql); 04848 SizeToExpand = MiPageFileFullCharge; 04849 MiPageFileFullCharge = 0; 04850 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 04851 MiReturnCommitment (SizeToExpand); 04852 } 04853 04854 } 04855 else { 04856 04857 // 04858 // Commit limit is lower than the number of committed pages. 04859 // 04860 04861 ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql); 04862 } 04863 04864 LOCK_PFN (OldIrql); 04865 } 04866 return; 04867 }

VOID MiPageFileFull VOID   ) 
 

VOID MiReleaseModifiedWriter VOID   ) 
 

Definition at line 275 of file modwrite.c.

References LOCK_PFN, MiFirstPageFileCreatedAndReady, TRUE, and UNLOCK_PFN.

Referenced by NtCreatePagingFile().

00281 : 00282 00283 Nonpagable wrapper to signal the modified writer when the first pagefile 00284 creation has completely finished. 00285 00286 --*/ 00287 00288 { 00289 KIRQL OldIrql; 00290 LOCK_PFN (OldIrql); 00291 MiFirstPageFileCreatedAndReady = TRUE; 00292 UNLOCK_PFN (OldIrql); 00293 }

VOID MiWriteComplete IN PVOID  Context,
IN PIO_STATUS_BLOCK  IoStatus,
IN ULONG  Reserved
 

Definition at line 2234 of file modwrite.c.

References ASSERT, _MDL::ByteCount, _MMMOD_WRITER_MDL_ENTRY::ControlArea, _MMMOD_WRITER_MDL_ENTRY::CurrentList, DbgPrint, _MMMOD_WRITER_LISTHEAD::Event, FALSE, _MMMOD_WRITER_MDL_ENTRY::File, _FILE_OBJECT::FileName, _CONTROL_AREA::FilePointer, _MMMOD_WRITER_MDL_ENTRY::FileResource, _MMPAGING_FILE::FreeSpace, FsRtlReleaseFileForModWrite(), GET_PAGING_FILE_NUMBER, GET_PAGING_FILE_OFFSET, IoRaiseInformationalHardError(), KeDelayExecutionThread(), KePulseEvent(), KernelMode, KeSetEvent(), _MMMOD_WRITER_MDL_ENTRY::LastPageToWrite, _MMMOD_WRITER_MDL_ENTRY::Links, _MMMOD_WRITER_LISTHEAD::ListHead, LOCK_PFN, _MDL::MappedSystemVa, _MMMOD_WRITER_MDL_ENTRY::Mdl, MDL_MAPPED_TO_SYSTEM_VA, _MDL::MdlFlags, MI_IS_PFN_DELETED, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MiCheckControlArea(), MiDecrementReferenceCount(), MiGetPteAddress, MiReleasePageFileSpace(), Mm30Milliseconds, MM_COPY_ON_WRITE_MASK, MM_DBG_MOD_WRITE, MM_DBG_PRINTS_MODWRITES, MM_PROTECTION_WRITE_MASK, MM_USABLE_PAGES_FREE, MmFreePagingSpaceLow, MmMappedFileIoComplete, MmNumberOfActiveMdlEntries, MmPagingFileDebug, MmPagingFileHeader, MmUnmapLockedPages(), _CONTROL_AREA::ModifiedWriteCount, NT_ERROR, NTSTATUS(), NULL, _CONTROL_AREA::NumberOfPfnReferences, Offset, _MMPFN::OriginalPte, _MMMOD_WRITER_MDL_ENTRY::Page, PAGE_SIZE, _MMMOD_WRITER_MDL_ENTRY::PagingFile, _MMMOD_WRITER_MDL_ENTRY::PagingListHead, PDE_TOP, _MMPFN::PteAddress, SHORT, TRUE, _CONTROL_AREA::u, _MMPTE::u, _MMPFN::u3, and UNLOCK_PFN.

Referenced by MiCancelWriteOfMappedPfn(), MiGatherMappedPages(), MiGatherPagefilePages(), and MiMappedPageWriter().

02242 : 02243 02244 This routine is the APC write completion procedure. It is invoked 02245 at APC_LEVEL when a page write operation is completed. 02246 02247 Arguments: 02248 02249 Context - Supplies a pointer to the MOD_WRITER_MDL_ENTRY which was 02250 used for this I/O. 02251 02252 IoStatus - Supplies a pointer to the IO_STATUS_BLOCK which was used 02253 for this I/O. 02254 02255 Return Value: 02256 02257 None. 02258 02259 Environment: 02260 02261 Kernel mode, APC_LEVEL. 02262 02263 --*/ 02264 02265 { 02266 02267 PMMMOD_WRITER_MDL_ENTRY WriterEntry; 02268 PMMMOD_WRITER_MDL_ENTRY NextWriterEntry; 02269 PPFN_NUMBER Page; 02270 PMMPFN Pfn1; 02271 KIRQL OldIrql; 02272 LONG ByteCount; 02273 NTSTATUS status; 02274 PCONTROL_AREA ControlArea; 02275 ULONG FailAllIo; 02276 PFILE_OBJECT FileObject; 02277 PERESOURCE FileResource; 02278 02279 UNREFERENCED_PARAMETER (Reserved); 02280 02281 FailAllIo = FALSE; 02282 02283 #if DBG 02284 if (MmDebug & MM_DBG_MOD_WRITE) { 02285 DbgPrint("MM MODWRITE: modified page write completed\n"); 02286 } 02287 #endif 02288 02289 // 02290 // A page write has completed, at this time the pages are not 02291 // on any lists, write-in-progress is set in the PFN database, 02292 // and the reference count was incremented. 02293 // 02294 02295 WriterEntry = (PMMMOD_WRITER_MDL_ENTRY)Context; 02296 ByteCount = (LONG)WriterEntry->Mdl.ByteCount; 02297 Page = &WriterEntry->Page[0]; 02298 02299 if (WriterEntry->Mdl.MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { 02300 MmUnmapLockedPages (WriterEntry->Mdl.MappedSystemVa, 02301 &WriterEntry->Mdl); 02302 } 02303 02304 // 02305 // Get the PFN lock so the PFN database can be manipulated. 02306 // 02307 02308 status = IoStatus->Status; 02309 ControlArea = WriterEntry->ControlArea; 02310 02311 LOCK_PFN (OldIrql); 02312 02313 // 02314 // Indicate that the write is complete. 02315 // 02316 02317 WriterEntry->LastPageToWrite = 0; 02318 02319 02320 while (ByteCount > 0) { 02321 02322 Pfn1 = MI_PFN_ELEMENT (*Page); 02323 ASSERT (Pfn1->u3.e1.WriteInProgress == 1); 02324 #if DBG 02325 02326 if (Pfn1->OriginalPte.u.Soft.Prototype == 0) { 02327 02328 ULONG Offset; 02329 Offset = GET_PAGING_FILE_OFFSET(Pfn1->OriginalPte); 02330 if ((Offset < 8192) && 02331 (GET_PAGING_FILE_NUMBER(Pfn1->OriginalPte) == 0)) { 02332 ASSERT ((MmPagingFileDebug[Offset] & 1) != 0); 02333 if (!MI_IS_PFN_DELETED(Pfn1)) { 02334 if ((GET_PAGING_FILE_NUMBER (Pfn1->OriginalPte)) == 0) { 02335 if ((MmPagingFileDebug[Offset] & ~0x1f) != 02336 ((ULONG_PTR)Pfn1->PteAddress << 3)) { 02337 if (Pfn1->PteAddress != MiGetPteAddress(PDE_BASE)) { 02338 02339 // 02340 // Make sure this isn't a PTE that was forked 02341 // during the I/O. 02342 // 02343 02344 if ((Pfn1->PteAddress < (PMMPTE)PDE_TOP) || 02345 ((Pfn1->OriginalPte.u.Soft.Protection & 02346 MM_COPY_ON_WRITE_MASK) == 02347 MM_PROTECTION_WRITE_MASK)) { 02348 DbgPrint("MMWRITE: Mismatch Pfn1 %p Offset %lx info %p\n", 02349 Pfn1, 02350 Offset, 02351 MmPagingFileDebug[Offset]); 02352 02353 DbgBreakPoint(); 02354 02355 } else { 02356 MmPagingFileDebug[Offset] &= 0x1f; 02357 MmPagingFileDebug[Offset] |= 02358 ((ULONG_PTR)Pfn1->PteAddress << 3); 02359 } 02360 } 02361 02362 } 02363 } 02364 } 02365 } 02366 } 02367 #endif //DBG 02368 02369 Pfn1->u3.e1.WriteInProgress = 0; 02370 02371 if (NT_ERROR(status)) { 02372 02373 // 02374 // If the file object is over the network, assume that this 02375 // I/O operation can never complete and mark the pages as 02376 // clean and indicate in the control area all I/O should fail. 02377 // Note that the modified bit in the PFN database is not set. 02378 // 02379 02380 if (((status != STATUS_FILE_LOCK_CONFLICT) && 02381 (ControlArea != NULL) && 02382 (ControlArea->u.Flags.Networked == 1)) 02383 || 02384 (status == STATUS_FILE_INVALID)) { 02385 02386 if (ControlArea->u.Flags.FailAllIo == 0) { 02387 ControlArea->u.Flags.FailAllIo = 1; 02388 FailAllIo = TRUE; 02389 02390 KdPrint(("MM MODWRITE: failing all io, controlarea %lx status %lx\n", 02391 ControlArea, status)); 02392 } 02393 } else { 02394 02395 // 02396 // The modified write operation failed, SET the modified bit 02397 // for each page which was written and free the page file 02398 // space. 02399 // 02400 02401 #if DBG 02402 if ((status != STATUS_FILE_LOCK_CONFLICT) && 02403 ((MmDebug & MM_DBG_PRINTS_MODWRITES) == 0)) { 02404 KdPrint(("MM MODWRITE: modified page write iosb failed - status 0x%lx\n", 02405 status)); 02406 } 02407 #endif 02408 02409 Pfn1->u3.e1.Modified = 1; 02410 } 02411 } 02412 02413 if ((Pfn1->u3.e1.Modified == 1) && 02414 (Pfn1->OriginalPte.u.Soft.Prototype == 0)) { 02415 02416 // 02417 // This page was modified since the write was done, 02418 // release the page file space. 02419 // 02420 02421 MiReleasePageFileSpace (Pfn1->OriginalPte); 02422 Pfn1->OriginalPte.u.Soft.PageFileHigh = 0; 02423 } 02424 02425 MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 15); 02426 MiDecrementReferenceCount (*Page); 02427 #if DBG 02428 *Page = 0xF0FFFFFF; 02429 #endif //DBG 02430 02431 Page += 1; 02432 ByteCount -= (LONG)PAGE_SIZE; 02433 } 02434 02435 // 02436 // Check to which list to insert this entry into depending on 02437 // the amount of free space left in the paging file. 02438 // 02439 02440 FileObject = WriterEntry->File; 02441 FileResource = WriterEntry->FileResource; 02442 02443 if ((WriterEntry->PagingFile != NULL) && 02444 (WriterEntry->PagingFile->FreeSpace < MM_USABLE_PAGES_FREE)) { 02445 02446 if (MmNumberOfActiveMdlEntries == 1) { 02447 02448 // 02449 // If we put this entry on the list, there will be 02450 // no more paging. Locate all entries which are non 02451 // zero and pull them from the list. 02452 // 02453 02454 InsertTailList (&MmFreePagingSpaceLow, &WriterEntry->Links); 02455 WriterEntry->CurrentList = &MmFreePagingSpaceLow; 02456 02457 MmNumberOfActiveMdlEntries -= 1; 02458 02459 // 02460 // Try to pull entries off the list. 02461 // 02462 02463 WriterEntry = (PMMMOD_WRITER_MDL_ENTRY)MmFreePagingSpaceLow.Flink; 02464 02465 while ((PLIST_ENTRY)WriterEntry != &MmFreePagingSpaceLow) { 02466 02467 NextWriterEntry = 02468 (PMMMOD_WRITER_MDL_ENTRY)WriterEntry->Links.Flink; 02469 02470 if (WriterEntry->PagingFile->FreeSpace != 0) { 02471 02472 RemoveEntryList (&WriterEntry->Links); 02473 02474 // 02475 // Insert this into the active list. 02476 // 02477 02478 if (IsListEmpty (&WriterEntry->PagingListHead->ListHead)) { 02479 KeSetEvent (&WriterEntry->PagingListHead->Event, 02480 0, 02481 FALSE); 02482 } 02483 02484 InsertTailList (&WriterEntry->PagingListHead->ListHead, 02485 &WriterEntry->Links); 02486 WriterEntry->CurrentList = &MmPagingFileHeader.ListHead; 02487 MmNumberOfActiveMdlEntries += 1; 02488 } 02489 02490 WriterEntry = NextWriterEntry; 02491 } 02492 02493 } else { 02494 02495 InsertTailList (&MmFreePagingSpaceLow, &WriterEntry->Links); 02496 WriterEntry->CurrentList = &MmFreePagingSpaceLow; 02497 MmNumberOfActiveMdlEntries -= 1; 02498 } 02499 } else { 02500 02501 // 02502 // Ample space exists, put this on the active list. 02503 // 02504 02505 if (IsListEmpty (&WriterEntry->PagingListHead->ListHead)) { 02506 KeSetEvent (&WriterEntry->PagingListHead->Event, 0, FALSE); 02507 } 02508 02509 InsertTailList (&WriterEntry->PagingListHead->ListHead, 02510 &WriterEntry->Links); 02511 } 02512 02513 ASSERT (((ULONG_PTR)WriterEntry->Links.Flink & 1) == 0); 02514 02515 UNLOCK_PFN (OldIrql); 02516 02517 if (FileResource != NULL) { 02518 FsRtlReleaseFileForModWrite (FileObject, FileResource); 02519 } 02520 02521 if (FailAllIo) { 02522 02523 if (ControlArea->FilePointer->FileName.Length && 02524 ControlArea->FilePointer->FileName.MaximumLength && 02525 ControlArea->FilePointer->FileName.Buffer) { 02526 02527 IoRaiseInformationalHardError( 02528 STATUS_LOST_WRITEBEHIND_DATA, 02529 &ControlArea->FilePointer->FileName, 02530 NULL 02531 ); 02532 } 02533 } 02534 02535 if (ControlArea != NULL) { 02536 02537 LOCK_PFN (OldIrql); 02538 02539 // 02540 // A write to a mapped file just completed, check to see if 02541 // there are any waiters on the completion of this i/o. 02542 // 02543 02544 ControlArea->ModifiedWriteCount -= 1; 02545 ASSERT ((SHORT)ControlArea->ModifiedWriteCount >= 0); 02546 if (ControlArea->u.Flags.SetMappedFileIoComplete != 0) { 02547 KePulseEvent (&MmMappedFileIoComplete, 02548 0, 02549 FALSE); 02550 } 02551 02552 ControlArea->NumberOfPfnReferences -= 1; 02553 02554 if (ControlArea->NumberOfPfnReferences == 0) { 02555 02556 // 02557 // This routine return with the PFN lock released!. 02558 // 02559 02560 MiCheckControlArea (ControlArea, NULL, OldIrql); 02561 } else { 02562 UNLOCK_PFN (OldIrql); 02563 } 02564 } 02565 02566 if (NT_ERROR(status)) { 02567 02568 // 02569 // Wait for a short time so other processing can continue. 02570 // 02571 02572 KeDelayExecutionThread (KernelMode, FALSE, &Mm30Milliseconds); 02573 } 02574 02575 return; 02576 }

BOOLEAN MmDisableModifiedWriteOfSection IN PSECTION_OBJECT_POINTERS  SectionObjectPointer  ) 
 

Definition at line 4397 of file modwrite.c.

References LOCK_PFN, NULL, _CONTROL_AREA::NumberOfMappedViews, _CONTROL_AREA::u, and UNLOCK_PFN.

Referenced by CcInitializeCacheMap().

04403 : 04404 04405 This function disables page writing by the modified page writer for 04406 the section which is mapped by the specified file object pointer. 04407 04408 This should only be used for files which CANNOT be mapped by user 04409 programs, e.g., volume files, directory files, etc. 04410 04411 Arguments: 04412 04413 SectionObjectPointer - Supplies a pointer to the section objects 04414 04415 04416 Return Value: 04417 04418 Returns TRUE if the operation was a success, FALSE if either 04419 the there is no section or the section already has a view. 04420 04421 --*/ 04422 04423 { 04424 PCONTROL_AREA ControlArea; 04425 KIRQL OldIrql; 04426 BOOLEAN state = 1; 04427 04428 LOCK_PFN (OldIrql); 04429 04430 ControlArea = ((PCONTROL_AREA)(SectionObjectPointer->DataSectionObject)); 04431 04432 if (ControlArea != NULL) { 04433 if (ControlArea->NumberOfMappedViews == 0) { 04434 04435 // 04436 // There are no views to this section, indicate no modified 04437 // page writing is allowed. 04438 // 04439 04440 ControlArea->u.Flags.NoModifiedWriting = 1; 04441 } else { 04442 04443 // 04444 // Return the current modified page writing state. 04445 // 04446 04447 state = (BOOLEAN)ControlArea->u.Flags.NoModifiedWriting; 04448 } 04449 } else { 04450 04451 // 04452 // This file no longer has an associated segment. 04453 // 04454 04455 state = 0; 04456 } 04457 04458 UNLOCK_PFN (OldIrql); 04459 return state; 04460 }

NTSTATUS MmGetCrashDumpInformation IN PSYSTEM_CRASH_DUMP_INFORMATION  CrashInfo  ) 
 

Definition at line 1392 of file modwrite.c.

References Handle, MmCrashDumpSection, NT_SUCCESS, NTSTATUS(), NULL, ObInsertObject(), PAGED_CODE, and Status.

Referenced by NtQuerySystemInformation().

01398 : 01399 01400 This function checks to see if a crash dump section exists and 01401 if so creates a handle to the section and returns that value 01402 in the CrashDumpInformation structure. Once the handle to the 01403 section has been created, no other references can be made 01404 to the crash dump section, and when that handle is closed, the 01405 crash dump section is deleted and the paging file space is 01406 available for reuse. 01407 01408 Arguments: 01409 01410 CrashInfo - Supplies a pointer to the crash dump information 01411 structure. 01412 01413 Return Value: 01414 01415 Status of the operation. A handle value of zero indicates no 01416 crash dump was located. 01417 01418 --*/ 01419 01420 { 01421 NTSTATUS Status; 01422 HANDLE Handle; 01423 01424 PAGED_CODE(); 01425 01426 if (MmCrashDumpSection == NULL) { 01427 Handle = 0; 01428 Status = STATUS_SUCCESS; 01429 } else { 01430 Status = ObInsertObject (MmCrashDumpSection, 01431 NULL, 01432 SECTION_MAP_READ, 01433 0, 01434 (PVOID *)NULL, 01435 &Handle); 01436 if (NT_SUCCESS(Status)) { 01437 01438 // 01439 // One shot operation. 01440 // 01441 01442 MmCrashDumpSection = NULL; 01443 } 01444 } 01445 01446 CrashInfo->CrashDumpSection = Handle; 01447 return Status; 01448 }

NTSTATUS MmGetCrashDumpStateInformation IN PSYSTEM_CRASH_STATE_INFORMATION  CrashInfo  ) 
 

Definition at line 1452 of file modwrite.c.

References MmCrashDumpSection, NULL, and PAGED_CODE.

Referenced by NtQuerySystemInformation().

01458 : 01459 01460 This function checks to see if a crash dump section exists and 01461 returns a BOOLEAN value in the CrashStateInformation structure 01462 based on the outcome. 01463 01464 Arguments: 01465 01466 CrashInfo - Supplies a pointer to the crash dump state information 01467 structure. 01468 01469 Return Value: 01470 01471 Status of the operation. A BOOLEAN value of FALSE indicates no 01472 crash dump was located. 01473 01474 --*/ 01475 01476 { 01477 PAGED_CODE(); 01478 01479 CrashInfo->ValidCrashDump = (MmCrashDumpSection != NULL); 01480 return STATUS_SUCCESS; 01481 }

NTSTATUS MmGetPageFileInformation OUT PVOID  SystemInformation,
IN ULONG  SystemInformationLength,
OUT PULONG  Length
 

Definition at line 4466 of file modwrite.c.

References _MMPAGING_FILE::CurrentUsage, MmNumberOfPagingFiles, MmPagingFile, PAGED_CODE, _MMPAGING_FILE::PageFileName, _MMPAGING_FILE::PeakUsage, ROUND_UP, and _MMPAGING_FILE::Size.

Referenced by NtQuerySystemInformation().

04474 : 04475 04476 This routine returns information about the currently active paging 04477 files. 04478 04479 Arguments: 04480 04481 SystemInformation - Returns the paging file information. 04482 04483 SystemInformationLength - Supplies the length of the SystemInformation 04484 buffer. 04485 04486 Length - Returns the length of the paging file information placed in the 04487 buffer. 04488 04489 Return Value: 04490 04491 Returns the status of the operation. 04492 04493 --*/ 04494 04495 { 04496 PSYSTEM_PAGEFILE_INFORMATION PageFileInfo; 04497 ULONG NextEntryOffset = 0; 04498 ULONG TotalSize = 0; 04499 ULONG i; 04500 UNICODE_STRING UserBufferPageFileName; 04501 04502 PAGED_CODE(); 04503 04504 *Length = 0; 04505 PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)SystemInformation; 04506 04507 PageFileInfo->TotalSize = 0; 04508 04509 for (i = 0; i < MmNumberOfPagingFiles; i += 1) { 04510 PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)( 04511 (PUCHAR)PageFileInfo + NextEntryOffset); 04512 NextEntryOffset = sizeof(SYSTEM_PAGEFILE_INFORMATION); 04513 TotalSize += sizeof(SYSTEM_PAGEFILE_INFORMATION); 04514 04515 if (TotalSize > SystemInformationLength) { 04516 return STATUS_INFO_LENGTH_MISMATCH; 04517 } 04518 04519 PageFileInfo->TotalSize = (ULONG)MmPagingFile[i]->Size; 04520 PageFileInfo->TotalInUse = (ULONG)MmPagingFile[i]->CurrentUsage; 04521 PageFileInfo->PeakUsage = (ULONG)MmPagingFile[i]->PeakUsage; 04522 04523 // 04524 // The PageFileName portion of the UserBuffer must be saved locally 04525 // to protect against a malicious thread changing the contents. This 04526 // is because we will reference the contents ourselves when the actual 04527 // string is copied out carefully below. 04528 // 04529 04530 UserBufferPageFileName.Length = MmPagingFile[i]->PageFileName.Length; 04531 UserBufferPageFileName.MaximumLength = MmPagingFile[i]->PageFileName.Length + sizeof(WCHAR); 04532 UserBufferPageFileName.Buffer = (PWCHAR)(PageFileInfo + 1); 04533 04534 PageFileInfo->PageFileName = UserBufferPageFileName; 04535 04536 TotalSize += ROUND_UP (UserBufferPageFileName.MaximumLength, 04537 sizeof(ULONG)); 04538 NextEntryOffset += ROUND_UP (UserBufferPageFileName.MaximumLength, 04539 sizeof(ULONG)); 04540 04541 if (TotalSize > SystemInformationLength) { 04542 return STATUS_INFO_LENGTH_MISMATCH; 04543 } 04544 04545 // 04546 // Carefully reference the user buffer here. 04547 // 04548 04549 RtlMoveMemory(UserBufferPageFileName.Buffer, 04550 MmPagingFile[i]->PageFileName.Buffer, 04551 MmPagingFile[i]->PageFileName.Length); 04552 UserBufferPageFileName.Buffer[ 04553 MmPagingFile[i]->PageFileName.Length/sizeof(WCHAR)] = UNICODE_NULL; 04554 PageFileInfo->NextEntryOffset = NextEntryOffset; 04555 } 04556 PageFileInfo->NextEntryOffset = 0; 04557 *Length = TotalSize; 04558 return STATUS_SUCCESS; 04559 }

NTSTATUS NtCreatePagingFile IN PUNICODE_STRING  PageFileName,
IN PLARGE_INTEGER  MinimumSize,
IN PLARGE_INTEGER  MaximumSize,
IN ULONG Priority  OPTIONAL
 

Definition at line 297 of file modwrite.c.

References ASSERT, _MMPAGING_FILE::Bitmap, CreateFileTypeNone, DbgPrint, _DEVICE_OBJECT::DeviceType, _MMPAGING_FILE::Entry, _MMPAGE_FILE_EXPANSION::Event, ExAllocatePoolWithTag, ExFreePool(), ExSystemExceptionFilter(), FALSE, _MMPAGING_FILE::File, File, _MMPAGING_FILE::FreeSpace, IO_NO_PARAMETER_CHECKING, IO_OPEN_PAGING_FILE, IoCreateFile(), IoFileObjectType, IoGetRelatedDeviceObject(), IoPageFileCreated(), IoQueryVolumeInformation(), KeInitializeEvent, KernelMode, KPROCESSOR_MODE, L, MAX_PAGE_FILES, _MMPAGING_FILE::MaximumSize, MiChargeCommitment(), MiCheckForCrashDump(), MiCheckPageFileMapping(), MiCheckPageFilePath(), MiCreateBitMap, MiExtendPagingFileMaximum(), MiInsertPageFileInList(), MiIssuePageExtendRequest(), MINIMUM_PAGE_FILE_SIZE, _MMPAGING_FILE::MinimumSize, MiReleaseModifiedWriter(), MiRemoveBitMap, MiReturnCommitment(), MMMOD_WRITER_MDL_ENTRY, MmModifiedWriteClusterSize, MmNumberOfPagingFiles, MmPageFileCreationLock, MMPAGING_FILE, MmPagingFile, MmPagingFileHeader, MmSystemPageFileLocated, MmTotalCommitLimit, MmTotalCommitLimitMaximum, MmTotalCommittedPages, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObOpenObjectByPointer(), ObReferenceObjectByHandle(), PAGE_SHIFT, PAGED_CODE, PagedPool, _MMPAGING_FILE::PageFileName, _MMPAGING_FILE::PageFileNumber, _MMPAGE_FILE_EXPANSION::PageFileNumber, _MMMOD_WRITER_MDL_ENTRY::PagingFile, _MMMOD_WRITER_MDL_ENTRY::PagingListHead, ProbeForRead, PsInitialSystemProcess, PsProcessType, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, ROUND_TO_PAGES, RtlClearBits(), RtlSetAllBits(), SeCreatePagefilePrivilege, _FILE_OBJECT::SectionObjectPointer, _MMPAGE_FILE_EXPANSION::Segment, SeSinglePrivilegeCheck(), Size, _MMPAGING_FILE::Size, Status, TRUE, and ZwSetInformationFile().

00306 : 00307 00308 This routine opens the specified file, attempts to write a page 00309 to the specified file, and creates the necessary structures to 00310 use the file as a paging file. 00311 00312 If this file is the first paging file, the modified page writer 00313 is started. 00314 00315 This system service requires the caller to have SeCreatePagefilePrivilege. 00316 00317 Arguments: 00318 00319 PageFileName - Supplies the fully qualified file name. 00320 00321 MinimumSize - Supplies the starting size of the paging file. 00322 This value is rounded up to the host page size. 00323 00324 MaximumSize - Supplies the maximum number of bytes to write to the file. 00325 This value is rounded up to the host page size. 00326 00327 Priority - Supplies the relative priority of this paging file. 00328 00329 Return Value: 00330 00331 tbs 00332 00333 --*/ 00334 00335 { 00336 PFILE_OBJECT File; 00337 NTSTATUS Status; 00338 OBJECT_ATTRIBUTES PagingFileAttributes; 00339 HANDLE FileHandle; 00340 IO_STATUS_BLOCK IoStatus; 00341 UNICODE_STRING CapturedName; 00342 PWSTR CapturedBuffer; 00343 LARGE_INTEGER CapturedMaximumSize; 00344 LARGE_INTEGER CapturedMinimumSize; 00345 LARGE_INTEGER SpecifiedSize; 00346 FILE_END_OF_FILE_INFORMATION EndOfFileInformation; 00347 KPROCESSOR_MODE PreviousMode; 00348 BOOLEAN Attached = FALSE; 00349 BOOLEAN HasPrivilege; 00350 HANDLE SystemProcess; 00351 FILE_FS_DEVICE_INFORMATION FileDeviceInfo; 00352 ULONG ReturnedLength; 00353 ULONG FinalStatus; 00354 ULONG PageFileNumber; 00355 ULONG NewMaxSizeInPages; 00356 ULONG NewMinSizeInPages; 00357 PMMPAGING_FILE FoundExisting; 00358 PRTL_BITMAP NewBitmap; 00359 PRTL_BITMAP OldBitmap; 00360 PDEVICE_OBJECT deviceObject; 00361 MMPAGE_FILE_EXPANSION PageExtend; 00362 00363 DBG_UNREFERENCED_PARAMETER (Priority); 00364 00365 PAGED_CODE(); 00366 00367 CapturedBuffer = NULL; 00368 00369 if (MmNumberOfPagingFiles == MAX_PAGE_FILES) { 00370 00371 // 00372 // The maximum number of paging files is already in use. 00373 // 00374 00375 Status = STATUS_TOO_MANY_PAGING_FILES; 00376 goto ErrorReturn0; 00377 } 00378 00379 PreviousMode = KeGetPreviousMode(); 00380 00381 try { 00382 00383 if (PreviousMode != KernelMode) { 00384 00385 // 00386 // Make sure the caller has the proper privilege to make 00387 // this call. 00388 // 00389 00390 HasPrivilege = SeSinglePrivilegeCheck (SeCreatePagefilePrivilege, 00391 PreviousMode 00392 ); 00393 00394 if (!HasPrivilege) { 00395 00396 Status = STATUS_PRIVILEGE_NOT_HELD; 00397 goto ErrorReturn0; 00398 } 00399 00400 // 00401 // Probe arguments. 00402 // 00403 00404 ProbeForRead( PageFileName, sizeof(*PageFileName), sizeof(UCHAR)); 00405 ProbeForRead( MaximumSize, sizeof(LARGE_INTEGER), 4); 00406 ProbeForRead( MinimumSize, sizeof(LARGE_INTEGER), 4); 00407 } 00408 00409 // 00410 // Capture arguments. 00411 // 00412 00413 CapturedMinimumSize = *MinimumSize; 00414 00415 #if defined (_WIN64) || defined (_X86PAE_) 00416 if (CapturedMinimumSize.QuadPart < MINIMUM_PAGE_FILE_SIZE) { 00417 Status = STATUS_INVALID_PARAMETER_2; 00418 goto ErrorReturn0; 00419 } 00420 00421 SpecifiedSize.QuadPart = (ROUND_TO_PAGES (CapturedMinimumSize.QuadPart)) >> PAGE_SHIFT; 00422 00423 if (SpecifiedSize.HighPart != 0) { 00424 Status = STATUS_INVALID_PARAMETER_2; 00425 goto ErrorReturn0; 00426 } 00427 #else 00428 if ((CapturedMinimumSize.HighPart != 0) || 00429 (CapturedMinimumSize.LowPart < MINIMUM_PAGE_FILE_SIZE)) { 00430 Status = STATUS_INVALID_PARAMETER_2; 00431 goto ErrorReturn0; 00432 } 00433 #endif 00434 00435 CapturedMaximumSize = *MaximumSize; 00436 00437 #if defined (_WIN64) || defined (_X86PAE_) 00438 SpecifiedSize.QuadPart = (ROUND_TO_PAGES (CapturedMaximumSize.QuadPart)) >> PAGE_SHIFT; 00439 00440 if (SpecifiedSize.HighPart != 0) { 00441 Status = STATUS_INVALID_PARAMETER_3; 00442 goto ErrorReturn0; 00443 } 00444 #else 00445 if (CapturedMaximumSize.HighPart != 0) { 00446 Status = STATUS_INVALID_PARAMETER_3; 00447 goto ErrorReturn0; 00448 } 00449 #endif 00450 00451 if (CapturedMinimumSize.QuadPart > CapturedMaximumSize.QuadPart) { 00452 Status = STATUS_INVALID_PARAMETER_3; 00453 goto ErrorReturn0; 00454 } 00455 00456 CapturedName = *PageFileName; 00457 CapturedName.MaximumLength = CapturedName.Length; 00458 00459 if ((CapturedName.Length == 0) || 00460 (CapturedName.Length > MAXIMUM_FILENAME_LENGTH )) { 00461 Status = STATUS_OBJECT_NAME_INVALID; 00462 goto ErrorReturn0; 00463 } 00464 00465 if (PreviousMode != KernelMode) { 00466 ProbeForRead (CapturedName.Buffer, 00467 CapturedName.Length, 00468 sizeof( UCHAR )); 00469 } 00470 00471 CapturedBuffer = ExAllocatePoolWithTag (PagedPool, 00472 (ULONG)CapturedName.Length, 00473 ' mM'); 00474 00475 if (CapturedBuffer == NULL) { 00476 Status = STATUS_INSUFFICIENT_RESOURCES; 00477 goto ErrorReturn0; 00478 } 00479 00480 // 00481 // Copy the string to the allocated buffer. 00482 // 00483 00484 RtlMoveMemory (CapturedBuffer, 00485 CapturedName.Buffer, 00486 CapturedName.Length); 00487 00488 // 00489 // Point the buffer to the string that was just copied. 00490 // 00491 00492 CapturedName.Buffer = CapturedBuffer; 00493 00494 } except (ExSystemExceptionFilter()) { 00495 00496 // 00497 // If an exception occurs during the probe or capture 00498 // of the initial values, then handle the exception and 00499 // return the exception code as the status value. 00500 // 00501 00502 if (CapturedBuffer != NULL) { 00503 ExFreePool (CapturedBuffer); 00504 } 00505 00506 Status = GetExceptionCode(); 00507 goto ErrorReturn0; 00508 } 00509 00510 // 00511 // Open a paging file and get the size. 00512 // 00513 00514 InitializeObjectAttributes( &PagingFileAttributes, 00515 &CapturedName, 00516 OBJ_CASE_INSENSITIVE, 00517 NULL, 00518 NULL ); 00519 00520 #if defined (_WIN64) || defined (_X86PAE_) 00521 EndOfFileInformation.EndOfFile.QuadPart = 00522 ROUND_TO_PAGES (CapturedMinimumSize.QuadPart); 00523 #else 00524 EndOfFileInformation.EndOfFile.HighPart = 0; 00525 #endif 00526 EndOfFileInformation.EndOfFile.LowPart = (ULONG) 00527 ROUND_TO_PAGES (CapturedMinimumSize.LowPart); 00528 00529 Status = IoCreateFile( &FileHandle, 00530 FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE, 00531 &PagingFileAttributes, 00532 &IoStatus, 00533 &CapturedMinimumSize, 00534 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, 00535 FILE_SHARE_WRITE, 00536 FILE_SUPERSEDE, 00537 FILE_NO_INTERMEDIATE_BUFFERING | FILE_NO_COMPRESSION, 00538 (PVOID) NULL, 00539 0L, 00540 CreateFileTypeNone, 00541 (PVOID) NULL, 00542 IO_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING ); 00543 00544 if (!NT_SUCCESS(Status)) { 00545 00546 // 00547 // Treat this as an extension of an existing pagefile maximum - 00548 // and try to open rather than create the paging file specified. 00549 // 00550 00551 Status = IoCreateFile( &FileHandle, 00552 FILE_WRITE_DATA | SYNCHRONIZE, 00553 &PagingFileAttributes, 00554 &IoStatus, 00555 &CapturedMinimumSize, 00556 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, 00557 FILE_SHARE_READ | FILE_SHARE_WRITE, 00558 FILE_OPEN, 00559 FILE_NO_INTERMEDIATE_BUFFERING | FILE_NO_COMPRESSION, 00560 (PVOID) NULL, 00561 0L, 00562 CreateFileTypeNone, 00563 (PVOID) NULL, 00564 IO_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING ); 00565 00566 if (!NT_SUCCESS(Status)) { 00567 00568 #if DBG 00569 if (Status != STATUS_DISK_FULL) { 00570 DbgPrint("MM MODWRITE: unable to open paging file %wZ - status = %X \n", &CapturedName, Status); 00571 } 00572 #endif 00573 00574 goto ErrorReturn1; 00575 } 00576 00577 Status = ObReferenceObjectByHandle ( FileHandle, 00578 FILE_READ_DATA | FILE_WRITE_DATA, 00579 IoFileObjectType, 00580 KernelMode, 00581 (PVOID *)&File, 00582 NULL ); 00583 00584 if (!NT_SUCCESS(Status)) { 00585 goto ErrorReturn2; 00586 } 00587 00588 FoundExisting = NULL; 00589 00590 ExAcquireFastMutex (&MmPageFileCreationLock); 00591 00592 for (PageFileNumber = 0; PageFileNumber < MmNumberOfPagingFiles; PageFileNumber += 1) { 00593 if (MmPagingFile[PageFileNumber]->File->SectionObjectPointer == File->SectionObjectPointer) { 00594 FoundExisting = MmPagingFile[PageFileNumber]; 00595 break; 00596 } 00597 } 00598 00599 if (FoundExisting == NULL) { 00600 Status = STATUS_NOT_FOUND; 00601 goto ErrorReturn4; 00602 } 00603 00604 // 00605 // Check for increases in the minimum or the maximum paging file sizes. 00606 // Decreasing either paging file size on the fly is not allowed. 00607 // 00608 00609 NewMaxSizeInPages = (ULONG)(CapturedMaximumSize.QuadPart >> PAGE_SHIFT); 00610 NewMinSizeInPages = (ULONG)(CapturedMinimumSize.QuadPart >> PAGE_SHIFT); 00611 00612 if (FoundExisting->MinimumSize > NewMinSizeInPages) { 00613 Status = STATUS_INVALID_PARAMETER_2; 00614 goto ErrorReturn4; 00615 } 00616 00617 if (FoundExisting->MaximumSize > NewMaxSizeInPages) { 00618 Status = STATUS_INVALID_PARAMETER_3; 00619 goto ErrorReturn4; 00620 } 00621 00622 if (NewMaxSizeInPages > FoundExisting->MaximumSize) { 00623 00624 // 00625 // Make sure that the pagefile increase doesn't cause the commit 00626 // limit (in pages) to wrap. Currently this can only happen on 00627 // PAE systems where 16 pagefiles of 16TB (==256TB) is greater 00628 // than the 32-bit commit variable (max is 16TB). 00629 // 00630 00631 if (MmTotalCommitLimitMaximum + (NewMaxSizeInPages - FoundExisting->MaximumSize) <= MmTotalCommitLimitMaximum) { 00632 Status = STATUS_INVALID_PARAMETER_3; 00633 goto ErrorReturn4; 00634 } 00635 00636 // 00637 // Handle the increase to the maximum paging file size. 00638 // 00639 00640 MiCreateBitMap (&NewBitmap, NewMaxSizeInPages, NonPagedPool); 00641 00642 if (NewBitmap == NULL) { 00643 Status = STATUS_INSUFFICIENT_RESOURCES; 00644 goto ErrorReturn4; 00645 } 00646 00647 OldBitmap = FoundExisting->Bitmap; 00648 00649 MiExtendPagingFileMaximum (PageFileNumber, NewBitmap); 00650 00651 MiRemoveBitMap (&OldBitmap); 00652 00653 // 00654 // We may be low on commitment and/or may have put a temporary 00655 // stopgate on things. Clear up the logjam now by forcing an 00656 // extension and immediately returning it. 00657 // 00658 00659 if (MmTotalCommittedPages + 100 > MmTotalCommitLimit) { 00660 if (MiChargeCommitment (200, NULL) == TRUE) { 00661 MiReturnCommitment (200); 00662 } 00663 } 00664 } 00665 00666 if (NewMinSizeInPages > FoundExisting->MinimumSize) { 00667 00668 // 00669 // Handle the increase to the minimum paging file size. 00670 // 00671 00672 if (NewMinSizeInPages > FoundExisting->Size) { 00673 00674 // 00675 // Queue a message to the segment dereferencing / pagefile 00676 // extending thread to see if the page file can be extended. 00677 // 00678 00679 PageExtend.RequestedExpansionSize = NewMinSizeInPages - FoundExisting->Size; 00680 PageExtend.Segment = NULL; 00681 PageExtend.PageFileNumber = PageFileNumber; 00682 KeInitializeEvent (&PageExtend.Event, NotificationEvent, FALSE); 00683 00684 MiIssuePageExtendRequest (&PageExtend); 00685 } 00686 00687 // 00688 // The current size is now greater than the new desired minimum. 00689 // Ensure subsequent contractions obey this new minimum. 00690 // 00691 00692 if (FoundExisting->Size >= NewMinSizeInPages) { 00693 ASSERT (FoundExisting->Size >= FoundExisting->MinimumSize); 00694 ASSERT (NewMinSizeInPages >= FoundExisting->MinimumSize); 00695 FoundExisting->MinimumSize = NewMinSizeInPages; 00696 } 00697 else { 00698 00699 // 00700 // The pagefile could not be expanded to handle the new minimum. 00701 // No easy way to undo any maximum raising that may have been 00702 // done as the space may have already been used, so just set 00703 // Status so our caller knows it didn't all go perfectly. 00704 // 00705 00706 Status = STATUS_INSUFFICIENT_RESOURCES; 00707 } 00708 } 00709 00710 goto ErrorReturn4; 00711 } 00712 00713 if (!NT_SUCCESS(IoStatus.Status)) { 00714 KdPrint(("MM MODWRITE: unable to open paging file %wZ - iosb %lx\n", &CapturedName, IoStatus.Status)); 00715 Status = IoStatus.Status; 00716 goto ErrorReturn1; 00717 } 00718 00719 // 00720 // Make sure that the pagefile increase doesn't cause the commit 00721 // limit (in pages) to wrap. Currently this can only happen on 00722 // PAE systems where 16 pagefiles of 16TB (==256TB) is greater 00723 // than the 32-bit commit variable (max is 16TB). 00724 // 00725 00726 if (MmTotalCommitLimitMaximum + (CapturedMaximumSize.QuadPart >> PAGE_SHIFT) 00727 <= MmTotalCommitLimitMaximum) { 00728 Status = STATUS_INVALID_PARAMETER_3; 00729 goto ErrorReturn2; 00730 } 00731 00732 Status = ZwSetInformationFile (FileHandle, 00733 &IoStatus, 00734 &EndOfFileInformation, 00735 sizeof(EndOfFileInformation), 00736 FileEndOfFileInformation); 00737 00738 if (!NT_SUCCESS(Status)) { 00739 KdPrint(("MM MODWRITE: unable to set length of paging file %wZ status = %X \n", 00740 &CapturedName, Status)); 00741 goto ErrorReturn2; 00742 } 00743 00744 if (!NT_SUCCESS(IoStatus.Status)) { 00745 KdPrint(("MM MODWRITE: unable to set length of paging file %wZ - iosb %lx\n", 00746 &CapturedName, IoStatus.Status)); 00747 Status = IoStatus.Status; 00748 goto ErrorReturn2; 00749 } 00750 00751 Status = ObReferenceObjectByHandle ( FileHandle, 00752 FILE_READ_DATA | FILE_WRITE_DATA, 00753 IoFileObjectType, 00754 KernelMode, 00755 (PVOID *)&File, 00756 NULL ); 00757 00758 if (!NT_SUCCESS(Status)) { 00759 KdPrint(("MM MODWRITE: Unable to reference paging file - %wZ\n", 00760 &CapturedName)); 00761 goto ErrorReturn2; 00762 } 00763 00764 // 00765 // Get the address of the target device object and ensure 00766 // the specified file is of a suitable type. 00767 // 00768 00769 deviceObject = IoGetRelatedDeviceObject (File); 00770 00771 if ((deviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM) && 00772 (deviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM) && 00773 (deviceObject->DeviceType != FILE_DEVICE_DFS_VOLUME) && 00774 (deviceObject->DeviceType != FILE_DEVICE_DFS_FILE_SYSTEM)) { 00775 KdPrint(("MM MODWRITE: Invalid paging file type - %x\n", 00776 deviceObject->DeviceType)); 00777 Status = STATUS_UNRECOGNIZED_VOLUME; 00778 goto ErrorReturn3; 00779 } 00780 00781 // 00782 // Make sure the specified file is not currently being used 00783 // as a mapped data file. 00784 // 00785 00786 Status = MiCheckPageFileMapping (File); 00787 if (!NT_SUCCESS(Status)) { 00788 goto ErrorReturn3; 00789 } 00790 00791 // 00792 // Make sure the volume is not a floppy disk. 00793 // 00794 00795 Status = IoQueryVolumeInformation ( File, 00796 FileFsDeviceInformation, 00797 sizeof(FILE_FS_DEVICE_INFORMATION), 00798 &FileDeviceInfo, 00799 &ReturnedLength 00800 ); 00801 00802 if (FILE_FLOPPY_DISKETTE & FileDeviceInfo.Characteristics) { 00803 Status = STATUS_FLOPPY_VOLUME; 00804 goto ErrorReturn3; 00805 } 00806 00807 // 00808 // Check with all of the drivers along the path to the file to ensure 00809 // that they are willing to follow the rules required of them and to 00810 // give them a chance to lock down code and data that needs to be locked. 00811 // If any of the drivers along the path refuses to participate, fail the 00812 // pagefile creation. 00813 // 00814 // BUGBUG: Failing the pagefile creation is commented out until the 00815 // storage drivers have been modified to correctly handle this request. 00816 // 00817 00818 Status = MiCheckPageFilePath (File); 00819 if (!NT_SUCCESS(Status)) { 00820 KdPrint(( "MiCheckPageFilePath(%wZ) FAILED: %x\n", &CapturedName, Status )); 00821 //goto ErrorReturn3; 00822 } 00823 00824 // 00825 // Acquire the global page file creation mutex. 00826 // 00827 00828 ExAcquireFastMutex (&MmPageFileCreationLock); 00829 00830 MmPagingFile[MmNumberOfPagingFiles] = ExAllocatePoolWithTag (NonPagedPool, 00831 sizeof(MMPAGING_FILE), 00832 ' mM'); 00833 if (MmPagingFile[MmNumberOfPagingFiles] == NULL) { 00834 00835 // 00836 // Allocate pool failed. 00837 // 00838 00839 Status = STATUS_INSUFFICIENT_RESOURCES; 00840 goto ErrorReturn4; 00841 } 00842 00843 RtlZeroMemory (MmPagingFile[MmNumberOfPagingFiles], sizeof(MMPAGING_FILE)); 00844 MmPagingFile[MmNumberOfPagingFiles]->File = File; 00845 MmPagingFile[MmNumberOfPagingFiles]->Size = (ULONG)( 00846 CapturedMinimumSize.QuadPart 00847 >> PAGE_SHIFT); 00848 00849 MmPagingFile[MmNumberOfPagingFiles]->MinimumSize = 00850 MmPagingFile[MmNumberOfPagingFiles]->Size; 00851 MmPagingFile[MmNumberOfPagingFiles]->FreeSpace = 00852 MmPagingFile[MmNumberOfPagingFiles]->Size - 1; 00853 00854 MmPagingFile[MmNumberOfPagingFiles]->MaximumSize = (PFN_NUMBER)( 00855 CapturedMaximumSize.QuadPart >> 00856 PAGE_SHIFT); 00857 00858 MmPagingFile[MmNumberOfPagingFiles]->PageFileNumber = MmNumberOfPagingFiles; 00859 00860 // 00861 // Adjust the commit page limit to reflect the new page file space. 00862 // 00863 00864 MmPagingFile[MmNumberOfPagingFiles]->Entry[0] = ExAllocatePoolWithTag (NonPagedPool, 00865 sizeof(MMMOD_WRITER_MDL_ENTRY) + 00866 MmModifiedWriteClusterSize * 00867 sizeof(PFN_NUMBER), 00868 ' mM'); 00869 00870 if (MmPagingFile[MmNumberOfPagingFiles]->Entry[0] == NULL) { 00871 00872 // 00873 // Allocate pool failed. 00874 // 00875 00876 Status = STATUS_INSUFFICIENT_RESOURCES; 00877 goto ErrorReturn5; 00878 } 00879 00880 RtlZeroMemory (MmPagingFile[MmNumberOfPagingFiles]->Entry[0], 00881 sizeof(MMMOD_WRITER_MDL_ENTRY)); 00882 00883 MmPagingFile[MmNumberOfPagingFiles]->Entry[0]->PagingListHead = 00884 &MmPagingFileHeader; 00885 MmPagingFile[MmNumberOfPagingFiles]->Entry[0]->PagingFile = 00886 MmPagingFile[MmNumberOfPagingFiles]; 00887 00888 MmPagingFile[MmNumberOfPagingFiles]->Entry[1] = ExAllocatePoolWithTag (NonPagedPool, 00889 sizeof(MMMOD_WRITER_MDL_ENTRY) + 00890 MmModifiedWriteClusterSize * 00891 sizeof(PFN_NUMBER), 00892 ' mM'); 00893 00894 if (MmPagingFile[MmNumberOfPagingFiles]->Entry[1] == NULL) { 00895 00896 // 00897 // Allocate pool failed. 00898 // 00899 00900 Status = STATUS_INSUFFICIENT_RESOURCES; 00901 goto ErrorReturn6; 00902 } 00903 00904 RtlZeroMemory (MmPagingFile[MmNumberOfPagingFiles]->Entry[1], 00905 sizeof(MMMOD_WRITER_MDL_ENTRY)); 00906 00907 MmPagingFile[MmNumberOfPagingFiles]->Entry[1]->PagingListHead = 00908 &MmPagingFileHeader; 00909 MmPagingFile[MmNumberOfPagingFiles]->Entry[1]->PagingFile = 00910 MmPagingFile[MmNumberOfPagingFiles]; 00911 00912 MmPagingFile[MmNumberOfPagingFiles]->PageFileName = CapturedName; 00913 00914 MiCreateBitMap (&MmPagingFile[MmNumberOfPagingFiles]->Bitmap, 00915 MmPagingFile[MmNumberOfPagingFiles]->MaximumSize, 00916 NonPagedPool); 00917 00918 if (MmPagingFile[MmNumberOfPagingFiles]->Bitmap == NULL) { 00919 00920 // 00921 // Allocate pool failed. 00922 // 00923 00924 Status = STATUS_INSUFFICIENT_RESOURCES; 00925 goto ErrorReturn7; 00926 } 00927 00928 RtlSetAllBits (MmPagingFile[MmNumberOfPagingFiles]->Bitmap); 00929 00930 // 00931 // Set the first bit as 0 is an invalid page location, clear the 00932 // following bits. 00933 // 00934 00935 RtlClearBits (MmPagingFile[MmNumberOfPagingFiles]->Bitmap, 00936 1, 00937 (ULONG)(MmPagingFile[MmNumberOfPagingFiles]->Size - 1)); 00938 00939 PageFileNumber = MmNumberOfPagingFiles; 00940 MiInsertPageFileInList (); 00941 00942 FinalStatus = MiCheckForCrashDump (File, PageFileNumber); 00943 00944 if (PageFileNumber == 0) { 00945 00946 // 00947 // The first paging file has been created and reservation of any 00948 // crashdump pages has completed, signal the modified 00949 // page writer. 00950 // 00951 00952 MiReleaseModifiedWriter (); 00953 } 00954 00955 ExReleaseFastMutex (&MmPageFileCreationLock); 00956 00957 // 00958 // Note that the file handle is not closed to prevent the 00959 // paging file from being deleted or opened again. (Actually, 00960 // the file handle is duped to the system process so process 00961 // termination will not close the handle). 00962 // 00963 00964 Status = ObOpenObjectByPointer( 00965 PsInitialSystemProcess, 00966 0, 00967 NULL, 00968 0, 00969 PsProcessType, 00970 KernelMode, 00971 &SystemProcess 00972 ); 00973 00974 if ( !NT_SUCCESS(Status)) { 00975 ZwClose (FileHandle); 00976 return FinalStatus; 00977 } 00978 00979 Status = ZwDuplicateObject( 00980 NtCurrentProcess(), 00981 FileHandle, 00982 SystemProcess, 00983 NULL, 00984 0, 00985 0, 00986 DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS 00987 ); 00988 00989 ASSERT(NT_SUCCESS(Status)); 00990 00991 if (!MmSystemPageFileLocated) { 00992 MmSystemPageFileLocated = IoPageFileCreated(FileHandle); 00993 } 00994 00995 ZwClose (SystemProcess); 00996 ZwClose (FileHandle); 00997 00998 return FinalStatus; 00999 01000 // 01001 // Error returns: 01002 // 01003 01004 ErrorReturn7: 01005 ExFreePool (MmPagingFile[MmNumberOfPagingFiles]->Entry[0]); 01006 01007 ErrorReturn6: 01008 ExFreePool (MmPagingFile[MmNumberOfPagingFiles]->Entry[1]); 01009 01010 ErrorReturn5: 01011 ExFreePool (MmPagingFile[MmNumberOfPagingFiles]); 01012 01013 ErrorReturn4: 01014 ExReleaseFastMutex (&MmPageFileCreationLock); 01015 01016 ErrorReturn3: 01017 ObDereferenceObject (File); 01018 01019 ErrorReturn2: 01020 ZwClose (FileHandle); 01021 01022 ErrorReturn1: 01023 ExFreePool (CapturedBuffer); 01024 01025 ErrorReturn0: 01026 return Status; 01027 }


Variable Documentation

POBJECT_TYPE IoFileObjectType
 

Definition at line 85 of file modwrite.c.

LOGICAL MiFirstPageFileCreatedAndReady = FALSE
 

Definition at line 43 of file modwrite.c.

Referenced by MiModifiedPageWriterWorker(), and MiReleaseModifiedWriter().

SIZE_T MiPageFileFullCharge
 

Definition at line 104 of file modwrite.c.

Referenced by MiPageFileFull().

PSECTION MmCrashDumpSection
 

Definition at line 83 of file modwrite.c.

Referenced by MiCheckForCrashDump(), MiCrashDumpWorker(), MmGetCrashDumpInformation(), and MmGetCrashDumpStateInformation().

KEVENT MmMappedFileIoComplete
 

Definition at line 92 of file modwrite.c.

Referenced by MiCleanSection(), MiWriteComplete(), MmInitSystem(), and MmPurgeSection().

KEVENT MmMappedPageWriterEvent
 

Definition at line 90 of file modwrite.c.

Referenced by MiGatherMappedPages(), MiMappedPageWriter(), and MiModifiedPageWriter().

LIST_ENTRY MmMappedPageWriterList
 

Definition at line 88 of file modwrite.c.

Referenced by MiCancelWriteOfMappedPfn(), MiGatherMappedPages(), MiMappedPageWriter(), and MiModifiedPageWriter().

ULONG MmModNoWriteInsert
 

Definition at line 108 of file modwrite.c.

Referenced by MiGatherMappedPages(), MiModifiedPageWriterWorker(), and MiObtainFreePages().

PFN_NUMBER MmMoreThanEnoughFreePages
 

Definition at line 149 of file modwrite.c.

SIZE_T MmOverCommit2
 

Definition at line 96 of file modwrite.c.

Referenced by MiInsertPageFileInList().

ULONG MmPageFileFullExtendCount
 

Definition at line 100 of file modwrite.c.

Referenced by MiPageFileFull().

SIZE_T MmPageFileFullExtendPages
 

Definition at line 98 of file modwrite.c.

Referenced by MiCauseOverCommitPopup(), MiChargeCommitment(), MiExtendPagingFiles(), MiPageFileFull(), and MiReturnCommitment().

LOGICAL MmPageFileFullPopupShown = FALSE
 

Definition at line 106 of file modwrite.c.

Referenced by MiPageFileFull().

BOOLEAN MmSystemPageFileLocated
 

Definition at line 110 of file modwrite.c.

Referenced by NtCreatePagingFile().

ULONG MmSystemShutdown
 

Definition at line 94 of file modwrite.c.

Referenced by MiModifiedPageWriter(), MiModifiedPageWriterWorker(), and MmShutdownSystem().

ULONG MmWriteAllModifiedPages
 

Definition at line 42 of file modwrite.c.

Referenced by MiFlushAllPages(), and MiModifiedPageWriterWorker().

HANDLE PspInitialSystemProcessHandle
 

Definition at line 86 of file modwrite.c.

Referenced by PsCreateSystemProcess(), PspCreateProcess(), and PspInitPhase0().


Generated on Sat May 15 19:44:48 2004 for test by doxygen 1.3.7