Hi,
In my ext2 file system driver, I split an nocached & pagingio IRP_MJ_READ to serveral associated IRPs, then send out the associated IRP separately. But the returned data is always wrong.
I pasted the codes bellow. Any idea will be appreciated.
Best wishes,
Matt Wu
mattwu@163.com
======================================================================================
typedef struct _EXT2_CONTEXT {
PIRP MasterIrp;
KEVENT Event;
BOOLEAN Wait;
ULONG Blocks;
ULONG Length;
} EXT2_CONTEXT, *PEXT2_CONTEXT;
NTSTATUS
Ext2ReadBlockSyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
{
PEXT2_CONTEXT pContext = (PEXT2_CONTEXT)Context;
if (!NT_SUCCESS( Irp->IoStatus.Status )) {
pContext->MasterIrp->IoStatus = Irp->IoStatus;
}
IoFreeMdl( Irp->MdlAddress );
IoFreeIrp( Irp );
if (InterlockedDecrement(&pContext->Blocks) == 0)
{
KeSetEvent( &pContext->Event, 0, FALSE );
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
Ext2ReadBlockAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PEXT2_CONTEXT pContext = (PEXT2_CONTEXT)Context;
if (!NT_SUCCESS( Irp->IoStatus.Status ))
{
pContext->MasterIrp->IoStatus = Irp->IoStatus;
}
if (InterlockedDecrement(&pContext->Blocks) == 0)
{
pContext->MasterIrp->IoStatus.Information = 0;
if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
{
pContext->MasterIrp->IoStatus.Information =
pContext->Length;
}
IoMarkIrpPending( pContext->MasterIrp );
ExFreePool(pContext);
}
return STATUS_SUCCESS;
}
NTSTATUS
Ext2ReadBlocks(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_BDL * Ext2BDL,
IN ULONG Count,
IN BOOLEAN bVerify )
{
PMDL Mdl;
PIRP Irp;
PIRP MasterIrp = IrpContext->Irp;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = STATUS_SUCCESS;
PEXT2_CONTEXT pContext = NULL;
ULONG dwTotal = 0;
ULONG i;
ASSERT(MasterIrp);
__try
{
pContext = ExAllocatePool(NonPagedPool, sizeof(EXT2_CONTEXT));
if (!pContext)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(pContext, sizeof(EXT2_CONTEXT));
pContext->Wait = IrpContext->IsSynchronous;
pContext->MasterIrp = MasterIrp;
pContext->Blocks = Count;
pContext->Length = 0;
if (pContext->Wait)
KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE);
for (i = 0; i < Count; i++)
{
Irp = IoMakeAssociatedIrp( MasterIrp,
(CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) );
if (!Irp)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer +
(*Ext2BDL)[i].Offset,
(*Ext2BDL)[i].Length,
FALSE,
FALSE,
Irp );
if (!Mdl)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
IoBuildPartialMdl( MasterIrp->MdlAddress,
Mdl,
(PCHAR)MasterIrp->UserBuffer + (*Ext2BDL)[i].Offset,
(*Ext2BDL)[i].Length );
IoSetNextIrpStackLocation( Irp );
IrpSp = IoGetCurrentIrpStackLocation( Irp );
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = (*Ext2BDL)[i].Length;
IrpSp->Parameters.Read.ByteOffset.QuadPart = (*Ext2BDL)[i].Lba;
IoSetCompletionRoutine( Irp,
IrpContext->IsSynchronous ?
&Ext2ReadBlockSyncCompletionRoutine :
&Ext2ReadBlockAsyncCompletionRoutine,
(PVOID) pContext,
TRUE,
TRUE,
TRUE );
IrpSp = IoGetNextIrpStackLocation( Irp );
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = (*Ext2BDL)[i].Length;
IrpSp->Parameters.Read.ByteOffset.QuadPart = (*Ext2BDL)[i].Length;
if ( bVerify )
{
SetFlag( IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
}
(*Ext2BDL)[i].Irp = Irp;
dwTotal += (*Ext2BDL)[i].Length;
}
MasterIrp->AssociatedIrp.IrpCount = Count;
if (IrpContext->IsSynchronous) {
MasterIrp->AssociatedIrp.IrpCount += 1;
}
pContext->Length = dwTotal;
for (i = 0; i < Count; i++)
{
Status = IoCallDriver ( Vcb->TargetDeviceObject,
(*Ext2BDL)[i].Irp );
}
if (IrpContext->IsSynchronous)
{
KeWaitForSingleObject( &(pContext->Event),
Executive, KernelMode, FALSE, NULL );
KeClearEvent( &(pContext->Event) );
}
}
__finally
{
if (IrpContext->IsSynchronous)
{
if (MasterIrp)
Status = MasterIrp->IoStatus.Status;
}
else
{
IrpContext->Irp = NULL;
Status = STATUS_PENDING;
}
if ( AbnormalTermination() )
{
for (i = 0; i < Count; i++)
{
if ((*Ext2BDL)[i].Irp != NULL )
{
if ( (*Ext2BDL)[i].Irp->MdlAddress != NULL )
{
IoFreeMdl( (*Ext2BDL)[i].Irp->MdlAddress );
}
IoFreeIrp( (*Ext2BDL)[i].Irp );
}
}
}
if (pContext)
ExFreePool(pContext);
}
return Status;
}
You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com