NTSTATUS FatFsdRead ( IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the driver entry to the common read routine for NtReadFile calls. For synchronous requests, the CommonRead is called with Wait == TRUE, which means the request will always be completed in the current thread, and never passed to the Fsp. If it is not a synchronous request, CommonRead is called with Wait == FALSE, which means the request will be passed to the Fsp only if there is a need to block. Arguments: VolumeDeviceObject - Supplies the volume device object where the file being Read exists Irp - Supplies the Irp being processed Return Value: NTSTATUS - The FSD status for the IRP --*/ { PFCB Fcb = NULL; NTSTATUS Status; PIRP_CONTEXT IrpContext = NULL; BOOLEAN TopLevel; DebugTrace(+1, Dbg, "FatFsdRead\n", 0); // // Call the common Read routine, with blocking allowed if synchronous // FsRtlEnterFileSystem(); // // We are first going to do a quick check for paging file IO. Since this // is a fast path, we must replicate the check for the fsdo. // if (!FatDeviceIsFatFsdo( IoGetCurrentIrpStackLocation(Irp)->DeviceObject)) { Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext); if ((NodeType(Fcb) == FAT_NTC_FCB) && FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) { // // Do the usual STATUS_PENDING things. // IoMarkIrpPending( Irp ); // // If there is not enough stack to do this read, then post this // read to the overflow queue. // if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) { KEVENT Event; PAGING_FILE_OVERFLOW_PACKET Packet; Packet.Irp = Irp; Packet.Fcb = Fcb; KeInitializeEvent( &Event, NotificationEvent, FALSE ); FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead ); // // And wait for the worker thread to complete the item // (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); } else { // // Perform the actual IO, it will be completed when the io finishes. // FatPagingFileIo( Irp, Fcb ); } FsRtlExitFileSystem(); return STATUS_PENDING; } } try { TopLevel = FatIsIrpTopLevel( Irp ); IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) ); // // If this is an Mdl complete request, don't go through // common read. // if ( FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE) ) { DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 ); try_return( Status = FatCompleteMdl( IrpContext, Irp )); } // // Check if we have enough stack space to process this request. If there // isn't enough then we will pass the request off to the stack overflow thread. // if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) { DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 ); try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) ); } Status = FatCommonRead( IrpContext, Irp ); try_exit: NOTHING; } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) { // // We had some trouble trying to perform the requested // operation, so we'll abort the I/O request with // the error status that we get back from the // execption code // Status = FatProcessException( IrpContext, Irp, GetExceptionCode() ); } if (TopLevel) { IoSetTopLevelIrp( NULL ); } FsRtlExitFileSystem(); // // And return to our caller // DebugTrace(-1, Dbg, "FatFsdRead -> %08lx\n", Status); UNREFERENCED_PARAMETER( VolumeDeviceObject ); return Status; }
NTSTATUS FsRtlInitializeWorkerThread ( VOID ) { OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Thread; ULONG i; NTSTATUS Status = STATUS_SUCCESS; // // Create worker threads to handle normal and paging overflow reads. // InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); for (i=0; i < 2; i++) { // // Initialize the FsRtl stack overflow work Queue objects. // KeInitializeQueue(&FsRtlWorkerQueues[i], 0); Status = PsCreateSystemThread( &Thread, THREAD_ALL_ACCESS, &ObjectAttributes, 0L, NULL, FsRtlWorkerThread, ULongToPtr( i )); if (!NT_SUCCESS( Status )) { return Status; } ZwClose( Thread ); } // // Initialize the serial workitem so we can guarantee to post items // for paging files to the worker threads. // KeInitializeEvent( &StackOverflowFallbackSerialEvent, SynchronizationEvent, TRUE ); // // Pass a NOP routine through FsRtlPostStackOverfow() in order to flush out // any prefetchw instructions that may lie in that path. Otherwise we'll // try to patch the prefetchw instruction when we can ill afford the stack // space. // #if defined(_AMD64_) FsRtlPostStackOverflow( NULL, NULL, FsRtlpNopStackOverflowRoutine ); FsRtlPostPagingFileStackOverflow( NULL, NULL, FsRtlpNopStackOverflowRoutine ); #endif return Status; }