When is a memory-mapped file written to disk?

Hello list,

For my personal understanding, I’m going through a lot of code in
fastfat, both in editor and in debugger, to figure out some stuff
about file systems and their interactions with the OS. I thought I
understood how stuff with memory-mapped files worked, but some
sessions in the debugger seem to be telling me that I don’t.

My understanding is that a file is memory-mapped and then threads in
the memory manager / other memory manager components write modified
pages out “at will”. To test this, I made a small application that
opens a file, creates a memory mapping, and writes into this memory
mapping. I have breakpoints on FatCommonWrite and FatCommonRead in
fastfat, and when the mapping is initially created, I see a read for
the file, but I never see a write.

I think to myself “aha, this is cache manager behavior” (even though I
created the file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING)
because I can ‘type’ the file and see my modifications, but still
never see a “write” go by via IRP. I “pull the plug” on the machine
(hard power off via vmware), and reboot, but the data has persisted,
so somehow it got written to the backing store!

Is there some other place I should be looking for these writes in the
fastfat driver? I’ve been reading the old blue book by Rajeev Nagar
and it has been backing up my assumptions that I should see a paging
write from the memory manager… is there another place in that book I
should look that will tell me the answers?

Thank you list,

Andrew

Not sure how, but you’re missing something. Here’s an easy pre-cooked
experiment that you can try:

  1. Download FileTest: http://www.zezula.net/en/fstools/filetest.html

  2. Run FileTest. Change the file name to x:\TestFile.bin, where x: is your
    FAT drive.

  3. Change the desired access to include GENERIC_WRITE and click CreateFile.

  4. Go to the NtFileInfo tab and select FileEndOfFileInformation from the
    drop down. Change the EndOfFile value to something other than 0 (e.g.
    0x100). Click NtSetInformationFile.

  5. Go to the File Ops tab. Under File mapping, change the size to map to be
    whatever you specified in step 4. Select PAGE_READWRITE and FILE_MAP_WRITE.

  6. Click CreateFileMapping, click MapViewOfFile, and then (finally) click
    Access data (WR).

You’ve now just created a file, extended it, mapped a view to it, and then
dirtied the view. You should see absolutely nothing happen in the debugger,
but sometime in the distant future you’ll see a call like this into FAT
(this is from XP):

fastfat!FatCommonWrite
fastfat!FatFsdWrite
nt!IopfCallDriver
nt!IovCallDriver
fltmgr!FltpDispatch
nt!IopfCallDriver
nt!IovCallDriver
sr!SrWrite
nt!IopfCallDriver
nt!IovCallDriver
fltmgr!FltpDispatch
nt!IopfCallDriver
nt!IovCallDriver
nt!IoAsynchronousPageWrite
nt!MiMappedPageWriter
nt!PspSystemThreadStartup
nt!KiThreadStartup

If you want to make this happen quickly, you can use my favorite trick of
using a scummy “RAM optimizer” application to force the Mm to start writing
out dirty pages. Those artificially increase the memory pressure in the
system and force these conditions to happen, which is helpful if you don’t
want to wait around for several weeks for it to happen naturally.

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Andrew” wrote in message news:xxxxx@ntfsd…
> Hello list,
>
> For my personal understanding, I’m going through a lot of code in
> fastfat, both in editor and in debugger, to figure out some stuff
> about file systems and their interactions with the OS. I thought I
> understood how stuff with memory-mapped files worked, but some
> sessions in the debugger seem to be telling me that I don’t.
>
> My understanding is that a file is memory-mapped and then threads in
> the memory manager / other memory manager components write modified
> pages out “at will”. To test this, I made a small application that
> opens a file, creates a memory mapping, and writes into this memory
> mapping. I have breakpoints on FatCommonWrite and FatCommonRead in
> fastfat, and when the mapping is initially created, I see a read for
> the file, but I never see a write.
>
> I think to myself “aha, this is cache manager behavior” (even though I
> created the file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING)
> because I can ‘type’ the file and see my modifications, but still
> never see a “write” go by via IRP. I “pull the plug” on the machine
> (hard power off via vmware), and reboot, but the data has persisted,
> so somehow it got written to the backing store!
>
> Is there some other place I should be looking for these writes in the
> fastfat driver? I’ve been reading the old blue book by Rajeev Nagar
> and it has been backing up my assumptions that I should see a paging
> write from the memory manager… is there another place in that book I
> should look that will tell me the answers?
>
> Thank you list,
>
> Andrew
>

I wasn’t waiting around in the debugger a long time (a few minutes),
which could explain why my “experiment” was failing.

