At a customer site that has been experiencing a certain problem for over one year (!), I have narrowed down the problem.
Scenario is:
A series of normal writes to a file opened with buffering occur.
IRP_MJ_CLEANUP occurs.
File is re-opened as read only, still with buffering, before the IRP_MJ_CLOSE.
FASTIO_ACQUIRE_FOR_CC_FLUSH/FASTIO_RELEASE_FOR_CC_FLUSH occur together with NO intervening paging writes or writes of any sort to that file between that acquire and release, that is seen in procmon.
Then a direct non-cached read occurs. That read is satisfied with still no paging writes. From cache?
It is an infrequent problem. Mostly the paging writes occur first so direct read is satisfied from disk. But occasionally we see the above with no paging writes, or not a complete coverage of paging writes to cover the latest normal writes to cached data. A Digital guardian dgfsmon.sys is in the stack…not sure if that’s related.
So question: Is it possible for the FS to satisfy that direct read on a file opened as read only and buffering from the cache? Or is the cached data being persisted to disk somehow without any paging IO, at least none seen in procmon?
NTFS will certainly do this - I’ve seen it (recently). It detects the case where the data is in the cache and satisfies it from the cache, not the disk. It’s not wrong (as far as NTFS is concerned) and eliminates the need to do I/O to retrieve data from disk that’s already in memory.
Thanks for that confirmation Tony! You and OSR are the best!
I’m trying to reproduce it now…if any tips that would be great.
Particular OS version, high stress scenario, etc…
You can do that I believe. I saw it in the customer’s procmon.
To try to reproduce, in the FltCreateFile that I call from my driver I pass in only FILE_ATTRIBUTE_NORMAL as the attributes parameter so buffered IO and then just GENERIC_READ as the desired access. I then call FltReadFile passing in FLTFL_IO_OPERATION_NON_CACHED in the flags argument.
Customer’s procmon create and read (without path/filename to protect anonymity):
IRP_MJ_CREATE …Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, AllocationSize: n/a, OpenResult: Opened
IRP_MJ_READ…Offset: 0, Length: 1,024, I/O Flags: Non-cached, Priority: Normal
" NTFS will certainly do this - I’ve seen it (recently). It detects the case
where the data is in the cache and satisfies it from the cache, not the disk.
It’s not wrong (as far as NTFS is concerned) and eliminates the need to do I/O
to retrieve data from disk that’s already in memory. "
Tony if this is true, then do we get any indication that the request is being satisfied from the cache not disk? Because if we are writing a encryption driver it will cause a huge data corruption problem. Isn’t it?
As per my understanding, if application issues a direct (non-cached) IO read, we should expect a paging write ONLY IF DATA is dirty in cache? If its a non-cached IO then this request will be satisfied from the disk. But it seems from your comment that may not be true. It may get satisfied from the cache?
No indication that this is the case. As for encryption, you should never be dependent upon the NTFS cache in an encryption driver in any case - that’s certainly why we use Isolation - our data, our cache, our control. Trying to do anything around the underlying FS behavior is always dangerous.
My previous comment was about a non-cached read being satisfied from the cache in a very specific case that we had observed. I wouldn’t generalize from that, but in at least one observed case, yes, it did certainly appear that the non-cached read was satisfied without performing any additional I/O.