memory mapped file detection logic

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.

  • M

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

>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.

What is the advantage of this over waiting for the data to be written out by
the mapped page writer? Also, this does not work if the pattern the
application uses is:

OpenFile()
MapFile()
CloseFile()
**Dirty mapping**

Which is quite common.

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?

You can’t be sure that there won’t be any more changes via memory mapping
until the section goes away. For example, nothing prevents me from using two
different file objects to create writable data mappings to the file (i.e.
performing my steps above twice). The first file object will create and back
the data section and the second one will simply reference the existing data
section, so just because you see a close to *a* file object used for memory
mapping doesn’t mean there isn’t still a section out there (*).

Given that, as a filter it’s not really your business to know when the
section is deleted. You don’t have access to the necessary state to be able
to make that determination and the FS/Mm don’t provide you any way to get
that information. However, what you *do* know is when the last reference to
the stream (or file) goes away, by registering your StreamContext (or
FileContext) cleanup callback. When this is called you know that there are
no user or kernel references to the stream/file (including section
references) and therefore there won’t be any outstanding modifications.

Your other choice here is a layered FS, which is a LOT more work but might
provide more flexibility in the implementation. Depending on your
requirements though this might be the equivalent of using a shotgun as a fly
swatter :slight_smile:

-scott

*Note that it’s also possible for a file system to change the file object
that backs the section (see FsRtlChangeBackingFileObject), so, while
tempting, it’s dangerous to just say, “the section will be deleted after the
first file object goes away.” You also have a potential race in determining
what, “first” means, especially if you have filters beneath you (which can
muddy the waters even further here anyway).


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

Scott,

I think you answered my question fully but, just to be sure, this is what I understood.

If I use FltSetStreamContext() to attach a stream context to a file object in my filter instance and I specified a ContextCleanupCallback for stream contexts in my filter registration data, then when I receive the context cleanup callback for a given file object, I can be certain that all dirty pages associated with all mappings for that file have been written to disk.

Is that what you said?

Thanks for the guidance,
David

>when I receive the context cleanup callback for a given file object, I can

be certain that all dirty pages associated with all mappings for that file
have >been written to disk.

A couple of corrections:

“when I receive the context cleanup callback for a given *stream context*, I
can be certain that all dirty pages associated with all mappings for that
*stream* have been written to disk.”

The idea is that the stream context only goes away when there are no more
file objects to the stream, therefore there can’t be anymore I/O (until
someone opens the stream again, that is).

(Also, to be clear because I have yet to mention it, up until this point
we’ve only been discussing local files.)

-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 think you answered my question fully but, just to be sure, this is what I
understood.

If I use FltSetStreamContext() to attach a stream context to a file object
in my filter instance and I specified a ContextCleanupCallback for stream
contexts in my filter registration data, then when I receive the context
cleanup callback for a given file object, I can be certain that all dirty
pages associated with all mappings for that file have been written to disk.

Is that what you said?

Thanks for the guidance,
David

One thing to keep in mind is that the ContextCleanupCallback for stream
contexts on W2K8 might not occur for hours or even days after the memory
mapped section is closed. On W2K3 I have seen it take about 5 seconds.

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Wednesday, November 23, 2011 11:05 AM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] memory mapped file detection logic

Scott,

I think you answered my question fully but, just to be sure, this is what I
understood.

If I use FltSetStreamContext() to attach a stream context to a file object
in my filter instance and I specified a ContextCleanupCallback for stream
contexts in my filter registration data, then when I receive the context
cleanup callback for a given file object, I can be certain that all dirty
pages associated with all mappings for that file have been written to disk.

Is that what you said?

Thanks for the guidance,
David


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

Right, in the case of memory mapped or cached file it’s going to be delayed
until Mm/Cc tear down their structures and deref the backing file object.
Often this won’t happen until there’s memory pressure (why throw away a
perfectly good data structure if you don’t need to?).

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

“Bill Wandel” wrote in message news:xxxxx@ntfsd…

One thing to keep in mind is that the ContextCleanupCallback for stream
contexts on W2K8 might not occur for hours or even days after the memory
mapped section is closed. On W2K3 I have seen it take about 5 seconds.

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Wednesday, November 23, 2011 11:05 AM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] memory mapped file detection logic

Scott,

I think you answered my question fully but, just to be sure, this is what I
understood.

If I use FltSetStreamContext() to attach a stream context to a file object
in my filter instance and I specified a ContextCleanupCallback for stream
contexts in my filter registration data, then when I receive the context
cleanup callback for a given file object, I can be certain that all dirty
pages associated with all mappings for that file have been written to disk.

Is that what you said?

Thanks for the guidance,
David


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