So I guess a related question I have is, the MSDN docs on combining
FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING suggest that the
memory manager will directly (or very quickly) write data through a
mapping to the backing store. I was thinking about this and arrived at
two conclusions:

a. the memory manager has some magical and relatively inexpensive way
to figure out when writes happen to a particular page/region of pages
and uses this to flush those pages out of a mapping “quickly” to the
backing store

b. I am reading too much into the docs, and a memory mapped file on a
file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING is still
cached in exactly the same way and data is written out “whenever”.

Since option ‘a’ involves “magical”, I was thinking that what was
really going on was option ‘b’, but I would really like to be sure.
Basically, how does a non-cached mapping work / differ from a cached
mapping, and when are things written out from the non-cached mapping?

I’ll try the experiment you suggest, thank you.

Andrew

On Wed, Jul 7, 2010 at 2:32 PM, Scott Noone wrote:
> Not sure how, but you’re missing something. Here’s an easy pre-cooked
> experiment that you can try:
>
> 1) Download FileTest: http://www.zezula.net/en/fstools/filetest.html
>
> 2) Run FileTest. Change the file name to x:\TestFile.bin, where x: is your
> FAT drive.
>
> 3) Change the desired access to include GENERIC_WRITE and click CreateFile.
>
> 4) Go to the NtFileInfo tab and select FileEndOfFileInformation from the
> drop down. Change the EndOfFile value to something other than 0 (e.g.
> 0x100). ?Click NtSetInformationFile.
>
> 5) Go to the File Ops tab. Under File mapping, change the size to map to be
> whatever you specified in step 4. Select PAGE_READWRITE and FILE_MAP_WRITE.
>
> 6) Click CreateFileMapping, click MapViewOfFile, and then (finally) click
> Access data (WR).
>
> You’ve now just created a file, extended it, mapped a view to it, and then
> dirtied the view. You should see absolutely nothing happen in the debugger,
> but sometime in the distant future you’ll see a call like this into FAT
> (this is from XP):
>
> fastfat!FatCommonWrite
> fastfat!FatFsdWrite
> nt!IopfCallDriver
> nt!IovCallDriver
> fltmgr!FltpDispatch
> nt!IopfCallDriver
> nt!IovCallDriver
> sr!SrWrite
> nt!IopfCallDriver
> nt!IovCallDriver
> fltmgr!FltpDispatch
> nt!IopfCallDriver
> nt!IovCallDriver
> nt!IoAsynchronousPageWrite
> nt!MiMappedPageWriter
> nt!PspSystemThreadStartup
> nt!KiThreadStartup
>
> If you want to make this happen quickly, you can use my favorite trick of
> using a scummy “RAM optimizer” application to force the Mm to start writing
> out dirty pages. Those artificially increase the memory pressure in the
> system and force these conditions to happen, which is helpful if you don’t
> want to wait around for several weeks for it to happen naturally.
>
> -scott
>
> –
> Scott Noone
> Consulting Associate
> OSR Open Systems Resources, Inc.
> http://www.osronline.com
>
>
>
> “Andrew” wrote in message news:xxxxx@ntfsd…
>>
>> Hello list,
>>
>> For my personal understanding, I’m going through a lot of code in
>> fastfat, both in editor and in debugger, to figure out some stuff
>> about file systems and their interactions with the OS. I thought I
>> understood how stuff with memory-mapped files worked, but some
>> sessions in the debugger seem to be telling me that I don’t.
>>
>> My understanding is that a file is memory-mapped and then threads in
>> the memory manager / other memory manager components write modified
>> pages out “at will”. To test this, I made a small application that
>> opens a file, creates a memory mapping, and writes into this memory
>> mapping. I have breakpoints on FatCommonWrite and FatCommonRead in
>> fastfat, and when the mapping is initially created, I see a read for
>> the file, but I never see a write.
>>
>> I think to myself “aha, this is cache manager behavior” (even though I
>> created the file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING)
>> because I can ‘type’ the file and see my modifications, but still
>> never see a “write” go by via IRP. I “pull the plug” on the machine
>> (hard power off via vmware), and reboot, but the data has persisted,
>> so somehow it got written to the backing store!
>>
>> Is there some other place I should be looking for these writes in the
>> fastfat driver? I’ve been reading the old blue book by Rajeev Nagar
>> and it has been backing up my assumptions that I should see a paging
>> write from the memory manager… is there another place in that book I
>> should look that will tell me the answers?
>>
>> Thank you list,
>>
>> Andrew
>>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

