CcInitializeCacheMap and PinAccess argument

Hi all,

Yesterday I got my file system to support cached read and write for the
first time. I was able to open a text file with notepad, edit, and save it
correctly. Today, while looking at the code that handles the CREATE IRP, I
noticed that I was passing TRUE to the PinAccess argument of
CcInitializeCacheMap(). Since I was not calling any of the CcPinXXX
functions, I changed this to FALSE.

After doing this, the lazy writer would call my AcquireFCBForLazyWrite()
callback with an FCB *after* I had received all CLOSE IRPs for all file
objects associated with that FCB. That obviously caused an access violation
in my code. When I set the PinAccess argument back to TRUE, this does not
happen anymore.

Can anyone explain what is going on? Thanks.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

Where do you call CcUninitalizeCacheMap?

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

Looking forward to seeing you at the next OSR File Systems class in
Boston, MA April 24-27, 2006.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Roger Tawa
Sent: Wednesday, January 18, 2006 6:58 PM
To: ntfsd redirect
Subject: [ntfsd] CcInitializeCacheMap and PinAccess argument

Hi all,

Yesterday I got my file system to support cached read and write for the
first time. I was able to open a text file with notepad, edit, and save
it
correctly. Today, while looking at the code that handles the CREATE
IRP, I
noticed that I was passing TRUE to the PinAccess argument of
CcInitializeCacheMap(). Since I was not calling any of the CcPinXXX
functions, I changed this to FALSE.

After doing this, the lazy writer would call my AcquireFCBForLazyWrite()
callback with an FCB *after* I had received all CLOSE IRPs for all file
objects associated with that FCB. That obviously caused an access
violation
in my code. When I set the PinAccess argument back to TRUE, this does
not
happen anymore.

Can anyone explain what is going on? Thanks.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Hi Tony,

Where do you call CcUninitalizeCacheMap?

First, I call CcInitializeCacheMap() when handling CREATE. I call it
only when FO_NO_INTERMEDIATE_BUFFERING is not specified.

I call CcUninitializeCacheMap(fileobj,0,0) in CLEANUP. I call it
unconditionally for all file objects, whether I called
CcInitializeCacheMap() or not. Additionally in CLEANUP, if this is
the last file object for this FCB, and the FCB is marked for
delete-on-close, I call CcPurgeCacheSection(sop,0,0,TRUE) *before*
calling CcUninitializeCacheMap().

Finally, in CLOSE, if this is the last file object for this FCB, I
free the memory allocated for the FCB. I also set the FsContext field
in the file object to null.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

If you are getting calls after close, there is something interfering
with normal dereference operation. This can happen (for example) with
interactions between file system filter drivers. I also had a case
where someone (above the FSD) was receiving the IRP_MJ_CLEANUP and then
bumping and dropping the reference count - the drop triggered a call to
IRP_MJ_CLOSE before the IRP_MJ_CLEANUP was called.

While the latter case is not terribly likely, you can test for it - in
your IRP_MJ_CLEANUP handler make sure that you set FO_CLEANUP_COMPLETE.
Then in IRP_MJ_CLOSE you can test that this bit is set (if it isn’t you
have an out-of-order close.)

Another case I’ve seen (now that I’m thinking about it) is that if you
are calling CcPurgeCache this can cause the IRP_MJ_CLOSE to arrive
before you have completed the IRP_MJ_CLEANUP processing. But this
probably doesn’t match very well either (although note that the purge
may trigger a CLOSE operation on a different file object than the
CLEANUP on which you are currently operating.)

What you have is most likely a reference count bug - you think the
reference on your FCB is zero when in fact it is not. Were I debugging
this problem I’d be looking at the file object the cache manager is
passing in to you - and then walking back through your logs (you ARE
using WPP tracing, so you can easily look at this information, right?)
and find where you think this file object went away - because it didn’t.

