Network Redirectors and the File System Process
Most of the file operations performed by a file system driver are usually completed in the user's thread context. These operations include all of the synchronous file I/O calls to the file system. In these cases, all of the work is done inline. The operation might block in the kernel, but the work is performed on the same thread. File systems on Windows often call this work using the user's thread context as the File System Dispatch (FSD). Most of the time, a file system will try to complete its work in the FSD.
There are some cases where an application does not want to block (asynchronous reads or asynchronous writes, for example). In these cases, the file I/O operation needs to be dispatched to a system worker thread for completion. File systems on Windows often call this work using a system worker thread context as the File System Process (FSP). The following example of an asynchronous IRP_MJ_WRITE request sent to a network mini-redirector illustrates a case where the FSP needs to be used.
To execute an asynchronous IRP_MJ_WRITE request, RDBSS or a network mini-redirector needs to acquire the file object's FCB resource (a synchronization object used for changing the file object). When the FCB resource is already held by another thread and RDBSS or the network mini-redirector try to acquire the FCB resource in the user's thread context (the FSD), this operation will block. Asynchronous requests to a file system are not supposed to block. For asynchronous requests (IRP_MJ_WRITE request, for example), a file system driver will first check if the needed resource is available (the FCB resource for a network mini-redirector, for example). If the resource is not available, then the file system driver posts the request to a work queue for later completion by a system worker thread (the FSP) and the file system returns STATUS_PENDING from the FSD thread. To the user application, the FSD will return STATUS_PENDING immediately, while the actual work will be handled by a system worker thread in the FSP.
Several tasks must be completed before a file system driver posts work to the FSP. The file system driver needs to capture the security context from the user's thread in the FSD since the work will be completed by a system worker thread. RDBSS does this automatically in the RxFsdPostRequest routine for network mini-redirectors. This routine is called by RDBSS whenever a network mini-redirector returns STATUS_PENDING with the PostRequest member of the RX_CONTEXT structure set to TRUE. If work is posted to a work queue, the file system driver must also make sure that the user buffers will be available for later use by the system worker thread. There are two methods to accomplish this task:
A file system driver can map the user buffers into kernel memory space before posting to the FSP so the buffers can be accessed later by a system worker thread (FSP). The method commonly used by file system drivers is to lock the user buffers in the FSP because the memory pages can always be mapped later by the system worker thread.
A file system can save the thread of the calling process from the FSP and the system worker thread can attach to this calling process while in the FSP. Using the KeStackAttachProcess, the system worker thread would attach to the user's calling process and access the user buffers and then detach from the user's calling process using KeUnstackDetachProcess when the work is done.
RDBSS will automatically lock user buffers using method 1 in the RxFsdPostRequest routine for a number of IRP requests as long as the RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED bit is not set in the Flags member of the RX_CONTEXT structure. User buffers will be locked for the following requests:
IRP_MJ_DIRECTORY_CONTROL with a minor function of IRP_MN_QUERY_DIRECTORY
IRP_MJ_READ as long as the minor function does not include IRP_MN_MDL
IRP_MJ_WRITE as long as the minor function does not include IRP_MN_MDL
Method 2 is commonly used for processing IRPs that use METHOD_NEITHER when only a small amount of information is normally passed and returned. These IRPs would include the following:
RDBSS only supports asynchronous calls for the MrxLowIoSubmit array of operations. If a network mini-redirector wants to implement other operations (MRxQueryFileInfo, for example) as an asynchronous call, the network mini-redirector needs to post the request to the FSP. If a network mini-redirector receives a request for MrxQueryFileInfo with the RX_CONTEXT_ASYNC_OPERATION bit set in the Flags member of the RX_CONTEXT structure, the network mini-redirector would need to post this request to the FSP for asynchronous operation. In the operation of the MrxQueryFileInfo routine, the network mini-redirector would first need to capture the security context of the user's thread and map the user buffers into kernel space (or set the system worker thread to attach to the user's calling process while executing in the FSP). Then the network mini-redirector would set the PostRequest member of the RX_CONTEXT structure to TRUE and return STATUS_PENDING from the FSD. The work would be dispatched by RDBSS to a work queue for operation by a system worker thread (the FSP).