mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 20:03:12 +00:00
Better page file creation that allows for system managed setting. A lot of thanks to Thomas on this patch.
svn path=/trunk/; revision=20334
This commit is contained in:
parent
60f9e8b3c5
commit
5caea08853
1 changed files with 177 additions and 36 deletions
|
@ -28,66 +28,207 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
#define GIGABYTE (1024 * 1024 * 1024) /* One Gigabyte */
|
||||||
|
|
||||||
static NTSTATUS STDCALL
|
static NTSTATUS STDCALL
|
||||||
SmpPagingFilesQueryRoutine(PWSTR ValueName,
|
SmpPagingFilesQueryRoutine(PWSTR ValueName,
|
||||||
ULONG ValueType,
|
ULONG ValueType,
|
||||||
PVOID ValueData,
|
PVOID ValueData,
|
||||||
ULONG ValueLength,
|
ULONG ValueLength,
|
||||||
PVOID Context,
|
PVOID Context,
|
||||||
PVOID EntryContext)
|
PVOID EntryContext)
|
||||||
{
|
{
|
||||||
UNICODE_STRING FileName;
|
UNICODE_STRING FileName;
|
||||||
LARGE_INTEGER InitialSize;
|
LARGE_INTEGER InitialSize = {{0, 0}};
|
||||||
LARGE_INTEGER MaximumSize;
|
LARGE_INTEGER MaximumSize = {{0, 0}};
|
||||||
NTSTATUS Status;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
LPWSTR p;
|
PWSTR p, ValueString = (PWSTR)ValueData;
|
||||||
|
WCHAR RootDriveLetter[5] = {0};
|
||||||
|
|
||||||
DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength);
|
if (ValueLength > 3 * sizeof(WCHAR) &&
|
||||||
DPRINT("ValueData '%S'\n", (PWSTR)ValueData);
|
(ValueLength % sizeof(WCHAR) != 0 ||
|
||||||
|
ValueString[(ValueLength / sizeof(WCHAR)) - 1] != L'\0'))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
if (ValueType != REG_SZ)
|
if (ValueType != REG_SZ)
|
||||||
{
|
{
|
||||||
return(STATUS_SUCCESS);
|
return STATUS_INVALID_PARAMETER_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Format: "<path>[ <initial_size>[ <maximum_size>]]"
|
* Format: "<path>[ <initial_size>[ <maximum_size>]]"
|
||||||
*/
|
*/
|
||||||
if ((p = wcschr(ValueData, ' ')) != NULL)
|
if ((p = wcschr(ValueString, L' ')) != NULL)
|
||||||
{
|
{
|
||||||
*p = L'\0';
|
*p = L'\0';
|
||||||
InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096;
|
InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096;
|
||||||
if (*p == ' ')
|
if (*p == ' ')
|
||||||
{
|
{
|
||||||
MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096;
|
MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
MaximumSize = InitialSize;
|
{
|
||||||
}
|
MaximumSize = InitialSize;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
InitialSize.QuadPart = 50 * 4096;
|
|
||||||
MaximumSize.QuadPart = 80 * 4096;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData,
|
if (!RtlDosPathNameToNtPathName_U (ValueString,
|
||||||
&FileName,
|
&FileName,
|
||||||
NULL,
|
NULL,
|
||||||
NULL))
|
NULL))
|
||||||
{
|
{
|
||||||
return (STATUS_SUCCESS);
|
return STATUS_OBJECT_PATH_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("SMSS: Created paging file %wZ with size %dKB\n",
|
/* If there is only a file name or if initial and max are both 0
|
||||||
&FileName, InitialSize.QuadPart / 1024);
|
* the system will pick the sizes. Then it makes intial the size of phyical memory
|
||||||
|
* and makes max the size of 1.5 * initial. If there isnt enough free space then it will
|
||||||
|
* fall back to intial 20% of free space and max 25%. There is a max of 1 gig before
|
||||||
|
* it doesnt make it bigger. */
|
||||||
|
if ((InitialSize.QuadPart == 0 && MaximumSize.QuadPart == 0) || p == NULL)
|
||||||
|
{
|
||||||
|
FILE_FS_SIZE_INFORMATION FileFsSize;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
HANDLE hFile;
|
||||||
|
SYSTEM_BASIC_INFORMATION SysBasicInfo;
|
||||||
|
UNICODE_STRING NtPathU;
|
||||||
|
LARGE_INTEGER FreeBytes = {{0, 0}};
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
|
||||||
|
DPRINT("System managed pagefile...\n");
|
||||||
|
/* Make sure the path that is given for the file actually has the drive in it.
|
||||||
|
At this point if there is not file name, no sizes will be set therefore no page
|
||||||
|
file will be created */
|
||||||
|
if (wcslen(ValueString) <= 3 ||
|
||||||
|
ValueString[1] != L':' ||
|
||||||
|
ValueString[2] != L'\\')
|
||||||
|
{
|
||||||
|
DPRINT1("Invalid path for pagefile.\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtQuerySystemInformation(SystemBasicInformation,
|
||||||
|
&SysBasicInfo,
|
||||||
|
sizeof(SysBasicInfo),
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Could not query for physical memory size.\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
DPRINT("PageSize: %d, PhysicalPages: %d, TotalMem: %d\n", SysBasicInfo.PageSize, SysBasicInfo.NumberOfPhysicalPages, (SysBasicInfo.NumberOfPhysicalPages * SysBasicInfo.PageSize) / 1024);
|
||||||
|
|
||||||
|
InitialSize.QuadPart = SysBasicInfo.NumberOfPhysicalPages *
|
||||||
|
SysBasicInfo.PageSize;
|
||||||
|
MaximumSize.QuadPart = InitialSize.QuadPart * 2;
|
||||||
|
|
||||||
|
DPRINT("InitialSize: %I64d PhysicalPages: %lu PageSize: %lu\n",InitialSize.QuadPart,SysBasicInfo.NumberOfPhysicalPages,SysBasicInfo.PageSize);
|
||||||
|
|
||||||
|
/* copy the drive letter, the colon and the slash,
|
||||||
|
tack a null on the end */
|
||||||
|
RootDriveLetter[0] = ValueString[0];
|
||||||
|
RootDriveLetter[1] = L':';
|
||||||
|
RootDriveLetter[2] = L'\\';
|
||||||
|
RootDriveLetter[3] = L'\0';
|
||||||
|
DPRINT("Root drive X:\\...\"%S\"\n",RootDriveLetter);
|
||||||
|
|
||||||
|
if (!RtlDosPathNameToNtPathName_U(RootDriveLetter,
|
||||||
|
&NtPathU,
|
||||||
|
NULL,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
DPRINT1("Invalid path to root of drive\n");
|
||||||
|
Status = STATUS_OBJECT_PATH_INVALID;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&NtPathU,
|
||||||
|
OBJ_CASE_INSENSITIVE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Get a handle to the root to find the free space on the drive */
|
||||||
|
Status = NtCreateFile(&hFile,
|
||||||
|
0,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
FILE_OPEN,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
|
||||||
|
RtlFreeUnicodeString(&NtPathU);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Could not open a handle to the volume.\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtQueryVolumeInformationFile(hFile,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&FileFsSize,
|
||||||
|
sizeof(FILE_FS_SIZE_INFORMATION),
|
||||||
|
FileFsSizeInformation);
|
||||||
|
|
||||||
|
NtClose(hFile);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Querying the volume free space failed!\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeBytes.QuadPart = FileFsSize.BytesPerSector *
|
||||||
|
FileFsSize.SectorsPerAllocationUnit *
|
||||||
|
FileFsSize.AvailableAllocationUnits.QuadPart;
|
||||||
|
|
||||||
|
DPRINT("Free bytes: %I64d Inital Size based on memory: %I64d \n",FreeBytes.QuadPart,InitialSize.QuadPart);
|
||||||
|
|
||||||
|
|
||||||
|
if (InitialSize.QuadPart > (FreeBytes.QuadPart / 4) || InitialSize.QuadPart == 0)
|
||||||
|
{
|
||||||
|
DPRINT("Inital Size took more then 25%% of free space\n");
|
||||||
|
/* Set by percentage of free space
|
||||||
|
* intial is 20%, and max is 25% */
|
||||||
|
InitialSize.QuadPart = FreeBytes.QuadPart / 5;
|
||||||
|
MaximumSize.QuadPart = FreeBytes.QuadPart / 4;
|
||||||
|
/* The page file is more then a gig, size it down */
|
||||||
|
if (InitialSize.QuadPart > GIGABYTE)
|
||||||
|
{
|
||||||
|
InitialSize.QuadPart = GIGABYTE;
|
||||||
|
MaximumSize.QuadPart = GIGABYTE * 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure that max is not smaller then initial */
|
||||||
|
if (InitialSize.QuadPart > MaximumSize.QuadPart)
|
||||||
|
{
|
||||||
|
DPRINT("Max page file size was bigger then inital.\n");
|
||||||
|
MaximumSize.QuadPart = InitialSize.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("SMSS: Created paging file %wZ with size %I64d KB\n",
|
||||||
|
&FileName, InitialSize.QuadPart / 1024);
|
||||||
|
|
||||||
Status = NtCreatePagingFile(&FileName,
|
Status = NtCreatePagingFile(&FileName,
|
||||||
&InitialSize,
|
&InitialSize,
|
||||||
&MaximumSize,
|
&MaximumSize,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
RtlFreeUnicodeString(&FileName);
|
RtlFreeUnicodeString(&FileName);
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,7 +238,7 @@ SmCreatePagingFiles(VOID)
|
||||||
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("SM: creating system paging files\n");
|
DbgPrint("SM: creating system paging files\n");
|
||||||
/*
|
/*
|
||||||
* Disable paging file on MiniNT/Live CD.
|
* Disable paging file on MiniNT/Live CD.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue