230 likes | 737 Views
Processing IO Operations. In the IRP world…. In your dispatch (pre-operation) routine you can: Pass through the operation with no completion Do not care about this operation Do not need to see the final status of this operation Pend an operation
E N D
Processing IO Operations © 2004 Microsoft Corporation. All rights reserved.
In the IRP world… • In your dispatch (pre-operation) routine you can: • Pass through the operation with no completion • Do not care about this operation • Do not need to see the final status of this operation • Pend an operation • Will call IoCallDriver()/IoCompleteRequest() from a worker thread sometime later • Pass through the operation, setting a completion • Need to see the final status of the operation • Synchronize the operation • Allows post-operation processing to be done in the context of the same thread that the dispatch routine was called – safe IRQL, maintain your local variable state • Complete the operation © 2004 Microsoft Corporation. All rights reserved.
In the IRP world… • In your completion (post-operation) routine you can: • Do completion work directly in completion routine • All the post-operation work can be done at DPC-level • Do completion work at safe IRQL • Queue to a worker thread to allow processing at safe IRQL, call IoCompleteRequest() to continue completion processing • Synchronize back to dispatch by signaling event • Dispatch routine is waiting and will pick up doing the post-operation work in the context of the dispatch routine thread, call IoCompleteRequest() when done • Cancel a successful CREATE operation © 2004 Microsoft Corporation. All rights reserved.
In the Filter Manager world… • Still have same flexibility but is mainly controlled by the value returned in preOperation completion • No longer need code that does IRP maintenance • Copying parameters to next stack location • Propagating pending flag © 2004 Microsoft Corporation. All rights reserved.
PreOperation Callback Return Values • FLT_PREOP_SUCCESS_NO_CALLBACK • PostOperation callback will not be called for this operation • FLT_PREOP_SUCCESS_WITH_CALLBACK • PostOperation callback will be called for this operation • Not valid to return if no postOperation callback was registered for this operation • FLT_PREOP_PENDING • Operation will be pended • Filter must complete or continue processing this IO sometime in the future © 2004 Microsoft Corporation. All rights reserved.
PreOperation Callback Return Values (cont) • FLT_PREOP_SYNCHRONIZE • PostOperation callback will be called in the context of the current thread at safe IRQL • IRP_MJ_CREATE operations are always synchronized • Do not synchronize asynchronous read/write operations • Will destroy the performance of the system • FLT_PREOP_COMPLETE • Filter completed this operation • FLT_CALLBACK_DATA.IoStatus will be returned as the final status for operation • FLT_PREOP_DISALLOW_FASTIO • FAST_IO will be failed – IO Manager may reissue request via IRP path • Can only be returned for operations that map to FAST_IO calls (FLTFL_CALLBACK_DATA_FAST_IO_OPERATION will be set in FLT_CALLBACK_DATA.Flags) © 2004 Microsoft Corporation. All rights reserved.
Retrieving operation status • For some operations it is important to retrieve the operation status returned by IoCallDriver() • Needed to know if an oplock was granted or not • FltRequestOperationStatusCallback() • Specifies a callback routine to be called when the operation status is returned (return value of IoCallDriver()) • Properly synchronized with unload • Handles operation being completed by a lower minifilter/legacy filter • As in the legacy model, may be called after the operation has completed © 2004 Microsoft Corporation. All rights reserved.
PostOperation Callback Return Values • FLT_POSTOP_FINISHED_PROCESSING • Finished with post-operation processing • Can continue with higher filter/IO Manager post-operation processing • FLT_POSTOP_MORE_PROCESSING_REQUIRED • Have queued completion work to a worker thread • Filter must continue completion processing on this IO at a later time • Note: PostOperation callbacks may be called at DPC level like completion routines • To cancel a CREATE operation: • Call FltCancelFileOpen() • IoCancelFileOpen() bug has been fixed • Return failure status through callback data © 2004 Microsoft Corporation. All rights reserved.
Pending IO in PreOperation Callback • FltCompletePendedPreOperation() • Must call this to restart processing of IO pended in the preOperation callback • Filter may: • Complete operation • Request postOperation callback through the FLT_PREOP_CALLBACK_STATUS parameter • Typically called from a worker thread © 2004 Microsoft Corporation. All rights reserved.
Pending IO in PreOperation Callback (cont) • FltQueueDeferredIoWorkItem() • Queue operation to worker thread for continued processing • Can fail if this operation is not safe to post – i.e., this is paging IO or top-level IRP is already set on this thread • Can fail if this Instance is in the process of being torndown © 2004 Microsoft Corporation. All rights reserved.
Pending IO in PostOperation Callback • FltDoCompletionProcessingWhenSafe() • Can fail if it is not safe to post • Not safe to post Paging IO’s • Synchronize operation if you cannot handle this failure • Tells filter the appropriate postOperation callback status to return • Will only post operation if currently at DPC IRQL • Will continue completion processing when WorkerRoutine has completed © 2004 Microsoft Corporation. All rights reserved.
Pending IO in PostOperation Callback (cont) • FltQueueDeferredIoWorkItem() • Works just like in preOperation • Will always queue work to worker thread if it is safe to do so • If successfully queues work, return FLT_POSTOP_MORE_PROCESSING_REQUIRED • FltCompletePendedPostOperation() • Must call this to restart processing of IO pended in the postOperation callback © 2004 Microsoft Corporation. All rights reserved.
Queuing Mechanisms • Generic queuing support • Deferred IO queuing support • Cancel safe queuing support © 2004 Microsoft Corporation. All rights reserved.
Generic Queuing Support • FltAllocateGenericWorkItem() • Allocates a generic work item • FltQueueGenericWorkItem() • Queues a generic work item • Associated with an Instance or Filter object • FltFreeGenericWorkItem() • Frees a generic work item © 2004 Microsoft Corporation. All rights reserved.
Generic Queuing Support (cont) • Work just like ExXxxWorkItem() routines • Can reuse work items • Filter is responsible for allocation and freeing • The Instance/Filter will not finish unloading while outstanding work items are still being processed © 2004 Microsoft Corporation. All rights reserved.
Deferred IO Queue Support • FltAllocateDeferredIoWorkItem() • Allocates deferred IO work item • FltQueueDeferredIoWorkItem() • Queues deferred IO work item • This can fail if operation cannot be pended • FltFreeDeferredIoWorkItem() • Frees deferred IO work item © 2004 Microsoft Corporation. All rights reserved.
Deferred IO Queue Support (cont) • Filter is responsible for allocation and freeing of deferred IO work item • Deferred IO work item can be reused • Instance cannot go away while there are outstanding deferred IO work items being processed © 2004 Microsoft Corporation. All rights reserved.
Cancel Safe Queuing Support • FltCbdqInitialize() • Initializes the cancel safe queue • FltCbdqInsertIo() • Inserts a FLT_CALLBACK_DATA into the queue • FltCbdqRemoveIo() • Removes a given FLT_CALLBACK_DATA from the queue • FltCbdqRemoveNextIo() • Removes the next FLT_CALLBACK_DATA that meets the peek criteria from the queue • FltCbdqDisable() • Disables insertion of new IOs to the queue • Used to allow the queue to be drained when an Instance is being torn down © 2004 Microsoft Corporation. All rights reserved.
Cancel Safe Queuing Support • FltCbdqEnable() • Enables new IOs to be added to the queue • Once the queue is initialized, it is enabled by default • Used only when pending preOperation callbacks • Provides cancel logic for filters that need to maintain a queue of outstanding IOs to service • Equivalent functionality to IoCsqXxx() provided for IRPs • Filter is responsible for disabling and draining queue on InstanceTeardownStart() © 2004 Microsoft Corporation. All rights reserved.
Cancel Support • FltSetCancelCompletion() • Allows setting of cancel routine for a given FLT_CALLBACK_DATA • FltClearCancelCompletion() • Allows clearing of the cancel routine for a given FLT_CALLBACK_DATA • FltIsIoCanceled() • Returns TRUE if the current operation has been canceled © 2004 Microsoft Corporation. All rights reserved.
Cancel Support (cont) • Equivalent to IoSetCancelRoutine() for IRPs (read documentation) • Filter is responsible for locking to make sure set/clear/cancel is properly synchronized • Can be used to implement your own cancellation logic • It is recommended that you use cancel safe queues © 2004 Microsoft Corporation. All rights reserved.
Oplock Support • FltInitializeOplock() • FltUninitializeOplock() • FltOplockFsctrl() • FltCheckOplock() • FltOplockIsFastIoPossible() • FltCurrentBatchOplock() • Internally extracts IRP from Callback Data and calls equivalent FSRTL routines © 2004 Microsoft Corporation. All rights reserved.
Byte Range Lock Support • FltInitializeFileLock() • FltUninitializeFileLock() • FltAllocateFileLock() • FltFreeFileLock() • FltProcessFileLock() • FltCheckLockForReadAccess() • FltCheckLockForWriteAccess() • Use in conjunction with existing FsRtl routines • Internally extracts IRP from Callback Data and calls equivalent FSRTL routines © 2004 Microsoft Corporation. All rights reserved.