Hi all,
I had a few questions about memory mapped files in the context of a minifilter. I want to be able to detect if somebody changes a file through a memory mapping. From what I can gather from the archives one easy way to determine if a section object is being created is to use the IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION callback in a minifilter, and look for a SyncType of CreateSection. This will tell me if somebody actually memory maps the file. But writes to this memory will just simply be memory writes by an application, and will eventually be written to disk via paging writes. So my other question is, is there any way to know if an application that has a memory mapping to a file writes to that memory *before* I see the CLEANUP IRP on the file object in question? Or might I see the section get created, the cleanup, and then in between the cleanup and the close the pages actually get written to disk as paging i/o?
Thanks,
Matt
>question? Or might I see the section get created, the cleanup, and then in between the cleanup and
the close the pages actually get written to disk as paging i/o?
CLEANUP has nothing to do with memory mapped file. You can map it, close the handle (this causes CLEANUP), and then write to the mapping.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
Ok, so you are basically saying that once I see a section get created, I must look at paging writes to know if my file has been changed, and these may come before or after the cleanup on the file object for the handle that was used to create the section?
Matt
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Wednesday, November 09, 2011 4:41 PM
To: Windows File Systems Devs Interest List
Subject: Re:[ntfsd] memory mapped file detection logic
question? Or might I see the section get created, the cleanup, and
then in between the cleanup and the close the pages actually get written to disk as paging i/o?
CLEANUP has nothing to do with memory mapped file. You can map it, close the handle (this causes CLEANUP), and then write to the mapping.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
NTFSD is sponsored by OSR
For our schedule of debugging and file system seminars 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
Yes, and in fact the paging writes might not even tell you whether the file has changed, they’ll simply tell you that the pages are marked dirty. In other words, if there is a mapping and nothing gets written but some of the pages are marked dirty you’ll still see paging writes.
As far as i know you can’t always know at IRP_MJ_CLEANUP if the mapped view has changed.
What are you trying to do ?
Thanks,
Alex.
Thanks Alex. At a high level, I’m trying to “know” if a file was changed or not, and then tell some other component. I believe I’m familiar with how to do this outside of the memory mapped case. In the memory mapped case at this point, it seems at best I can realize whether something got memory mapped or not, and then just assume that it’s dirty. I guess my overall question is, is it possible to do better than this and know specifically whether a file has been written to or changed by a memory mapping, and if so, how would you go about it.
Thanks,
Matt
It’s also possible that the file has not changed at then time you’re processing the IRP_MJ_CLEANUP but that it changes after that. So even if you could reliably tell at IRP_MJ_CLEANUP that no application wrote anything in the mapped view that does not necessarily mean that the file won’t be modified.
Thanks,
Alex.
On 11/9/2011 4:17 PM, xxxxx@gmail.com wrote:
It’s also possible that the file has not changed at then time you’re processing the IRP_MJ_CLEANUP but that it changes after that. So even if you could reliably tell at IRP_MJ_CLEANUP that no application wrote anything in the mapped view that does not necessarily mean that the file won’t be modified.
Just to clarify and tie back to what Max said, you can open a file,
memory map it, close the file and you will get the cleanup in the
filter. Now the user mode app still has a handle to the memory mapped
section and can perform memory mapped IO on that view, long after the
actual backing file handle has been closed.
Throw into the mix where you have an active ‘normal’, cached writer …
now you could have paging sent down and you have no idea if the paging
was initiated due to a ‘normal’ cached write to the file or through a
memory mapped IO. Of course you can track top level writes but even then
there are some cases where it is difficult to determine anything with
certainty.
And finally, you will only be called for the section create the first
time the section is created, once the section is created the callback is
not made for further mappings of that section. Of course this has been
around for some time and it may have changed with later OS’s, post Vista.
Pete
Thanks,
Alex.
NTFSD is sponsored by OSR
For our schedule of debugging and file system seminars 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
–
Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295
>Ok, so you are basically saying that once I see a section get created, I must look at paging writes to
know if my file has been changed, and these may come before or after the cleanup on the file object
for the handle that was used to create the section?
Exactly.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
>> At a high level, I’m trying to “know” if a file was changed or not, and then tell some other component.
You want to pass this info when the application writes to the file using the API or mapped pointer? I doubt that would be possible at all considering its just a memory write from application perspective. MM later in its modified page processing will generates a paging IO. But this paging IO does not guaranty that the contents are changed(it just meant that the modified bit is set). I recently encountered a same case.
If it is about notifying ASAP than you may also look at the callback of “acquire for mod write”, this will be called before you receive the paging write in case of modified mapped pages. Though again as said “it does not necessarily meant that the contents are changed”; but see if it suits you.
I believe that the specs for memory-mapped files include a discussion of
“coherency”. If a file is mapped in the same operating system instance
more than once, changes are “coherent”, and any change made by one process
will be immediately visible (one memory cycle later) in all other
processes. However, coherence is explicitly NOT guaranteed with respect
to mappings made in other OS instances (note: it used to be “on other
processors” but multicore systems and virtualization complicate the
description). Coherency with ReadFile and WriteFile is explicitly NOT
guaranteed, even if running on the same OS instance. It sounds as if the
OP is trying to solve a problem even Microsoft thought unsolvable (or at
least whose solution would be extremely complex and probably result in a
massive performance hit).
joe
>> At a high level, I’m trying to “know” if a file was changed or not, and
>> then tell some other component.
You want to pass this info when the application writes to the file using
the API or mapped pointer? I doubt that would be possible at all
considering its just a memory write from application perspective. MM later
in its modified page processing will generates a paging IO. But this
paging IO does not guaranty that the contents are changed(it just meant
that the modified bit is set). I recently encountered a same case.
If it is about notifying ASAP than you may also look at the callback of
“acquire for mod write”, this will be called before you receive the paging
write in case of modified mapped pages. Though again as said “it does not
necessarily meant that the contents are changed”; but see if it suits you.
NTFSD is sponsored by OSR
For our schedule of debugging and file system seminars 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
> description). Coherency with ReadFile and WriteFile is explicitly NOT
guaranteed, even if running on the same OS instance.
According to the docs - yes.
According to the real implementation - lack of coherency only occurs with noncached reads/writes racing with memory-mapped file stuff. In this case, and only in this case.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
“Maxim S. Shatskih” wrote in message news:xxxxx@ntfsd…
According to the real implementation - lack of coherency only occurs with
noncached reads/writes racing with memory-mapped file stuff.
Hence the addition of CcCoherencyFlushAndPurgeCache, which will try to push
the dirty bits from user mapped views into the PFNs before flushing.
However, not all FSDs call it (FAT doesn’t, for example), so there’s still
no real general guarantee that I’m aware of.
-scott
–
Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com
Thank you, that is useful information.
joe
> description). Coherency with ReadFile and WriteFile is explicitly NOT
> guaranteed, even if running on the same OS instance.
According to the docs - yes.
According to the real implementation - lack of coherency only occurs with
noncached reads/writes racing with memory-mapped file stuff. In this case,
and only in this case.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com
NTFSD is sponsored by OSR
For our schedule of debugging and file system seminars 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 it is about notifying ASAP than you may also look at the callback of “acquire for mod write”, this will be called before you receive the paging write in case of modified mapped
pages. Though again as said “it does not necessarily meant that the contents are changed”; but see if it suits you.
Ok, does this mean then, that the Pre/PostReleaseForModifiedPageWriter callback will be called after these paging writes? I realize that paging can constantly be getting dirty again.
Thanks,
Matt
“Matthew White” wrote in message news:xxxxx@ntfsd…
Ok, does this mean then, that the Pre/PostReleaseForModifiedPageWriter
callback will be called after these paging writes? I realize that paging
can >constantly be getting dirty again.
Right, the pre-callback is called before a paging write to the file and the
post callback is called when the paging write completes. As you note you can
see multiple invocations of this as the mappings are dirtied and written out
over time.
Given your initial requirements, this might not buy you much over just
looking for the paging writes, but it’s something you could explore.
-scott
–
Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com
“Matthew White” wrote in message news:xxxxx@ntfsd…
If it is about notifying ASAP than you may also look at the callback of
“acquire for mod write”, this will be called before you receive the paging
write in case of modified mapped
pages. Though again as said “it does not necessarily meant that the
contents are changed”; but see if it suits you.
Ok, does this mean then, that the Pre/PostReleaseForModifiedPageWriter
callback will be called after these paging writes? I realize that paging
can constantly be getting dirty again.
Thanks,
Matt
@Scott
I guess you meant to say that Acquire callbacks will be called before the paging write and release callback after paging write. right?
Pre and post simply meant before the lower layer has given an opportunity to handle this callback; and after the lower layer has handled it.(The call can be completed as well; in which case MM will not involve the lower layer)
>I guess you meant to say that Acquire callbacks will be called before the
paging write and release callback after paging write. right?
Yes. Is that not what I said?
“…the pre-callback is called before a paging write to the file and the
post callback is called when the paging write completes.”
And, yes, there would be conditions where you would see the pre-acquire but
not see a write, such as some edge conditions inside the Mm as well as lower
filters failing the operation. This again adds to the question of whether
this callback is helpful to Matt or not.
-scott
–
Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com
wrote in message news:xxxxx@ntfsd…
@Scott
I guess you meant to say that Acquire callbacks will be called before the
paging write and release callback after paging write. right?
Pre and post simply meant before the lower layer has given an opportunity to
handle this callback; and after the lower layer has handled it.(The call can
be completed as well; in which case MM will not involve the lower layer)
Just to clear this up based on an offline conversation with Aditya…
The pattern you will see is obviously:
* PreAcquireForModifiedPageWriter
* PostAcquireForModifiedPageWriter
* PreReleaseForModifiedPageWriter
* PostReleaseForModifiedPageWriter
Confusion added here was mine for applying pre/post terminology to the
ordering of the callbacks relative to the I/O.
-scott
–
Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com
On 11/10/2011 06:02 AM, Scott Noone wrote:
“Maxim S. Shatskih” wrote in message news:xxxxx@ntfsd…
> According to the real implementation - lack of coherency only occurs
> with noncached reads/writes racing with memory-mapped file stuff.
Hence the addition of CcCoherencyFlushAndPurgeCache, which will try to
push the dirty bits from user mapped views into the PFNs before
flushing. However, not all FSDs call it (FAT doesn’t, for example), so
there’s still no real general guarantee that I’m aware of.
Key word is “try.” There are still no guarantees even when this
function is called, because pages may be locked that prevent the purge
from succeeding.
I have a related question. I am trying to do something similar to what Matthew (who started this thread) is trying to accomplish. I have found that if I call FltFlushBuffers() in the pre-processing callback for IRP_MJ_CLEANUP, all the dirty pages of a file mapping that are in memory at that time will be flushed and that this is a synchronous operation. I realize that the file mapping can still be modified but, when the IRP_MJ_CLOSE and ContextCleanup callbacks are invoked for that file object, is it then certain that all changes to the file mapping have been written to the disk?
Thanks,
David