📄 deviosup.c
字号:
// and dealt with as a normal IO error.
//
(VOID)FatLowLevelReadWrite( IrpContext,
Vcb->TargetDeviceObject,
Irp,
Vcb );
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatSingleAsync -> VOID\n", 0);
return;
}
VOID
FatSingleNonAlignedSync (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PUCHAR Buffer,
IN LBO Lbo,
IN ULONG ByteCount,
IN PIRP Irp
)
/*++
Routine Description:
This routine reads or writes one or more contiguous sectors from a device
Synchronously, and does so to a buffer that must come from non paged
pool. It saves a pointer to the Irp's original Mdl, and creates a new
one describing the given buffer. It implements the read by simply filling
in the next stack frame in the Irp, and passing it on. The transfer
occurs to the single buffer originally specified in the user request.
Arguments:
IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
Vcb - Supplies the device to read
Buffer - Supplies a buffer from non-paged pool.
Lbo - Supplies the starting Logical Byte Offset to begin reading from
ByteCount - Supplies the number of bytes to read from the device
Irp - Supplies the master Irp to associated with the async
request.
Return Value:
None.
--*/
{
PIO_STACK_LOCATION IrpSp;
PMDL Mdl;
PMDL SavedMdl;
DebugTrace(+1, Dbg, "FatSingleNonAlignedAsync\n", 0);
DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
DebugTrace( 0, Dbg, "Vcb = %08lx\n", Vcb );
DebugTrace( 0, Dbg, "Buffer = %08lx\n", Buffer );
DebugTrace( 0, Dbg, "Lbo = %08lx\n", Lbo);
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
//
// Create a new Mdl describing the buffer, saving the current one in the
// Irp
//
SavedMdl = Irp->MdlAddress;
Irp->MdlAddress = 0;
Mdl = IoAllocateMdl( Buffer,
ByteCount,
FALSE,
FALSE,
Irp );
if (Mdl == NULL) {
Irp->MdlAddress = SavedMdl;
FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
//
// Lock the new Mdl in memory.
//
try {
MmProbeAndLockPages( Mdl, KernelMode, IoWriteAccess );
} finally {
if ( AbnormalTermination() ) {
IoFreeMdl( Mdl );
Irp->MdlAddress = SavedMdl;
}
}
//
// Set up the completion routine address in our stack frame.
//
IoSetCompletionRoutine( Irp,
&FatSingleSyncCompletionRoutine,
IrpContext->FatIoContext,
TRUE,
TRUE,
TRUE );
//
// Setup the next IRP stack location in the associated Irp for the disk
// driver beneath us.
//
IrpSp = IoGetNextIrpStackLocation( Irp );
//
// Setup the Stack location to do a read from the disk driver.
//
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = ByteCount;
IrpSp->Parameters.Read.ByteOffset.QuadPart = Lbo;
//
// If this I/O originating during FatVerifyVolume, bypass the
// verify logic.
//
if ( Vcb->VerifyThread == KeGetCurrentThread() ) {
SetFlag( IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
}
//
// Issue the read request
//
DebugDoit( FatIoCallDriverCount += 1);
//
// If IoCallDriver returns an error, it has completed the Irp
// and the error will be caught by our completion routines
// and dealt with as a normal IO error.
//
try {
(VOID)FatLowLevelReadWrite( IrpContext,
Vcb->TargetDeviceObject,
Irp,
Vcb );
FatWaitSync( IrpContext );
} finally {
MmUnlockPages( Mdl );
IoFreeMdl( Mdl );
Irp->MdlAddress = SavedMdl;
}
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatSingleNonAlignedSync -> VOID\n", 0);
return;
}
VOID
FatWaitSync (
IN PIRP_CONTEXT IrpContext
)
/*++
Routine Description:
This routine waits for one or more previously started I/O requests
from the above routines, by simply waiting on the event.
Arguments:
Return Value:
None
--*/
{
DebugTrace(+1, Dbg, "FatWaitSync, Context = %08lx\n", IrpContext->FatIoContext );
KeWaitForSingleObject( &IrpContext->FatIoContext->Wait.SyncEvent,
Executive, KernelMode, FALSE, NULL );
KeClearEvent( &IrpContext->FatIoContext->Wait.SyncEvent );
DebugTrace(-1, Dbg, "FatWaitSync -> VOID\n", 0 );
}
//
// Internal Support Routine
//
NTSTATUS
FatMultiSyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
)
/*++
Routine Description:
This is the completion routine for all reads and writes started via
FatRead/WriteMultipleAsynch. It must synchronize its operation for
multiprocessor environments with itself on all other processors, via
a spin lock found via the Context parameter.
The completion routine has the following responsibilities:
If the individual request was completed with an error, then
this completion routine must see if this is the first error
(essentially by Vbo), and if so it must correctly reduce the
byte count and remember the error status in the Context.
If the IrpCount goes to 1, then it sets the event in the Context
parameter to signal the caller that all of the asynch requests
are done.
Arguments:
DeviceObject - Pointer to the file system device object.
Irp - Pointer to the associated Irp which is being completed. (This
Irp will no longer be accessible after this routine returns.)
Contxt - The context parameter which was specified for all of
the multiple asynch I/O requests for this MasterIrp.
Return Value:
The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
immediately complete the Master Irp without being in a race condition
with the IoCompleteRequest thread trying to decrement the IrpCount in
the Master Irp.
--*/
{
PFAT_IO_CONTEXT Context = Contxt;
PIRP MasterIrp = Context->MasterIrp;
DebugTrace(+1, Dbg, "FatMultiSyncCompletionRoutine, Context = %08lx\n", Context );
//
// If we got an error (or verify required), remember it in the Irp
//
MasterIrp = Context->MasterIrp;
if (!NT_SUCCESS( Irp->IoStatus.Status )) {
ASSERT( NT_SUCCESS( FatAssertNotStatus ) || Irp->IoStatus.Status != FatAssertNotStatus );
#ifdef SYSCACHE_COMPILE
DbgPrint( "FAT SYSCACHE: MultiSync (IRP %08x for Master %08x) -> %08x\n", Irp, MasterIrp, Irp->IoStatus );
#endif
MasterIrp->IoStatus = Irp->IoStatus;
}
ASSERT( !(NT_SUCCESS( Irp->IoStatus.Status ) && Irp->IoStatus.Information == 0 ));
//
// We must do this here since IoCompleteRequest won't get a chance
// on this associated Irp.
//
IoFreeMdl( Irp->MdlAddress );
IoFreeIrp( Irp );
if (InterlockedDecrement(&Context->IrpCount) == 0) {
FatDoCompletionZero( MasterIrp, Context );
KeSetEvent( &Context->Wait.SyncEvent, 0, FALSE );
}
DebugTrace(-1, Dbg, "FatMultiSyncCompletionRoutine -> SUCCESS\n", 0 );
UNREFERENCED_PARAMETER( DeviceObject );
return STATUS_MORE_PROCESSING_REQUIRED;
}
//
// Internal Support Routine
//
NTSTATUS
FatMultiAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
)
/*++
Routine Description:
This is the completion routine for all reads and writes started via
FatRead/WriteMultipleAsynch. It must synchronize its operation for
multiprocessor environments with itself on all other processors, via
a spin lock found via the Context parameter.
The completion routine has has the following responsibilities:
If the individual request was completed with an error, then
this completion routine must see if this is the first error
(essentially by Vbo), and if so it must correctly reduce the
byte count and remember the error status in the Context.
If the IrpCount goes to 1, then it sets the event in the Context
parameter to signal the caller that all of the asynch requests
are done.
Arguments:
DeviceObject - Pointer to the file system device object.
Irp - Pointer to the associated Irp which is being completed. (This
Irp will no longer be accessible after this routine returns.)
Contxt - The context parameter which was specified for all of
the multiple asynch I/O requests for this MasterIrp.
Return Value:
The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
immediately complete the Master Irp without being in a race condition
with the IoCompleteRequest thread trying to decrement the IrpCount in
the Master Irp.
--*/
{
PFAT_IO_CONTEXT Context = Contxt;
PIRP MasterIrp = Context->MasterIrp;
DebugTrace(+1, Dbg, "FatMultiAsyncCompletionRoutine, Context = %08lx\n", Context );
//
// If we got an error (or verify required), remember it in the Irp
//
MasterIrp = Context->MasterIrp;
if (!NT_SUCCESS( Irp->IoStatus.Status )) {
ASSERT( NT_SUCCESS( FatAssertNotStatus ) || Irp->IoStatus.Status != FatAssertNotStatus );
#ifdef SYSCACHE_COMPILE
DbgPrint( "FAT SYSCACHE: MultiAsync (IRP %08x for Master %08x) -> %08x\n", Irp, MasterIrp, Irp->IoStatus );
#endif
MasterIrp->IoStatus = Irp->IoStatus;
}
ASSERT( !(NT_SUCCESS( Irp->IoStatus.Status ) && Irp->IoStatus.Information == 0 ));
if (InterlockedDecrement(&Context->IrpCount) == 0) {
FatDoCompletionZero( MasterIrp, Context );
if (NT_SUCCESS(MasterIrp->IoStatus.Status)) {
MasterIrp->IoStatus.Information =
Context->Wait.Async.RequestedByteCount;
ASSERT(MasterIrp->IoStatus.Information != 0);
//
// Now if this wasn't PagingIo, set either the read or write bit.
//
if (!FlagOn(MasterIrp->Flags, IRP_PAGING_IO)) {
SetFlag( Context->Wait.Async.FileObject->Flags,
IoGetCurrentIrpStackLocation(MasterIrp)->MajorFunction == IRP_MJ_READ ?
FO_FILE_FAST_IO_READ : FO_FILE_MODIFIED );
}
}
//
// If this was a special async write, decrement the count. Set the
// event if this was the final outstanding I/O for the file. We will
// also want to queue an APC to deal with any error conditionions.
//
if ((Context->Wait.Async.NonPagedFcb) &&
(ExInterlockedAddUlong( &Context->Wait.Async.NonPagedFcb->OutstandingAsyncWrites,
0xffffffff,
&FatData.GeneralSpinLock ) == 1)) {
KeSetEvent( Context->Wait.Async.NonPagedFcb->OutstandingAsyncEvent, 0, FALSE );
}
//
// Now release the resources.
//
if (Context->Wait.Async.Resource != NULL) {
ExReleaseResourceForThreadLite( Context->Wait.Async.Resource,
Context->Wait.Async.ResourceThreadId );
}
if (Context->Wait.Async.Resource2 != NULL) {
ExReleaseResourceForThreadLite( Context->Wait.As
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -