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.c?rev=55803&r1=55802&r2=55803&view=diff
==============================================================================
--- 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);


Reply via email to