> Basically, how does a non-cached mapping work / differ from a cached

mapping, and when are things written out from the non-cached mapping?

It doesn’t, those flags are only meaningful to the read/write interface.
It’s alluded to in the MSDN comments about FILE_FLAG_NO_BUFFERING:

The file or device is being opened with no system caching for data reads and
writes. This flag does not affect hard disk caching or memory mapped files.

http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Andrew” wrote in message news:xxxxx@ntfsd…
> I wasn’t waiting around in the debugger a long time (a few minutes),
> which could explain why my “experiment” was failing.
>
> So I guess a related question I have is, the MSDN docs on combining
> FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING suggest that the
> memory manager will directly (or very quickly) write data through a
> mapping to the backing store. I was thinking about this and arrived at
> two conclusions:
>
> a. the memory manager has some magical and relatively inexpensive way
> to figure out when writes happen to a particular page/region of pages
> and uses this to flush those pages out of a mapping “quickly” to the
> backing store
>
> b. I am reading too much into the docs, and a memory mapped file on a
> file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING is still
> cached in exactly the same way and data is written out “whenever”.
>
> Since option ‘a’ involves “magical”, I was thinking that what was
> really going on was option ‘b’, but I would really like to be sure.
> Basically, how does a non-cached mapping work / differ from a cached
> mapping, and when are things written out from the non-cached mapping?
>
> I’ll try the experiment you suggest, thank you.
>
> Andrew
>
> On Wed, Jul 7, 2010 at 2:32 PM, Scott Noone wrote:
>> Not sure how, but you’re missing something. Here’s an easy pre-cooked
>> experiment that you can try:
>>
>> 1) Download FileTest: http://www.zezula.net/en/fstools/filetest.html
>>
>> 2) Run FileTest. Change the file name to x:\TestFile.bin, where x: is
>> your
>> FAT drive.
>>
>> 3) Change the desired access to include GENERIC_WRITE and click
>> CreateFile.
>>
>> 4) Go to the NtFileInfo tab and select FileEndOfFileInformation from the
>> drop down. Change the EndOfFile value to something other than 0 (e.g.
>> 0x100). Click NtSetInformationFile.
>>
>> 5) Go to the File Ops tab. Under File mapping, change the size to map to
>> be
>> whatever you specified in step 4. Select PAGE_READWRITE and
>> FILE_MAP_WRITE.
>>
>> 6) Click CreateFileMapping, click MapViewOfFile, and then (finally) click
>> Access data (WR).
>>
>> You’ve now just created a file, extended it, mapped a view to it, and
>> then
>> dirtied the view. You should see absolutely nothing happen in the
>> debugger,
>> but sometime in the distant future you’ll see a call like this into FAT
>> (this is from XP):
>>
>> fastfat!FatCommonWrite
>> fastfat!FatFsdWrite
>> nt!IopfCallDriver
>> nt!IovCallDriver
>> fltmgr!FltpDispatch
>> nt!IopfCallDriver
>> nt!IovCallDriver
>> sr!SrWrite
>> nt!IopfCallDriver
>> nt!IovCallDriver
>> fltmgr!FltpDispatch
>> nt!IopfCallDriver
>> nt!IovCallDriver
>> nt!IoAsynchronousPageWrite
>> nt!MiMappedPageWriter
>> nt!PspSystemThreadStartup
>> nt!KiThreadStartup
>>
>> If you want to make this happen quickly, you can use my favorite trick of
>> using a scummy “RAM optimizer” application to force the Mm to start
>> writing
>> out dirty pages. Those artificially increase the memory pressure in the
>> system and force these conditions to happen, which is helpful if you
>> don’t
>> want to wait around for several weeks for it to happen naturally.
>>
>> -scott
>>
>> –
>> Scott Noone
>> Consulting Associate
>> OSR Open Systems Resources, Inc.
>> http://www.osronline.com
>>
>>
>>
>> “Andrew” wrote in message news:xxxxx@ntfsd…
>>>
>>> Hello list,
>>>
>>> For my personal understanding, I’m going through a lot of code in
>>> fastfat, both in editor and in debugger, to figure out some stuff
>>> about file systems and their interactions with the OS. I thought I
>>> understood how stuff with memory-mapped files worked, but some
>>> sessions in the debugger seem to be telling me that I don’t.
>>>
>>> My understanding is that a file is memory-mapped and then threads in
>>> the memory manager / other memory manager components write modified
>>> pages out “at will”. To test this, I made a small application that
>>> opens a file, creates a memory mapping, and writes into this memory
>>> mapping. I have breakpoints on FatCommonWrite and FatCommonRead in
>>> fastfat, and when the mapping is initially created, I see a read for
>>> the file, but I never see a write.
>>>
>>> I think to myself “aha, this is cache manager behavior” (even though I
>>> created the file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING)
>>> because I can ‘type’ the file and see my modifications, but still
>>> never see a “write” go by via IRP. I “pull the plug” on the machine
>>> (hard power off via vmware), and reboot, but the data has persisted,
>>> so somehow it got written to the backing store!
>>>
>>> Is there some other place I should be looking for these writes in the
>>> fastfat driver? I’ve been reading the old blue book by Rajeev Nagar
>>> and it has been backing up my assumptions that I should see a paging
>>> write from the memory manager… is there another place in that book I
>>> should look that will tell me the answers?
>>>
>>> Thank you list,
>>>
>>> Andrew
>>>
>>
>> —
>> NTFSD is sponsored by OSR
>>
>> For our schedule of debugging and file system seminars
>> (including our new fs mini-filter seminar) visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>

