Author: tfaber Date: Wed Feb 22 09:07:03 2012 New Revision: 55803
URL: http://svn.reactos.org/svn/reactos?rev=55803&view=rev Log: [SMSS2] - When deleting an old page file, take the newly freed space into account - Keep at least 64 MB of disk free instead of 32 so that 2nd stage can succeed with a small disk - Miscellaneous fixes and simplifications in the page file code
Modified: trunk/reactos/base/system/smss2/pagefile.c
Modified: trunk/reactos/base/system/smss2/pagefile.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/pagefile.... ============================================================================== --- trunk/reactos/base/system/smss2/pagefile.c [iso-8859-1] (original) +++ trunk/reactos/base/system/smss2/pagefile.c [iso-8859-1] Wed Feb 22 09:07:03 2012 @@ -15,10 +15,15 @@ /* GLOBALS ********************************************************************/
// -// Taken from ASSERTs +// Constants // #define STANDARD_PAGING_FILE_NAME L"\??\?:\pagefile.sys" #define STANDARD_DRIVE_LETTER_OFFSET 4 +#define MEGABYTE 0x100000UL +#define MAXIMUM_PAGEFILE_SIZE (4095 * MEGABYTE) +/* This should be 32 MB, but we need more than that for 2nd stage setup */ +#define MINIMUM_TO_KEEP_FREE (64 * MEGABYTE) +#define FUZZ_FACTOR (16 * MEGABYTE)
// // Structure and flags describing each pagefile @@ -83,9 +88,8 @@ PSMP_PAGEFILE_DESCRIPTOR Descriptor, ListDescriptor; ULONG i; WCHAR c; - PWCHAR p, ArgBuffer; PLIST_ENTRY NextEntry; - UNICODE_STRING PageFileName, Arguments; + UNICODE_STRING PageFileName, Arguments, SecondArgument;
/* Make sure we don't have too many */ if (SmpNumberOfPagingFiles >= 16) @@ -131,7 +135,7 @@ }
/* Was a pagefile not specified, or was it specified with no size? */ - if ((Arguments.Buffer) || (ZeroSize)) + if (!(Arguments.Buffer) || (ZeroSize)) { /* In this case, the system will manage its size */ SystemManaged = TRUE; @@ -149,17 +153,18 @@ }
/* Now advance to the next argument */ - ArgBuffer = Arguments.Buffer; - p = ArgBuffer; - while (*p++) - { - /* Which should be a space... */ - if (*p == L' ') + for (i = 0; i < Arguments.Length / sizeof(WCHAR); i++) + { + /* Found a space -- second argument must start here */ + if (Arguments.Buffer[i] == L' ') { - /* And use the rest of the arguments as a maximum size */ - Arguments.Length -= ((PCHAR)p - (PCHAR)ArgBuffer); - Arguments.Buffer = ArgBuffer; - Status = RtlUnicodeStringToInteger(&Arguments, 0, &MaxSize); + /* Use the rest of the arguments as a maximum size */ + SecondArgument.Buffer = &Arguments.Buffer[i]; + SecondArgument.Length = Arguments.Length - + i * sizeof(WCHAR); + SecondArgument.MaximumLength = Arguments.MaximumLength - + i * sizeof(WCHAR); + Status = RtlUnicodeStringToInteger(&SecondArgument, 0, &MaxSize); if (!NT_SUCCESS(Status)) { /* Fail */ @@ -168,8 +173,6 @@ return Status; }
- /* We have both min and max, restore argument buffer */ - Arguments.Buffer = ArgBuffer; // Actual Windows Bug in faillure case above. break; } } @@ -192,8 +195,8 @@ /* Capture all our data into the descriptor */ Descriptor->Token = *PageFileToken; Descriptor->Name = PageFileName; - Descriptor->MinSize.QuadPart = MinSize * 0x100000; - Descriptor->MaxSize.QuadPart = MaxSize * 0x100000; + Descriptor->MinSize.QuadPart = MinSize * MEGABYTE; + Descriptor->MaxSize.QuadPart = MaxSize * MEGABYTE; if (SystemManaged) Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED; Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = RtlUpcaseUnicodeChar(Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET]); @@ -271,8 +274,7 @@ }
NtClose(FileHandle); - Size->LowPart = StandardInfo.AllocationSize.LowPart; - Size->HighPart = StandardInfo.AllocationSize.HighPart; + Size->QuadPart = StandardInfo.AllocationSize.QuadPart; return STATUS_SUCCESS; }
@@ -346,9 +348,7 @@
/* Build the standard path */ wcscpy(PathString, L"\??\A:\"); - VolumeName.Buffer = PathString; - VolumeName.Length = wcslen(PathString) * sizeof(WCHAR); - VolumeName.MaximumLength = VolumeName.Length + sizeof(UNICODE_NULL); + RtlInitUnicodeString(&VolumeName, PathString); VolumeName.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = Volume->DriveLetter; DPRINT("SMSS:PFILE: Querying volume `%wZ' for free space \n", &VolumeName);
@@ -378,13 +378,12 @@ FileFsSizeInformation); if (!NT_SUCCESS(Status)) { - /* We failed -- keep going */ + /* We failed */ DPRINT1("SMSS:PFILE: Query volume `%wZ' (handle %p) for size failed" " with status %X \n", &VolumeName, VolumeHandle, Status); - RtlFreeHeap(RtlGetProcessHeap(), 0, Volume); NtClose(VolumeHandle); return Status; } @@ -394,10 +393,9 @@ FreeSpace.QuadPart = SizeInfo.AvailableAllocationUnits.QuadPart * SizeInfo.SectorsPerAllocationUnit; FinalFreeSpace.QuadPart = FreeSpace.QuadPart * SizeInfo.BytesPerSector; - Volume->FreeSpace = FinalFreeSpace;
/* Check if there's less than 32MB free so we don't starve the disk */ - if (FinalFreeSpace.QuadPart <= 0x2000000) + if (FinalFreeSpace.QuadPart <= MINIMUM_TO_KEEP_FREE) { /* In this case, act as if there's no free space */ Volume->FreeSpace.QuadPart = 0; @@ -405,7 +403,8 @@ else { /* Trim off 32MB to give the disk a bit of breathing room */ - Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart - 0x2000000; + Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart - + MINIMUM_TO_KEEP_FREE; }
return STATUS_SUCCESS; @@ -540,7 +539,7 @@
/* Check how big we can make the pagefile */ Status = SmpGetPagingFileSize(&Descriptor->Name, &PageFileSize); - if (PageFileSize.QuadPart > 0) ShouldDelete = TRUE; + if (NT_SUCCESS(Status) && PageFileSize.QuadPart > 0) ShouldDelete = TRUE; DPRINT("SMSS:PFILE: Detected size %I64X for future paging file `%wZ'\n", PageFileSize, &Descriptor->Name); @@ -588,7 +587,13 @@ if (Descriptor->ActualMinSize.QuadPart < MinimumSize->QuadPart) { /* Delete the current page file and fail */ - if (ShouldDelete) SmpDeletePagingFile(&Descriptor->Name); + if (ShouldDelete) + { + SmpDeletePagingFile(&Descriptor->Name); + + /* FIXFIX: Windows Vista does this, and it seems like we should too, so try to see if this fixes KVM */ + Volume->FreeSpace.QuadPart = PageFileSize.QuadPart; + } DPRINT1("SMSS:PFILE: Failing for min %I64X, max %I64X, real min %I64X \n", Descriptor->ActualMinSize.QuadPart, Descriptor->ActualMaxSize.QuadPart, @@ -644,8 +649,8 @@ { /* The default descriptor uses 128MB as a pagefile size */ Descriptor->Flags |= SMP_PAGEFILE_DEFAULT; - Descriptor->MinSize.QuadPart = 0x8000000; - Descriptor->MaxSize.QuadPart = 0x8000000; + Descriptor->MinSize.QuadPart = 128 * MEGABYTE; + Descriptor->MaxSize.QuadPart = 128 * MEGABYTE; }
VOID @@ -674,7 +679,7 @@ MaximumSize = 3 * Ram;
/* If we have more than 1GB, use that as minimum, otherwise, use 1.5X RAM */ - MinimumSize = (Ram >= 0x40000000) ? Ram : MaximumSize / 2; + MinimumSize = (Ram >= 1024 * MEGABYTE) ? Ram : MaximumSize / 2;
/* Write the new sizes in the descriptor and mark it as system managed */ Descriptor->MinSize.QuadPart = MinimumSize; @@ -708,19 +713,19 @@ else { /* Check if the minimum is more then 4095 MB */ - if (MinSize > 0xFFF00000) + if (MinSize > MAXIMUM_PAGEFILE_SIZE) { /* Trim it, this isn't allowed */ WasTooBig = TRUE; - MinSize = 0xFFF00000; + MinSize = MAXIMUM_PAGEFILE_SIZE; }
/* Check if the maximum is more then 4095 MB */ - if (MaxSize > 0xFFF00000) + if (MaxSize > MAXIMUM_PAGEFILE_SIZE) { /* Trim it, this isn't allowed */ WasTooBig = TRUE; - MaxSize = 0xFFF00000; + MaxSize = MAXIMUM_PAGEFILE_SIZE; } }
@@ -752,14 +757,14 @@ 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; + FuzzFactor.QuadPart = FUZZ_FACTOR;
/* 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; + Size.QuadPart = DecreaseSize ? 16 * MEGABYTE : Descriptor->MinSize.QuadPart;
/* Check if this should be a fixed pagefile or an any pagefile*/ if (Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] == '?') @@ -777,7 +782,6 @@ SmpCreateEmergencyPagingFile(VOID) { PSMP_PAGEFILE_DESCRIPTOR Descriptor; - ULONG Length; WCHAR Buffer[32];
/* Allocate a descriptor */ @@ -787,18 +791,14 @@ if (!Descriptor) return STATUS_NO_MEMORY;
/* Initialize it */ - RtlInitUnicodeString(&Descriptor->Name, NULL); RtlInitUnicodeString(&Descriptor->Token, NULL);
/* Copy the default pagefile name */ + ASSERT(sizeof(Buffer) >= sizeof(STANDARD_PAGING_FILE_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); + RtlInitUnicodeString(&Descriptor->Name, Buffer); Descriptor->Name.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = '?'; Descriptor->Flags |= SMP_PAGEFILE_SYSTEM_MANAGED | SMP_PAGEFILE_EMERGENCY | @@ -818,7 +818,6 @@ { NTSTATUS Status; UNICODE_STRING VolumePath; - ULONG Length; BOOLEAN BootVolumeFound = FALSE; WCHAR StartChar, Drive, DriveDiff; HANDLE VolumeHandle; @@ -849,14 +848,11 @@
/* Build the volume string, starting with A: (we'll edit this in place) */ wcscpy(Buffer, L"\??\A:\"); - Length = wcslen(Buffer); - VolumePath.Buffer = Buffer; - VolumePath.Length = Length * sizeof(WCHAR); - VolumePath.MaximumLength = Length * sizeof(WCHAR) + sizeof(UNICODE_NULL); + RtlInitUnicodeString(&VolumePath, Buffer);
/* Start with the C drive except on weird Japanese NECs... */ StartChar = SharedUserData->AlternativeArchitecture ? L'A' : L'C'; - for (Drive = StartChar, DriveDiff = StartChar - 'A'; Drive <= L'Z'; Drive++, DriveDiff++) + for (Drive = StartChar, DriveDiff = StartChar - L'A'; Drive <= L'Z'; Drive++, DriveDiff++) { /* Skip the disk if it's not in the drive map */ if (!((1 << DriveDiff) & ProcessInformation.Query.DriveMap)) continue; @@ -967,10 +963,9 @@ FreeSpace.QuadPart = SizeInfo.AvailableAllocationUnits.QuadPart * SizeInfo.SectorsPerAllocationUnit; FinalFreeSpace.QuadPart = FreeSpace.QuadPart * SizeInfo.BytesPerSector; - Volume->FreeSpace = FinalFreeSpace;
/* Check if there's less than 32MB free so we don't starve the disk */ - if (FinalFreeSpace.QuadPart <= 0x2000000) + if (FinalFreeSpace.QuadPart <= MINIMUM_TO_KEEP_FREE) { /* In this case, act as if there's no free space */ Volume->FreeSpace.QuadPart = 0; @@ -978,7 +973,8 @@ else { /* Trim off 32MB to give the disk a bit of breathing room */ - Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart - 0x2000000; + Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart - + MINIMUM_TO_KEEP_FREE; }
/* All done, add this volume to our descriptor list */ @@ -1026,7 +1022,7 @@ }
/* If we fail creating pagefiles, try to reduce by this much each time */ - FuzzFactor.QuadPart = 0x1000000; + FuzzFactor.QuadPart = FUZZ_FACTOR;
/* Loop the descriptor list */ NextEntry = SmpPagingFileDescriptorList.Flink; @@ -1068,7 +1064,7 @@ /* 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; + Size.QuadPart = 16 * MEGABYTE; Status = SmpCreatePagingFileOnAnyDrive(Descriptor, &FuzzFactor, &Size); @@ -1077,7 +1073,7 @@ else { /* It's a fixed pagefile: override the minimum and use ours */ - Size.QuadPart = 0x1000000; + Size.QuadPart = 16 * MEGABYTE; Status = SmpCreatePagingFileOnFixedDrive(Descriptor, &FuzzFactor, &Size);