Tracking down MmSt paged pool usage

 

A trend that I’ve noticed recently are cases involving paged pool depletion with high MmSt tag usage that remains after trying KB304101 (PoolUsageMaximum). These pool allocations are used by the memory manager for section object prototype PTEs. There are generally only two options when this happens: 1) upgrade to a 64-bit platform, or 2) reduce the size of the volumes. But we may want to know what mapped files are using this memory. Here is how it can be done. Start with !memusage.

 

5: kd> !memusage

 loading PFN database

loading (100% complete)

Compiling memory usage data (99% Complete).

             Zeroed: 19073 ( 76292 kb)

               Free: 0 ( 0 kb)

            Standby: 1468824 (5875296 kb)

           Modified: 368 ( 1472 kb)

    ModifiedNoWrite: 1927 ( 7708 kb)

       Active/Valid: 605772 (2423088 kb)

         Transition: 0 ( 0 kb)

                Bad: 0 ( 0 kb)

            Unknown: 0 ( 0 kb)

              TOTAL: 2095964 (8383856 kb)

  Building kernel map

  Finished building kernel map

Scanning PFN database - (100% complete)

 

Following this you will see the list of mapped files and their control areas.

 

  Usage Summary (in Kb):

Control Valid Standby Dirty Shared Locked PageTables name

8c62a638 1108 945868 3064 0 0 0 mapped_file( $Mft )

 

The control area is the address at the far left and has a Segment field that contains the total number of PTEs.

 

5: kd> dt 8c62a638 _CONTROL_AREA Segment->TotalNumberOfPtes

nt!_CONTROL_AREA

   +0x000 Segment :

      +0x004 TotalNumberOfPtes : 0x1e8b00

 

The MmSt allocations contain these PTEs so all we need to do is multiply this by the size of a PTE to get the total size of the MmSt allocations for this control area. Note that there may be multiple allocations for this control area, but this number will reflect the total size all these allocations.

 

5: kd> ?? 0x1e8b00 * sizeof(nt!_MMPTE)

unsigned int 0xf45800

 

So now we know the MmSt size in bytes for a single control area, or mapped file. What if we would like to see the totals for all mapped files from the !memusage output? First, place the !memusage output in a text file and remove all header information. You will also need to remove all tail information including the page file and process summaries. Every line should look like these.

 

8c62a638 1108 945868 3064 0 0 0 mapped_file( $Mft )

8b06ac18 516 0 0 0 0 0 No Name for File

 

We want to include the “No Name for File” entries since those are valid mapped files even though the name could not be located. Next strip out everything but the control area address. You can use Excel or any other tool that allows you to select and delete columns in a text file. Now we have a file with a single column of all the control areas on the system. The following debugger command script can be used to process this file.

 

$$ countptes.txt script

r $t2 = 0;

$$ Replace the memusage.txt file name with your file name.

.foreach /f (ca "memusage.txt") {

    r $t1 = @@c++(((nt!_CONTROL_AREA *)(0x${ca}))->Segment->TotalNumberOfPtes);

    .printf "Control Area %p : %d\n", ${ca}, @$t1;

    r $t2 = @$t2 + @$t1;

}

.printf "Total PTEs : %d\n", @$t2;

.printf "MmSt size : %d bytes\n", (@$t2 * @@c++(sizeof(nt!_MMPTE)));

 

The following command will execute the script.

 

5: kd> $$><countptes.txt

 

This will show the number of PTEs for each control area, followed by a summary.

 

Total PTEs : 62790244

MmSt size : 502321952 bytes

 

A common high user of MmSt allocations is $Mft. The cache manager will hold the MmSt allocations for these file system metadata files at a cost of up to 4 files per PTE. This technique can be used to determine how much $Mft is using MmSt pool memory by first using findstr at a command prompt to isolate just those values from the !memusage output.

 

C:\Projects>findstr /c:"$Mft" memusage.txt >mftusage.txt

 

After stripping out the control area addresses with Excel and running the command script you’ll have the size of the MmSt allocations for just the $Mft files. If this is consuming most of the MmSt bytes then you are limited to the options mentioned at the beginning of this article. There may be other options if something else is the primary user but it will likely involve reducing some heavy load on the system.

 

-Bryan