The two sequences you describe are, in fact, two of several combinations you
would observe (under normal circumstances. It is possible that other
software, such as a file system filter driver, might modify this from the
normal behavior.)
Each time a section object is created, it refers to a specific file object.
A file object is created each time a user opens the file. The file object
references the section object pointers structure which, in turn, refers to
as many as two section objects.
ALL file object for the same file should reference the same section object
pointers structure. Thus, you have a one-to-one relationship for the
section object to the file object. You have a many-to-one relationship for
the file object to the section object pointers. Thus, the first sequence
you see:
IRP_MJ_CLEANUP
I/O from the VM system (not JUST the lazy writer)
IRP_MJ_CLOSE
is the sequence for a file that has been opened by a user (or created by the
FSD,) the section is created and points to THAT file object. The user then
closes the file, which generates the IRP_MJ_CLEANUP call. Subsequently you
may observe:
IRP_MJ_READ
IRP_MJ_WRITE
IRP_MJ_QUERY_INFORMATION
IRP_MJ_SET_INFORMATION
for that file. This is because there is activity from the VM system.
The second sequence you describe:
IRP_MJ_CLEANUP
IRP_MJ_CLOSE
would be consistent with a file object that was NOT used as the reference
for the section object and hence is not needed by the VM system.
Another sequence you might see is:
IRP_MJ_{READ,WRITE,{QUERY,SET}_INFORMATION}
IRP_MJ_CLOSE
This would be from an FSD (such as NTFS) that creates a file object
(IoCreateStreamFileObjectLite) that is then used to back a section object.
This sequence will occur in Windows 2000, but not in NT 4.0 (because this
call does not exist in NT 4.0.)
A subsequent developer suggested that you purge/flush the section. First,
the code would look something like:
if (SectionObjectPointers->ImageSectionObject) {
MmFlushImageSection(SectionObjectPointers->ImageSectionObject,
MmFlushForWrite);
}
if (SectionObjectPointers->DataSectionObject) {
CcFlushCache(SectionObjectPointers->DataSectionObject, 0, 0, NULL);
CcPurgeCacheSection(SectionObjectPointers->DataSectionObject, NULL, NULL,
TRUE);
}
Second, be aware that this will materially degrade the performance of the
system because you are now discarding the cache contents, so that a
subsequent fetch of the file data will require that you re-fetch it from
disk.
Third, be aware that these calls FAIL if the file is still in use. This
happens, for example, if the file is being memory mapped, which INCLUDES
execution and use by “notepad” (in Windows 2000.) Thus, flushing and
purging will not necessarily force the section to be closed. The other
reason this will fail is because there is synchronization contention.
Fourth, be advised that flushing/purging a section can cause an IRP_MJ_CLOSE
on a DIFFERENT file object to re-enter the storage stack. That’s fine so
long as you are prepared for it, but if you do not expect it, you run the
risk of adding deadlocks to the system.
An important thing to do is to ensure that using memory mapped files works
correctly. You can use Notepad in Windows 2000, although I recommend
writing a program that exercises the memory mapped interface. A GREAT trick
is to open a file, memory map it, close the file, and use the memory mapping
to modify the file contents. THAT is the case which causes the greatest
problem to most file systems and file system filter drivers.
I hope this helps.
Regards,
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
-----Original Message-----
From: xxxxx@itg.hitachi.co.jp [mailto:xxxxx@itg.hitachi.co.jp]
Sent: Wednesday, October 04, 2000 2:19 AM
To: File Systems Developers
Subject: [ntfsd] cleanup,close, and lazy writer
Sensitivity: Personal
Hi,
We are writing a file system filter driver for en/decryption.
Our filter resides above the FSD.
We are confused at the sequence of
IRP_MJ_CLEANUP, IRP_MJ_CLOSE and the lazy writer.
The key for the file encryption must be on memory while the file is opend
and the key must be erased when the file is closed.
We are at a loss to decide when to erase the key because the key is
needed by the lazy writer.
We saw the sequence of
1. IRP_MJ_CLEANUP
2. the lazy writer
3. IRP_MJ_CLOSE.
and also saw the sequence of
1. IRP_MJ_CLOSE
2. IRP_MJ_CLEANUP.
Are there any other kind of sequences?
Any help is greately appreciated.
Thanks in advance.
Takashi.