How foolish of me! Things make much more sense now. That’s far more
than an allusion. :wink: I should have read the MSDN more closely.

Thank you for your time, Scott.

Andrew

On Wed, Jul 7, 2010 at 3:12 PM, Scott Noone wrote:
>> Basically, how does a non-cached mapping work / differ from a cached
>> mapping, and when are things written out from the non-cached mapping?
>
> It doesn’t, those flags are only meaningful to the read/write interface.
> It’s alluded to in the MSDN comments about FILE_FLAG_NO_BUFFERING:
>
> The file or device is being opened with no system caching for data reads and
> writes. This flag does not affect hard disk caching or memory mapped files.
>
> http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
>
> -scott
>
> –
> Scott Noone
> Consulting Associate
> OSR Open Systems Resources, Inc.
> http://www.osronline.com
>
>
> “Andrew” wrote in message news:xxxxx@ntfsd…
>>
>> I wasn’t waiting around in the debugger a long time (a few minutes),
>> which could explain why my “experiment” was failing.
>>
>> So I guess a related question I have is, the MSDN docs on combining
>> FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING suggest that the
>> memory manager will directly (or very quickly) write data through a
>> mapping to the backing store. I was thinking about this and arrived at
>> two conclusions:
>>
>> a. the memory manager has some magical and relatively inexpensive way
>> to figure out when writes happen to a particular page/region of pages
>> and uses this to flush those pages out of a mapping “quickly” to the
>> backing store
>>
>> b. I am reading too much into the docs, and a memory mapped file on a
>> file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING is still
>> cached in exactly the same way and data is written out “whenever”.
>>
>> Since option ‘a’ involves “magical”, I was thinking that what was
>> really going on was option ‘b’, but I would really like to be sure.
>> Basically, how does a non-cached mapping work / differ from a cached
>> mapping, and when are things written out from the non-cached mapping?
>>
>> I’ll try the experiment you suggest, thank you.
>>
>> Andrew
>>
>> On Wed, Jul 7, 2010 at 2:32 PM, Scott Noone wrote:
>>>
>>> Not sure how, but you’re missing something. Here’s an easy pre-cooked
>>> experiment that you can try:
>>>
>>> 1) Download FileTest: http://www.zezula.net/en/fstools/filetest.html
>>>
>>> 2) Run FileTest. Change the file name to x:\TestFile.bin, where x: is
>>> your
>>> FAT drive.
>>>
>>> 3) Change the desired access to include GENERIC_WRITE and click
>>> CreateFile.
>>>
>>> 4) Go to the NtFileInfo tab and select FileEndOfFileInformation from the
>>> drop down. Change the EndOfFile value to something other than 0 (e.g.
>>> 0x100). ?Click NtSetInformationFile.
>>>
>>> 5) Go to the File Ops tab. Under File mapping, change the size to map to
>>> be
>>> whatever you specified in step 4. Select PAGE_READWRITE and
>>> FILE_MAP_WRITE.
>>>
>>> 6) Click CreateFileMapping, click MapViewOfFile, and then (finally) click
>>> Access data (WR).
>>>
>>> You’ve now just created a file, extended it, mapped a view to it, and
>>> then
>>> dirtied the view. You should see absolutely nothing happen in the
>>> debugger,
>>> but sometime in the distant future you’ll see a call like this into FAT
>>> (this is from XP):
>>>
>>> fastfat!FatCommonWrite
>>> fastfat!FatFsdWrite
>>> nt!IopfCallDriver
>>> nt!IovCallDriver
>>> fltmgr!FltpDispatch
>>> nt!IopfCallDriver
>>> nt!IovCallDriver
>>> sr!SrWrite
>>> nt!IopfCallDriver
>>> nt!IovCallDriver
>>> fltmgr!FltpDispatch
>>> nt!IopfCallDriver
>>> nt!IovCallDriver
>>> nt!IoAsynchronousPageWrite
>>> nt!MiMappedPageWriter
>>> nt!PspSystemThreadStartup
>>> nt!KiThreadStartup
>>>
>>> If you want to make this happen quickly, you can use my favorite trick of
>>> using a scummy “RAM optimizer” application to force the Mm to start
>>> writing
>>> out dirty pages. Those artificially increase the memory pressure in the
>>> system and force these conditions to happen, which is helpful if you
>>> don’t
>>> want to wait around for several weeks for it to happen naturally.
>>>
>>> -scott
>>>
>>> –
>>> Scott Noone
>>> Consulting Associate
>>> OSR Open Systems Resources, Inc.
>>> http://www.osronline.com
>>>
>>>
>>>
>>> “Andrew” wrote in message news:xxxxx@ntfsd…
>>>>
>>>> Hello list,
>>>>
>>>> For my personal understanding, I’m going through a lot of code in
>>>> fastfat, both in editor and in debugger, to figure out some stuff
>>>> about file systems and their interactions with the OS. I thought I
>>>> understood how stuff with memory-mapped files worked, but some
>>>> sessions in the debugger seem to be telling me that I don’t.
>>>>
>>>> My understanding is that a file is memory-mapped and then threads in
>>>> the memory manager / other memory manager components write modified
>>>> pages out “at will”. To test this, I made a small application that
>>>> opens a file, creates a memory mapping, and writes into this memory
>>>> mapping. I have breakpoints on FatCommonWrite and FatCommonRead in
>>>> fastfat, and when the mapping is initially created, I see a read for
>>>> the file, but I never see a write.
>>>>
>>>> I think to myself “aha, this is cache manager behavior” (even though I
>>>> created the file with FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING)
>>>> because I can ‘type’ the file and see my modifications, but still
>>>> never see a “write” go by via IRP. I “pull the plug” on the machine
>>>> (hard power off via vmware), and reboot, but the data has persisted,
>>>> so somehow it got written to the backing store!
>>>>
>>>> Is there some other place I should be looking for these writes in the
>>>> fastfat driver? I’ve been reading the old blue book by Rajeev Nagar
>>>> and it has been backing up my assumptions that I should see a paging
>>>> write from the memory manager… is there another place in that book I
>>>> should look that will tell me the answers?
>>>>
>>>> Thank you list,
>>>>
>>>> Andrew
>>>>
>>>
>>> —
>>> NTFSD is sponsored by OSR
>>>
>>> For our schedule of debugging and file system seminars
>>> (including our new fs mini-filter seminar) visit:
>>> http://www.osr.com/seminars
>>>
>>> To unsubscribe, visit the List Server section of OSR Online at
>>> http://www.osronline.com/page.cfm?name=ListServer
>>>
>>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

