📄 deviosup.c
字号:
KeDelayExecutionThread (KernelMode, FALSE, &Fat30Milliseconds);
}
//
// Note that since we failed to launch this associated Irp, that the completion
// code at the bottom will take care of completing the master Irp.
//
if (!NT_SUCCESS(Irp->IoStatus.Status)) {
ASSERT( IrpCount );
break;
}
} else {
//
// Indicate we used an associated Irp.
//
IrpCount -= 1;
}
//
// With an associated IRP, we must take over the first stack location so
// we can have one to put the completion routine on. When re-using the
// master IRP, its already there.
//
if (!IrpIsMaster) {
//
// Get the first IRP stack location in the associated Irp
//
IoSetNextIrpStackLocation( AssocIrp );
NextIrpSp = IoGetCurrentIrpStackLocation( AssocIrp );
//
// Setup the Stack location to describe our read.
//
NextIrpSp->MajorFunction = IrpSp->MajorFunction;
NextIrpSp->Parameters.Read.Length = NextByteCount;
NextIrpSp->Parameters.Read.ByteOffset.QuadPart = Vbo;
//
// We also need the VolumeDeviceObject in the Irp stack in case
// we take the failure path.
//
NextIrpSp->DeviceObject = IrpSp->DeviceObject;
} else {
//
// Save the MDL in the IRP and prepare the stack
// context for the completion routine.
//
KeInitializeEvent( &Context.Event, SynchronizationEvent, FALSE );
Context.RestoreMdl = Irp->MdlAddress;
}
//
// And drop our Mdl into the Irp.
//
AssocIrp->MdlAddress = Mdl;
//
// Set up the completion routine address in our stack frame.
// For true associated IRPs, this is only invoked on error or
// cancel, and just copies the error Status into master irp's
// iosb.
//
// If the error implies a media problem, it also enqueues a
// worker item to write out the dirty bit so that the next
// time we run we will do a autochk /r
//
if (IrpIsMaster) {
IoSetCompletionRoutine( AssocIrp,
FatPagingFileCompletionRoutineCatch,
&Context,
TRUE,
TRUE,
TRUE );
} else {
IoSetCompletionRoutine( AssocIrp,
FatPagingFileCompletionRoutine,
Irp,
FALSE,
TRUE,
TRUE );
}
//
// Setup the next IRP stack location for the disk driver beneath us.
//
NextIrpSp = IoGetNextIrpStackLocation( AssocIrp );
//
// Since this is paging file IO, we'll just ignore the verify bit.
//
SetFlag( NextIrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
//
// Setup the Stack location to do a read from the disk driver.
//
NextIrpSp->MajorFunction = IrpSp->MajorFunction;
NextIrpSp->Parameters.Read.Length = NextByteCount;
NextIrpSp->Parameters.Read.ByteOffset.QuadPart = NextLbo;
(VOID)IoCallDriver( DeviceObject, AssocIrp );
//
// Wait for the Irp in the catch case and drop the flags.
//
if (IrpIsMaster) {
KeWaitForSingleObject( &Context.Event, Executive, KernelMode, FALSE, NULL );
IrpIsMaster = MdlIsReserve = FALSE;
//
// If the Irp is showing a failed status, there is no point in continuing.
// In doing so, we get to avoid squirreling away the failed status in case
// we were to re-use the master irp again.
//
// Note that since we re-used the master, we must not have issued the "last"
// associated Irp, and thus the completion code at the bottom will take care
// of that for us.
//
if (!NT_SUCCESS(Irp->IoStatus.Status)) {
ASSERT( IrpCount );
break;
}
}
//
// Now adjust everything for the next pass through the loop.
//
Vbo += NextByteCount;
BufferOffset += NextByteCount;
ByteCount -= NextByteCount;
//
// Try to lookup the next run, if we are not done and we got
// all the way through the current run.
//
if (RemainingByteCount) {
//
// Advance the Lbo/Vbo if we have more to do in the current run.
//
NextLbo += NextByteCount;
NextVbo += NextByteCount;
NextByteCount = RemainingByteCount;
} else {
CurrentIndex += 1;
if ( CurrentIndex <= LastIndex ) {
ASSERT( ByteCount != 0 );
FatGetNextMcbEntry( Fcb->Vcb, &Fcb->Mcb,
CurrentIndex,
&NextVbo,
&NextLbo,
&NextByteCount );
ASSERT( NextVbo == Vbo );
}
}
} // while ( CurrentIndex <= LastIndex )
//
// If we didn't get enough associated Irps going to make this asynchronous, we
// twiddle our thumbs and wait for those we did launch to complete.
//
if (IrpCount) {
while (Irp->AssociatedIrp.IrpCount != IrpCount) {
KeDelayExecutionThread (KernelMode, FALSE, &Fat30Milliseconds);
}
IoCompleteRequest( Irp, IO_DISK_INCREMENT );
}
DebugTrace(-1, Dbg, "FatPagingFileIo -> VOID\n", 0);
return;
}
NTSTATUS
FatNonCachedIo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB FcbOrDcb,
IN ULONG StartingVbo,
IN ULONG ByteCount,
IN ULONG UserByteCount
)
/*++
Routine Description:
This routine performs the non-cached disk io described in its parameters.
The choice of a single run is made if possible, otherwise multiple runs
are executed.
Arguments:
IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
Irp - Supplies the requesting Irp.
FcbOrDcb - Supplies the file to act on.
StartingVbo - The starting point for the operation.
ByteCount - The lengh of the operation.
UserByteCount - The last byte the user can see, rest to be zeroed.
Return Value:
None.
--*/
{
//
// Declare some local variables for enumeration through the
// runs of the file, and an array to store parameters for
// parallel I/Os
//
BOOLEAN Wait;
LBO NextLbo;
VBO NextVbo;
ULONG NextByteCount;
BOOLEAN NextIsAllocated;
LBO LastLbo;
ULONG LastByteCount;
BOOLEAN LastIsAllocated;
BOOLEAN EndOnMax;
ULONG FirstIndex;
ULONG CurrentIndex;
ULONG LastIndex;
ULONG NextRun;
ULONG BufferOffset;
ULONG OriginalByteCount;
IO_RUN StackIoRuns[FAT_MAX_IO_RUNS_ON_STACK];
PIO_RUN IoRuns;
DebugTrace(+1, Dbg, "FatNonCachedIo\n", 0);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
DebugTrace( 0, Dbg, "FcbOrDcb = %08lx\n", FcbOrDcb );
DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", StartingVbo );
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount );
if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
PFILE_SYSTEM_STATISTICS Stats =
&FcbOrDcb->Vcb->Statistics[KeGetCurrentProcessorNumber()];
if (IrpContext->MajorFunction == IRP_MJ_READ) {
Stats->Fat.NonCachedReads += 1;
Stats->Fat.NonCachedReadBytes += ByteCount;
} else {
Stats->Fat.NonCachedWrites += 1;
Stats->Fat.NonCachedWriteBytes += ByteCount;
}
}
//
// Initialize some locals.
//
NextRun = 0;
BufferOffset = 0;
OriginalByteCount = ByteCount;
Wait = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
//
// For nonbuffered I/O, we need the buffer locked in all
// cases.
//
// This call may raise. If this call succeeds and a subsequent
// condition is raised, the buffers are unlocked automatically
// by the I/O system when the request is completed, via the
// Irp->MdlAddress field.
//
FatLockUserBuffer( IrpContext,
Irp,
(IrpContext->MajorFunction == IRP_MJ_READ) ?
IoWriteAccess : IoReadAccess,
ByteCount );
//
// Setup the required zeroing for read requests.
//
if (UserByteCount != ByteCount) {
PMDL Mdl;
ASSERT( ByteCount > UserByteCount );
Mdl = IoAllocateMdl( (PUCHAR) Irp->UserBuffer + UserByteCount,
ByteCount - UserByteCount,
FALSE,
FALSE,
NULL );
if (Mdl == NULL) {
FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
IoBuildPartialMdl( Irp->MdlAddress,
Mdl,
(PUCHAR) Irp->UserBuffer + UserByteCount,
ByteCount - UserByteCount );
IrpContext->FatIoContext->ZeroMdl = Mdl;
//
// Map the MDL now so we can't fail at IO completion time. Note
// that this will be only a single page.
//
if (MmGetSystemAddressForMdlSafe( Mdl, NormalPagePriority ) == NULL) {
FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
}
//
// Try to lookup the first run. If there is just a single run,
// we may just be able to pass it on.
//
FatLookupFileAllocation( IrpContext,
FcbOrDcb,
StartingVbo,
&NextLbo,
&NextByteCount,
&NextIsAllocated,
&EndOnMax,
&FirstIndex );
//
// We just added the allocation, thus there must be at least
// one entry in the mcb corresponding to our write, ie.
// NextIsAllocated must be true. If not, the pre-existing file
// must have an allocation error.
//
if ( !NextIsAllocated ) {
FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
ASSERT( NextByteCount != 0 );
//
// If the request was not aligned correctly, read in the first
// part first.
//
//
// See if the write covers a single valid run, and if so pass
// it on. We must bias this by the byte that is lost at the
// end of the maximal file.
//
if ( NextByteCount >= ByteCount - (EndOnMax ? 1 : 0)) {
if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
CollectDiskIoStats(FcbOrDcb->Vcb, IrpContext->MajorFunction,
FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO), 1);
} else {
PFILE_SYSTEM_STATISTICS Stats =
&FcbOrDcb->Vcb->Statistics[KeGetCurrentProcessorNumber()];
if (IrpContext->MajorFunction == IRP_MJ_READ) {
Stats->Fat.NonCachedDiskReads += 1;
} else {
Stats->Fat.NonCachedDiskWrites += 1;
}
}
DebugTrace( 0, Dbg, "Passing 1 Irp on to Disk Driver\n", 0 );
FatSingleAsync( IrpContext,
FcbOrDcb->Vcb,
NextLbo,
ByteCount,
Irp );
} else {
//
// If there we can't wait, and there are more runs than we can handle,
// we will have to post this request.
//
FatLookupFileAllocation( IrpContext,
FcbOrDcb,
StartingVbo + ByteCount - 1,
&LastLbo,
&LastByteCount,
&LastIsAllocated,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -