PMMPAGING_FILE MmPagingFile[MAX_PAGING_FILES];
/* Lock for examining the list of paging files */
-static KSPIN_LOCK PagingFileListLock;
+KGUARDED_MUTEX MmPageFileCreationLock;
/* Number of paging files */
ULONG MmNumberOfPagingFiles;
{
ULONG i;
- KeInitializeSpinLock(&PagingFileListLock);
+ KeInitializeGuardedMutex(&MmPageFileCreationLock);
MiFreeSwapPages = 0;
MiUsedSwapPages = 0;
{
ULONG i;
ULONG_PTR off;
- KIRQL oldIrql;
PMMPAGING_FILE PagingFile;
i = FILE_FROM_ENTRY(Entry);
off = OFFSET_FROM_ENTRY(Entry) - 1;
- KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
+ KeAcquireGuardedMutex(&MmPageFileCreationLock);
PagingFile = MmPagingFile[i];
if (PagingFile == NULL)
KeBugCheck(MEMORY_MANAGEMENT);
}
- RtlClearBit(PagingFile->AllocMap, off >> 5);
+ RtlClearBit(PagingFile->Bitmap, off >> 5);
- PagingFile->FreePages++;
- PagingFile->UsedPages--;
+ PagingFile->FreeSpace++;
+ PagingFile->CurrentUsage--;
MiFreeSwapPages++;
MiUsedSwapPages--;
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
}
SWAPENTRY
NTAPI
MmAllocSwapPage(VOID)
{
- KIRQL oldIrql;
ULONG i;
ULONG off;
SWAPENTRY entry;
- KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
+ KeAcquireGuardedMutex(&MmPageFileCreationLock);
if (MiFreeSwapPages == 0)
{
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
return(0);
}
for (i = 0; i < MAX_PAGING_FILES; i++)
{
if (MmPagingFile[i] != NULL &&
- MmPagingFile[i]->FreePages >= 1)
+ MmPagingFile[i]->FreeSpace >= 1)
{
- off = RtlFindClearBitsAndSet(MmPagingFile[i]->AllocMap, 1, 0);
+ off = RtlFindClearBitsAndSet(MmPagingFile[i]->Bitmap, 1, 0);
if (off == 0xFFFFFFFF)
{
KeBugCheck(MEMORY_MANAGEMENT);
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
return(STATUS_UNSUCCESSFUL);
}
MiUsedSwapPages++;
MiFreeSwapPages--;
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
entry = ENTRY_FROM_FILE_OFFSET(i, off + 1);
return(entry);
}
}
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
KeBugCheck(MEMORY_MANAGEMENT);
return(0);
}
NTSTATUS NTAPI
NtCreatePagingFile(IN PUNICODE_STRING FileName,
- IN PLARGE_INTEGER InitialSize,
+ IN PLARGE_INTEGER MinimumSize,
IN PLARGE_INTEGER MaximumSize,
IN ULONG Reserved)
{
IO_STATUS_BLOCK IoStatus;
PFILE_OBJECT FileObject;
PMMPAGING_FILE PagingFile;
- KIRQL oldIrql;
ULONG AllocMapSize;
ULONG Count;
KPROCESSOR_MODE PreviousMode;
UNICODE_STRING PageFileName;
- LARGE_INTEGER SafeInitialSize, SafeMaximumSize, AllocationSize;
+ LARGE_INTEGER SafeMinimumSize, SafeMaximumSize, AllocationSize;
FILE_FS_DEVICE_INFORMATION FsDeviceInfo;
SECURITY_DESCRIPTOR SecurityDescriptor;
PACL Dacl;
PWSTR Buffer;
- DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
- FileName, InitialSize->QuadPart);
+ DPRINT("NtCreatePagingFile(FileName %wZ, MinimumSize %I64d)\n",
+ FileName, MinimumSize->QuadPart);
+
+ PAGED_CODE();
if (MmNumberOfPagingFiles >= MAX_PAGING_FILES)
{
_SEH2_TRY
{
- SafeInitialSize = ProbeForReadLargeInteger(InitialSize);
+ SafeMinimumSize = ProbeForReadLargeInteger(MinimumSize);
SafeMaximumSize = ProbeForReadLargeInteger(MaximumSize);
PageFileName.Length = FileName->Length;
}
else
{
- SafeInitialSize = *InitialSize;
+ SafeMinimumSize = *MinimumSize;
SafeMaximumSize = *MaximumSize;
PageFileName.Length = FileName->Length;
/* Pagefiles can't be larger than 4GB and ofcourse the minimum should be
smaller than the maximum */
- if (0 != SafeInitialSize.u.HighPart)
+ if (0 != SafeMinimumSize.u.HighPart)
{
return STATUS_INVALID_PARAMETER_2;
}
{
return STATUS_INVALID_PARAMETER_3;
}
- if (SafeMaximumSize.u.LowPart < SafeInitialSize.u.LowPart)
+ if (SafeMaximumSize.u.LowPart < SafeMinimumSize.u.LowPart)
{
return STATUS_INVALID_PARAMETER_MIX;
}
* of the paging file is cluster 3042 but cluster 3043 is NOT part of the
* paging file but of another file. We can't write a complete page (4096
* bytes) to the physical location of cluster 3042 then. */
- AllocationSize.QuadPart = SafeInitialSize.QuadPart + PAGE_SIZE;
+ AllocationSize.QuadPart = SafeMinimumSize.QuadPart + PAGE_SIZE;
/* First, attempt to replace the page file, if existing */
Status = IoCreateFile(&FileHandle,
/* Find if it matches a previous page file */
PagingFile = NULL;
+
+ /* FIXME: should be calling unsafe instead,
+ * we should already be in a guarded region
+ */
+ KeAcquireGuardedMutex(&MmPageFileCreationLock);
if (MmNumberOfPagingFiles > 0)
{
i = 0;
/* If we didn't find the page file, fail */
if (PagingFile == NULL)
{
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
ExFreePoolWithTag(Dacl, 'lcaD');
return STATUS_NOT_FOUND;
}
+ /* Don't allow page file shrinking */
+ if (PagingFile->MinimumSize > (SafeMinimumSize.QuadPart >> PAGE_SHIFT))
+ {
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ ExFreePoolWithTag(Dacl, 'lcaD');
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return STATUS_INVALID_PARAMETER_2;
+ }
+
+ if ((SafeMaximumSize.QuadPart >> PAGE_SHIFT) < PagingFile->MaximumSize)
+ {
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
+ ObDereferenceObject(FileObject);
+ ZwClose(FileHandle);
+ ExFreePoolWithTag(Dacl, 'lcaD');
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return STATUS_INVALID_PARAMETER_3;
+ }
+
/* FIXME: implement parameters checking and page file extension */
UNIMPLEMENTED;
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
ObDereferenceObject(FileObject);
ZwClose(FileHandle);
ExFreePoolWithTag(Dacl, 'lcaD');
/* DACL is no longer needed, free it */
ExFreePoolWithTag(Dacl, 'lcaD');
- /* Set its end of file to initial size */
+ /* FIXME: To enable once page file managment is moved to ARM3 */
+#if 0
+ /* Check we won't overflow commit limit with the page file */
+ if (MmTotalCommitLimitMaximum + (SafeMaximumSize.QuadPart >> PAGE_SHIFT) <= MmTotalCommitLimitMaximum)
+ {
+ ZwClose(FileHandle);
+ ExFreePoolWithTag(Buffer, TAG_MM);
+ return STATUS_INVALID_PARAMETER_3;
+ }
+#endif
+
+ /* Set its end of file to minimal size */
Status = ZwSetInformationFile(FileHandle,
&IoStatus,
- &SafeInitialSize,
+ &SafeMinimumSize,
sizeof(LARGE_INTEGER),
FileEndOfFileInformation);
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatus.Status))
}
Status = ObReferenceObjectByHandle(FileHandle,
- FILE_ALL_ACCESS,
+ FILE_READ_DATA | FILE_WRITE_DATA,
IoFileObjectType,
KernelMode,
(PVOID*)&FileObject,
PagingFile->FileHandle = FileHandle;
PagingFile->FileObject = FileObject;
- PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart;
- PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart;
- PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE);
- PagingFile->UsedPages = 0;
+ PagingFile->MaximumSize = (SafeMaximumSize.QuadPart >> PAGE_SHIFT);
+ PagingFile->Size = (SafeMinimumSize.QuadPart >> PAGE_SHIFT);
+ PagingFile->MinimumSize = (SafeMinimumSize.QuadPart >> PAGE_SHIFT);
+ /* First page is never used: it's the header
+ * TODO: write it
+ */
+ PagingFile->FreeSpace = (ULONG)(SafeMinimumSize.QuadPart / PAGE_SIZE) - 1;
+ PagingFile->CurrentUsage = 0;
PagingFile->PageFileName = PageFileName;
+ ASSERT(PagingFile->Size == PagingFile->FreeSpace + PagingFile->CurrentUsage + 1);
- AllocMapSize = sizeof(RTL_BITMAP) + (((PagingFile->FreePages + 31) / 32) * sizeof(ULONG));
- PagingFile->AllocMap = ExAllocatePoolWithTag(NonPagedPool,
- AllocMapSize,
- TAG_MM);
- if (PagingFile->AllocMap == NULL)
+ AllocMapSize = sizeof(RTL_BITMAP) + (((PagingFile->MaximumSize + 31) / 32) * sizeof(ULONG));
+ PagingFile->Bitmap = ExAllocatePoolWithTag(NonPagedPool,
+ AllocMapSize,
+ TAG_MM);
+ if (PagingFile->Bitmap == NULL)
{
ExFreePoolWithTag(PagingFile, TAG_MM);
ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlInitializeBitMap(PagingFile->AllocMap,
- (PULONG)(PagingFile->AllocMap + 1),
- (ULONG)(PagingFile->FreePages));
- RtlClearAllBits(PagingFile->AllocMap);
+ RtlInitializeBitMap(PagingFile->Bitmap,
+ (PULONG)(PagingFile->Bitmap + 1),
+ (ULONG)(PagingFile->MaximumSize));
+ RtlClearAllBits(PagingFile->Bitmap);
- KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
+ /* FIXME: should be calling unsafe instead,
+ * we should already be in a guarded region
+ */
+ KeAcquireGuardedMutex(&MmPageFileCreationLock);
ASSERT(MmPagingFile[MmNumberOfPagingFiles] == NULL);
MmPagingFile[MmNumberOfPagingFiles] = PagingFile;
MmNumberOfPagingFiles++;
- MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
- KeReleaseSpinLock(&PagingFileListLock, oldIrql);
+ MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreeSpace;
+ KeReleaseGuardedMutex(&MmPageFileCreationLock);
MmSwapSpaceMessage = FALSE;