Also, another suggestion: defer calling CcInitializeCacheMap until the
first read. While not *required* for correct behavior, many open calls
never do I/O to the file, and setting up and tearing down the cache map
is a relatively expensive operation, particularly when you aren’t going
to use it (not necessary, but merely an observation on efficient
implementation tricks.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

Looking forward to seeing you at the next OSR File Systems class in
Boston, MA April 24-27, 2006.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Roger Tawa
Sent: Wednesday, January 18, 2006 9:00 PM
To: ntfsd redirect
Subject: Re: [ntfsd] CcInitializeCacheMap and PinAccess argument

Hi Tony,

Where do you call CcUninitalizeCacheMap?

First, I call CcInitializeCacheMap() when handling CREATE. I call it
only when FO_NO_INTERMEDIATE_BUFFERING is not specified.

I call CcUninitializeCacheMap(fileobj,0,0) in CLEANUP. I call it
unconditionally for all file objects, whether I called
CcInitializeCacheMap() or not. Additionally in CLEANUP, if this is
the last file object for this FCB, and the FCB is marked for
delete-on-close, I call CcPurgeCacheSection(sop,0,0,TRUE) *before*
calling CcUninitializeCacheMap().

Finally, in CLOSE, if this is the last file object for this FCB, I
free the memory allocated for the FCB. I also set the FsContext field
in the file object to null.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: unknown lmsubst tag argument:
‘’
To unsubscribe send a blank email to xxxxx@lists.osr.com

Thanks for all the tips Tony, I will try them out.

I am testing on a machine with a checked build of XP SP2, with nothing
much installed except the DDK and vc.net 2003. I don’t think there is
a filter involved, but I’ll double check anyway. FYI, I am writing an
FSD, not a filter.

I am calling CcPurgeCacheSection() during CLEANUP, but only when
delete-on-close is set. But I see this problem for non
delete-on-close files. BTW, in the case of delete-on-close, I return
STATUS_PENDING for the CLEANUP IRP, and complete it in the background.
Shouldn’t be a problem right?

I suspect your are correct: there is a bug in my FCB ref counting.

No I’m not using WPP tracing (blush), only DbgPrint(). But I am
dumping a full trace of the IRPs as they go by, so I can go back in my
logs and see what is happened. See below for a stripped down version
of the trace that leads to the crash. This is a very simple case,
repro’able 100% of the time. Only one file object is involved.

I will take a look at WPP though, because DbgPrint() is soooo slooooowww…

Thanks again.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

oops, forgot to include the trace:

-------start debug trace-------
PIFSK:CREATE 0x862acf68 “\wri.txt” [cmd.exe] Thread=3D0x85787020
PIFSK: FO: 0xf3c96cb4
PIFSK:Initializing FCB 0x86092e90
PIFSK: Got FCB=3D0x86092e90 Refs=3D1
PIFSK:CREATE 0x862acf68 COMPLETED Status=3D0x00000000(STATUS_SUCCESS)
Info=3D0x00000001(1)

PIFSK:QUERY_INFORMATION 0x8664ef68 “\wri.txt” [cmd.exe] Thread=3D0x85787020
PIFSK: FO: 0xf3c96cb4
PIFSK: FCB: 0x86092e90
PIFSK:QUERY_INFORMATION 0x8664ef68 COMPLETED
Status=3D0x00000000(STATUS_SUCCESS) Info=3D0x00000028(40)

PIFSK:CLEANUP 0x86012f68 “\wri.txt” [cmd.exe] Thread=3D0x85787020
PIFSK: FO: 0xf3c96cb4
PIFSK: FCB: 0x86092e90
PIFSK:CLEANUP 0x86012f68 COMPLETED Status=3D0x00000000(STATUS_SUCCESS)
Info=3D0x00000000(0)

PIFSK:CLOSE 0x869e4f68 “\wri.txt” [cmd.exe] Thread=3D0x85787020
PIFSK: FO: 0xf3c96cb4
PIFSK: FCB: 0x86092e90
PIFSK:Tearing down FCB 0x86092e90
PIFSK:CLOSE 0x869e4f68 COMPLETED Status=3D0x00000000(STATUS_SUCCESS)
Info=3D0x00000000(0)

PIFSK:CREATE 0x865e8f68 “\wri.txt” [cmd.exe] Thread=3D0x85787020
PIFSK: FO: 0x85c85190

PIFSK:PifsAcquireFCBForLazyWrite FCB=3D0x86092e90 Thread=3D0x85e48020

*** Fatal System Error: 0x000000d5
(0x86092E98,0x00000000,0xF3229060,0x00000000)

Driver at fault:
*** Pifsk.SYS - Address F3229060 base at F3226000, DateStamp 43ce9e89
.
-------end debug trace-------

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]

Hi Tony,

Finally got around to checking everything.

No filters installed on my test system. I set the FO_CLEANUP_COMPLETE
in my CLEANUP, and assert for it in my CLOSE; I have not triggered it
yet…

As you guessed, I did have a ref counting problem with my FCB. Thanks
for the help.

=================================================
Roger Tawa
http://tawacentral.net/
[One thing about paradigms: shift happens.]
[When you stop, you’re done.]