[SMSS2]: Implement all the processing required for being able to create emergency, system, and manual-sized page files, on both fixed drives any "any" drives. Missing the code to build volume descriptors and to actually ask the kernel to create the file (right now, just prints what should be done and sizes).

svn path=/trunk/; revision=55335
This commit is contained in:
Alex Ionescu 2012-01-30 21:28:48 +00:00
parent 2740865cc0
commit 51dbd93981

View file

@ -14,7 +14,11 @@
/* GLOBALS ********************************************************************/
#define STANDARD_DRIVE_LETTER_OFFSET 4
//
// Taken from ASSERTs
//
#define STANDARD_PAGING_FILE_NAME L"\\??\\?:\\pagefile.sys"
#define STANDARD_DRIVE_LETTER_OFFSET 4
#define SMP_PAGEFILE_CREATED 0x01
#define SMP_PAGEFILE_DEFAULT 0x02
@ -209,7 +213,308 @@ SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
NTSTATUS
NTAPI
SmpCreatePagingFiles(VOID)
SmpCreatePagingFileOnFixedDrive(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
IN PLARGE_INTEGER FuzzFactor,
IN PLARGE_INTEGER MinimumSize)
{
DPRINT1("Should create fixed pagefile of sizes: %I64d %I64d\n",
FuzzFactor->QuadPart, MinimumSize->QuadPart);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
SmpCreatePagingFileOnAnyDrive(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
IN PLARGE_INTEGER FuzzFactor,
IN PLARGE_INTEGER MinimumSize)
{
DPRINT1("Should create 'any' pagefile of sizes: %I64d %I64d\n",
FuzzFactor->QuadPart, MinimumSize->QuadPart);
return STATUS_SUCCESS;
}
VOID
NTAPI
SmpMakeDefaultPagingFileDescriptor(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
{
/* The default descriptor uses 128MB as a pagefile size */
Descriptor->Flags |= SMP_PAGEFILE_DEFAULT;
Descriptor->MinSize.QuadPart = 0x8000000;
Descriptor->MaxSize.QuadPart = 0x8000000;
}
VOID
NTAPI
SmpMakeSystemManagedPagingFileDescriptor(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
{
NTSTATUS Status;
LONGLONG MinimumSize, MaximumSize, Ram;
SYSTEM_BASIC_INFORMATION BasicInfo;
/* Query the page size of the system, and the amount of RAM */
Status = NtQuerySystemInformation(SystemBasicInformation,
&BasicInfo,
sizeof(BasicInfo),
NULL);
if (!NT_SUCCESS(Status))
{
/* If we failed, use defaults since we have no idea otherwise */
DPRINT1("SMSS:PFILE: NtQuerySystemInformation failed with %x \n", Status);
SmpMakeDefaultPagingFileDescriptor(Descriptor);
return;
}
/* Chekc how much RAM we have and set three times this amount as maximum */
Ram = BasicInfo.NumberOfPhysicalPages * BasicInfo.PageSize;
MaximumSize = 3 * Ram;
/* If we have more than 1GB, use that as minimum, otherwise, use 1.5X RAM */
MinimumSize = (Ram >= 0x40000000) ? Ram : MaximumSize / 2;
/* Write the new sizes in the descriptor and mark it as system managed */
Descriptor->MinSize.QuadPart = MinimumSize;
Descriptor->MaxSize.QuadPart = MaximumSize;
Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED;
}
NTSTATUS
NTAPI
SmpValidatePagingFileSizes(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONGLONG MinSize, MaxSize;
BOOLEAN WasTooBig = FALSE;
/* Capture the min and max */
MinSize = Descriptor->MinSize.QuadPart;
MaxSize = Descriptor->MaxSize.QuadPart;
DPRINT1("SMSS:PFILE: Validating sizes for `%wZ' %I64X %I64X\n",
&Descriptor->Name, MinSize, MaxSize);
/* Don't let minimum be bigger than maximum */
if (MinSize > MaxSize) MaxSize = MinSize;
/* On PAE we can have bigger pagefiles... */
if (SharedUserData->ProcessorFeatures[PF_PAE_ENABLED])
{
/* But we don't support that yet */
DPRINT1("ReactOS does not support PAE yet... assuming sizes OK\n");
}
else
{
/* Check if the minimum is more then 4095 MB */
if (MinSize > 0xFFF00000)
{
/* Trim it, this isn't allowed */
WasTooBig = TRUE;
MinSize = 0xFFF00000;
}
/* Check if the maximum is more then 4095 MB */
if (MaxSize > 0xFFF00000)
{
/* Trim it, this isn't allowed */
WasTooBig = TRUE;
MaxSize = 0xFFF00000;
}
}
/* Did we trim? */
if (WasTooBig)
{
/* Notify debugger output and write a flag in the descriptor */
DPRINT1("SMSS:PFILE: Trimmed size of `%wZ' to maximum allowed \n",
&Descriptor->Name);
Descriptor->Flags |= SMP_PAGEFILE_WAS_TOO_BIG;
}
/* Now write the (possibly trimmed) sizes back */
Descriptor->MinSize.QuadPart = MinSize;
Descriptor->MaxSize.QuadPart = MaxSize;
return Status;
}
NTSTATUS
NTAPI
SmpCreateSystemManagedPagingFile(IN PSMP_PAGEFILE_DESCRIPTOR Descriptor,
IN BOOLEAN DecreaseSize)
{
LARGE_INTEGER FuzzFactor, Size;
/* Make sure there's at least 1 paging file and that we are system-managed */
ASSERT(SmpNumberOfPagingFiles >= 1);
ASSERT(!IsListEmpty(&SmpPagingFileDescriptorList));
ASSERT(Descriptor->Flags & SMP_PAGEFILE_SYSTEM_MANAGED); // Descriptor->SystemManaged == 1 in ASSERT.
/* Keep decreasing the pagefile by this amount if we run out of space */
FuzzFactor.QuadPart = 0x1000000;
/* Create the descriptor for it (mainly the right sizes) and validate */
SmpMakeSystemManagedPagingFileDescriptor(Descriptor);
SmpValidatePagingFileSizes(Descriptor);
/* Use either the minimum size in the descriptor, or 16MB in minimal mode */
Size.QuadPart = DecreaseSize ? 0x1000000 : Descriptor->MinSize.QuadPart;
/* Check if this should be a fixed pagefile or an any pagefile*/
if (Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == '?')
{
/* Find a disk for it */
return SmpCreatePagingFileOnAnyDrive(Descriptor, &FuzzFactor, &Size);
}
/* Use the disk that was given */
return SmpCreatePagingFileOnFixedDrive(Descriptor, &FuzzFactor, &Size);
}
NTSTATUS
NTAPI
SmpCreateEmergencyPagingFile(VOID)
{
PSMP_PAGEFILE_DESCRIPTOR Descriptor;
ULONG Length;
WCHAR Buffer[32];
/* Allocate a descriptor */
Descriptor = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SMP_PAGEFILE_DESCRIPTOR));
if (!Descriptor) return STATUS_NO_MEMORY;
/* Initialize it */
RtlInitUnicodeString(&Descriptor->Name, NULL);
RtlInitUnicodeString(&Descriptor->Token, NULL);
/* Copy the default pagefile name */
wcscpy(Buffer, STANDARD_PAGING_FILE_NAME);
Length = wcslen(Buffer) * sizeof(WCHAR);
ASSERT(sizeof(Buffer) > Length);
/* Fill the rest of the descriptor out */
Descriptor->Name.Buffer = Buffer;
Descriptor->Name.Length = Length;
Descriptor->Name.MaximumLength = Length + sizeof(UNICODE_NULL);
Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = '?';
Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED |
SMP_PAGEFILE_EMERGENCY |
SMP_PAGEFILE_ON_ANY_DRIVE;
/* Insert it into the descriptor list */
InsertHeadList(&SmpPagingFileDescriptorList, &Descriptor->Entry);
SmpNumberOfPagingFiles++;
/* Go ahead and create it now, with the minimal size possible */
return SmpCreateSystemManagedPagingFile(Descriptor, TRUE);
}
NTSTATUS
NTAPI
SmpCreateVolumeDescriptors(VOID)
{
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
SmpCreatePagingFiles(VOID)
{
NTSTATUS Status;
PSMP_PAGEFILE_DESCRIPTOR Descriptor;
LARGE_INTEGER Size, FuzzFactor;
BOOLEAN Created = FALSE;
PLIST_ENTRY NextEntry;
/* Check if no paging files were requested */
if (!(SmpNumberOfPagingFiles) && !(SmpRegistrySpecifierPresent))
{
/* The list should be empty -- nothign to do */
ASSERT(IsListEmpty(&SmpPagingFileDescriptorList));
DPRINT1("SMSS:PFILE: No paging file was requested \n");
return STATUS_SUCCESS;
}
/* Initialize the volume descriptors so we can know what's available */
Status = SmpCreateVolumeDescriptors();
if (!NT_SUCCESS(Status))
{
/* We can't make decisions without this, so fail */
DPRINT1("SMSS:PFILE: Failed to create volume descriptors (status %X)\n",
Status);
return Status;
}
/* If we fail creating pagefiles, try to reduce by this much each time */
FuzzFactor.QuadPart = 0x1000000;
/* Loop the descriptor list */
NextEntry = SmpPagingFileDescriptorList.Flink;
while (NextEntry != &SmpPagingFileDescriptorList)
{
/* Check what kind of descriptor this is */
Descriptor = CONTAINING_RECORD(NextEntry, SMP_PAGEFILE_DESCRIPTOR, Entry);
if (Descriptor->Flags & SMP_PAGEFILE_SYSTEM_MANAGED)
{
/* This is a system-managed descriptor. Create the correct file */
DPRINT1("SMSS:PFILE: Creating a system managed paging file (`%wZ')\n",
&Descriptor->Name);
Status = SmpCreateSystemManagedPagingFile(Descriptor, FALSE);
if (!NT_SUCCESS(Status))
{
/* We failed -- try again, with size minimization this time */
DPRINT1("SMSS:PFILE: Trying lower sizes for (`%wZ') \n",
&Descriptor->Name);
Status = SmpCreateSystemManagedPagingFile(Descriptor, TRUE);
}
}
else
{
/* This is a manually entered descriptor. Validate its size first */
SmpValidatePagingFileSizes(Descriptor);
/* Check if this is an ANY pagefile or a FIXED pagefile */
DPRINT1("SMSS:PFILE: Creating a normal paging file (`%wZ') \n",
&Descriptor->Name);
if (Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == L'?')
{
/* It's an any pagefile, try to create it wherever possible */
Size = Descriptor->MinSize;
Status = SmpCreatePagingFileOnAnyDrive(Descriptor,
&FuzzFactor,
&Size);
if (!NT_SUCCESS(Status))
{
/* We failed to create it. Try again with a smaller size */
DPRINT1("SMSS:PFILE: Trying lower sizes for (`%wZ') \n",
&Descriptor->Name);
Size.QuadPart = 0x1000000;
Status = SmpCreatePagingFileOnAnyDrive(Descriptor,
&FuzzFactor,
&Size);
}
}
else
{
/* It's a fixed pagefile: override the minimum and use ours */
Size.QuadPart = 0x1000000;
Status = SmpCreatePagingFileOnFixedDrive(Descriptor,
&FuzzFactor,
&Size);
}
}
/* Go to the next descriptor */
if (NT_SUCCESS(Status)) Created = TRUE;
NextEntry = NextEntry->Flink;
}
/* Check if none of the code in our loops above was able to create it */
if (!Created)
{
/* Build an emergency pagefile ourselves */
DPRINT1("SMSS:PFILE: Creating emergency paging file. \n");
Status = SmpCreateEmergencyPagingFile();
}
/* All done */
return Status;
}