> If you want to make this happen quickly, you can use my favorite trick of

using a scummy “RAM optimizer” application to force the Mm to start
writing out dirty pages. Those artificially increase the memory pressure
in the system and force these conditions to happen, which is helpful if
you don’t want to wait around for several weeks for it to happen
naturally.

You can also use rammap.exe from Sysinternals to empty all working sets
and then flush the modified list.


Pavel Lebedinsky/Windows Fundamentals Test
This posting is provided “AS IS” with no warranties, and confers no rights.

“Pavel Lebedinsky” wrote in message
news:xxxxx@ntfsd…
> You can also use rammap.exe from Sysinternals to empty all working sets
> and then flush the modified list.

Nifty, certainly less scummy and seems to be a better option for Vista and
later. Thanks.

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Pavel Lebedinsky” wrote in message
news:xxxxx@ntfsd…
>> If you want to make this happen quickly, you can use my favorite trick of
>> using a scummy “RAM optimizer” application to force the Mm to start
>> writing out dirty pages. Those artificially increase the memory pressure
>> in the system and force these conditions to happen, which is helpful if
>> you don’t want to wait around for several weeks for it to happen
>> naturally.
>
>
> You can also use rammap.exe from Sysinternals to empty all working sets
> and then flush the modified list.
>
> –
> Pavel Lebedinsky/Windows Fundamentals Test
> This posting is provided “AS IS” with no warranties, and confers no
> rights.
>
>