Forcing the Cache Manager to release its reference to a File Object

I’ve run up against a brick wall, and am hoping someone here can give me some advice. You know that File Object that the Cache Manager (not sure if that is technically accurate) latches onto to use for internal file management, caching, etc.? I need that to go away for a specified file that has no other open handles to it. I believe what I am looking to do is to evict that file from cache so that Cc will release the file object.

I need to do this for two reasons:

One is that the information in the stream context is out of date. I don’t want to have to make marks on the wall to try to catch stream context for file X and then add locking to perform the update. I’d like to just have it go away, and the next time the file is accessed, start anew, peacefully, in PostCreate.

The other is that I process the data as it is read into the cache, and I need to redo that processing for the file based on new configuration.

I thought I had found the answer in CcCoherencyFlushAndPurgeCache(). Based on the documentation, I thought that I could invoke one of the Acquire For IRPs to acquire the file, and then call this function. But I have read through many an old post here and the advice is always the same, “Thou Shalt Not Call Cc functions for objects that you don’t own.”

So that is my rock. What advice do you have Mr. Hard Place? :confused:

I cannot remember your use case. Is this the ZFS port? If so then you own the cache and it suffices to call CcCoherencyFlushAndPurgeCache

Good luck working out what locks you need. You need to interlock against CcInitializeCacheMapand CcUninitializeCacheMap but not interlock against paging writes.

If you are in cleanup you might be able toset the length to zero in CcUninitializeCacheMap But beware of waiting for the event because it occassionaly won’t fire (which is I suspect why FAT didn’t use it the last time I looked).

If you are a filter then you do not own the cache and so this is the standard reply
:

In general you cannot. What are you going to do if the user has sections mapped?

But you may get some mileage with the IRP_MJ_FLUSH IRP_MN_FLUSH_AND_PURGE combo.

What you MUST NOT DO (unless you own the cache) is what people often crop up and say “just call such and such a Cc Function” - those calls are reserved for people who are managing the cache.

I’m the latter, a filter. I will test the IRP_MJ_FLUSH IRP_MN_FLUSH_AND_PURGE combo you mentioned and see if that gets at least some of what I need.

Thanks again, Rod!

Rod, I see that I can use FltFlushBuffers() to send IRP_MJ_FLUSH from a minifilter. Any idea how to generate this IRP using IRP_MN_FLUSH_AND_PURGE?

You’ll probably need to do it by hand, using FltAllocateCaabackData and FltPerformSynchrousIo. There should be examples in the archive

Perfect! Thanks.

@rod_widdowson This worked perfectly. Thanks for your advice.

_PFLT_CALLBACK_DATA data;
FltAllocateCallbackData(_fltInstance, fileObject, &data);
data->Iopb->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
data->Iopb->MinorFunction = IRP_MN_FLUSH_AND_PURGE;
FltPerformSynchronousIo(data);
NTSTATUS status = data->IoStatus.Status;
FltFreeCallbackData(data);
return status;