FltAllocateCallbackdata etc. in paging I/O Path

Can we use FltAllocateCallbackdata() and FltBuildSynchronousFsdRequest() or
FltBuildAsynchronousFsdRequest() in the paging write path?
Basically i want to use this for 2 things:

  1. Copy the contents of the buffer ( page ) to another file ( which i am
    keeping for logging purpose).
  2. Increase the size of the file for which i got the write request

Are 1. and 2. possible (safe)?
I know that one can not issue file system calls in a paging i/o path using
FltWriteFile, etc…
But is the use of FltAllocateCallbackdata() and
FltBuildSynchronousFsdRequest() or FltBuildAsynchronousFsdRequest() safe?
What are the other alternatives?

Thanks!

First of all, ask yourself a question why you cannot use FltWriteFile() and friends while processing paging IO, and, at this point, you will realize what can and what cannot be done here…

When you process paging IO (IRP_PAGING_IO flag is set) and FsRtlIsPagingFile() returns false, although you can take page faults on data, you cannot take them on code, for understandable reasons - otherwise, you will get into an infinite recursion. When you process paging IO and FsRtlIsPagingFile() returns true (i.e. the target file is paging one), you cannot page fault on either code or data, for obvious reasons. All functions that you have mentioned are callable only at
IRQL< DISPATCH_LEVEL, which means they potentially may page-fault even on code, and, hence, cannot be used while processing paging IO.

At this point the solution becomes obvious - once you cannot cause page faults at IRQL>=DISPATCH_LEVEL, you should use only those functions that are callable at elevated IRQL while processing paging IO. Fltxxx and Zwxxx functions, as well as IoBuildDeviceIoControlRequest() and IoBuildAsynchronousFsdRequest(), are not among them. Therefore, the only option left is IoAllocateIrp()-IoCallDriver() sequence…

Anton Bassov

Thanks Anton!
I am implementing a minifilter.
The documentation for FltPerformAsynchronousIo says :
“The caller of FltPerformAsynchronousIo can be running at IRQL <= APC_LEVEL
if the IRP_PAGING_IO flag is set in the IrpFlags member of the
FLT_IO_PARAMETER_BLOCK structure for the operation. (This flag is only valid
for IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_QUERY_INFORMATION, and
IRP_MJ_SET_INFORMATION operations.) Otherwise, the caller must be running at
IRQL PASSIVE_LEVEL.”

This means that we can use this function in the paging i/o path also.
However, the documentation for FltAllocateCallbackdata just says that it can
be used when IRQL <=APC_LEVEL and does not say anything in particular for
paging i/o.
Since, FltPerformASynchronousIo can be used, it can be assumed that
FltAllocateCallbackdata should also work.

So in this situation, are the following operations legal:
PreWrite() {
FltAllocateCallbackdata()
FltPerformAsynchronousIo(…,CallbackRoutine,…)
KeWaitForSingleObject(event,INFINITE TIME);
}

Callback(){
KeSetEvent(event);
}

Will the above work?
Any special conditions that i should look out for?

----- Original Message -----
From:
To: “Windows File Systems Devs Interest List”
Sent: Monday, July 23, 2007 10:19 AM
Subject: RE:[ntfsd] FltAllocateCallbackdata etc. in paging I/O Path

> First of all, ask yourself a question why you cannot use FltWriteFile()
> and friends while processing paging IO, and, at this point, you will
> realize what can and what cannot be done here…
>
> When you process paging IO (IRP_PAGING_IO flag is set) and
> FsRtlIsPagingFile() returns false, although you can take page faults on
> data, you cannot take them on code, for understandable reasons -
> otherwise, you will get into an infinite recursion. When you process
> paging IO and FsRtlIsPagingFile() returns true (i.e. the target file is
> paging one), you cannot page fault on either code or data, for obvious
> reasons. All functions that you have mentioned are callable only at
> IRQL< DISPATCH_LEVEL, which means they potentially may page-fault even on
> code, and, hence, cannot be used while processing paging IO.
>
> At this point the solution becomes obvious - once you cannot cause page
> faults at IRQL>=DISPATCH_LEVEL, you should use only those functions that
> are callable at elevated IRQL while processing paging IO. Fltxxx and Zwxxx
> functions, as well as IoBuildDeviceIoControlRequest() and
> IoBuildAsynchronousFsdRequest(), are not among them. Therefore, the only
> option left is IoAllocateIrp()-IoCallDriver() sequence…
>
> Anton Bassov
>
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@yahoo.co.in
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

