IoMakeAssociatedIrp problems

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

Hi, all,

I got it. Thanks!

IrpSp->Parameters.Read.ByteOffset.QuadPart = (*Ext2BDL)[i].Length;
It Should be "IrpSp->Parameters.Read.ByteOffset.QuadPart = (*Ext2BDL)[i].Offset;


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

>Hi, all,

I got it. Thanks!

> IrpSp->Parameters.Read.ByteOffset.QuadPart = (*Ext2BDL)[i].Length;
It Should be "IrpSp->Parameters.Read.ByteOffset.QuadPart = (*Ext2BDL)[i].Offset;
IrpSp->Parameters.Read.ByteOffset.QuadPart = (*Ext2BDL)[i].Lba;

Matt Wu
mattwu@163.com
http://sysinternals.yeah.net


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