The doc states:

“Dispatch routines in the paging I/O path should never call IoCallDriver at
any IRQL above APC_LEVEL”

ms-help:

wrote news:xxxxx@ntfsd…
> First of all, ask yourself a question why you cannot use FltWriteFile()
> and friends while processing paging IO, and, at this point, you will
> realize what can and what cannot be done here…
>
> When you process paging IO (IRP_PAGING_IO flag is set) and
> FsRtlIsPagingFile() returns false, although you can take page faults on
> data, you cannot take them on code, for understandable reasons -
> otherwise, you will get into an infinite recursion. When you process
> paging IO and FsRtlIsPagingFile() returns true (i.e. the target file is
> paging one), you cannot page fault on either code or data, for obvious
> reasons. All functions that you have mentioned are callable only at
> IRQL< DISPATCH_LEVEL, which means they potentially may page-fault even on
> code, and, hence, cannot be used while processing paging IO.
>
> At this point the solution becomes obvious - once you cannot cause page
> faults at IRQL>=DISPATCH_LEVEL, you should use only those functions that
> are callable at elevated IRQL while processing paging IO. Fltxxx and Zwxxx
> functions, as well as IoBuildDeviceIoControlRequest() and
> IoBuildAsynchronousFsdRequest(), are not among them. Therefore, the only
> option left is IoAllocateIrp()-IoCallDriver() sequence…
>
> Anton Bassov
>
></ms-help:>

> The doc states:

“Dispatch routines in the paging I/O path should never call IoCallDriver at
any IRQL above APC_LEVEL”

Please note that no one here speaks about actually making a call at DPC level. What I speak about are routines that are *callable* at DPC level in whatever context - the very fact that a routine may be called at DPC level in some context means that all its code and all variables that it accesses reside in non-pageable memory, and, hence, this routine is just guaranteed not to cause page faults in its code (i.e. something that you cannot guarantee about a routine that cannot be called at elevated IRQL)…

Therefore, I use the fact that a routine is callable at DPC level simply as an indicator - no one suggests making a call itself at elevated IRQL…

Anton Bassov

> The documentation for FltPerformAsynchronousIo says :

“The caller of FltPerformAsynchronousIo can be running at IRQL <= APC_LEVEL
if the IRP_PAGING_IO flag is set in the IrpFlags member of the
FLT_IO_PARAMETER_BLOCK structure for the operation. (This flag is only valid
for IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_QUERY_INFORMATION, and
IRP_MJ_SET_INFORMATION operations.) Otherwise, the caller must be running at
IRQL PASSIVE_LEVEL.”

This means that we can use this function in the paging i/o path also.However, the documentation > for FltAllocateCallbackdata just says that it can be used when IRQL <=APC_LEVEL and
does not say anything in particular for paging i/o.

Basically, everything depends on the target file …

All the above applies only as long as we speak about a paging IO path to the “normal” file and not to the paging file itself. Indeed, the only calls that you should avoid while processing paging IO path to the “normal” file are those that has to be made strictly at PASSIVE_LEVEL (i.e. Zwxx routines and
FltCreateFile() and friends) - the ones that can be made at IRQL<=APC_LEVEL are OK.
However, when you process paging IO path to the paging file itself, you should avoid *any* function
that is not callable at DPC level.

Anton Bassov