System hang at boot time

hi-

I have a volume upper filter driver that was working great. it kept
stats about the number of reads/writes sent to the volume(disk), and other
information like the byte offset and the size of the request. I just
took the toaster filter sample (from the XPDDK) and modified it to suit my needs.

Now, I wanted to add a completion routine that could inspect data
after a read request has been completed. The routine is as follows:

NTSTATUS
StatFilterReadCompRoutine(PDEVICE_OBJECT DeviceObject, PIRP pIrp,
PVOID Context) {
PKEVENT event = (PKEVENT)Context;
if(pIrp->PendingReturned) {
IoMarkIrpPending(pIrp);
}
KeSetEvent(event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

This routine is set in StatFilterRead(…) like follows:

NTSTATUS
StatFilterRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp )
{

/* set the completion routine */
IoSetCompletionRoutine(pIrp, StatFilterReadCompRoutine,
&(deviceExtension->eventdude), TRUE, TRUE, TRUE);

/* initialize the event */
KeInitializeEvent(&(deviceExtension->event),
NotificationEvent, FALSE);

/* IoCopy because we set the completion routine */
IoCopyCurrentIrpStackLocationToNext(pIrp);
status = IoCallDriver(deviceExtension->NextLowerDriver, pIrp);
KeWaitForSingleObject(&(deviceExtension->eventdude), Executive,
KernelMode, FALSE, NULL);

pIrp->IoStatus.Status = status; // FIXME: is this right?

if( NT_SUCCESS(status) ) {
/* inspect the contents of the read request */
}
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}

As you can see, the two functions do anything currently. I just
wanted to get the completion routine stuff to work and get control
back the the read dispatch routine. However, the system hangs during
boot. The only changes to the code are the completion routine stuff.
Nothing in the driver is in paged memory. I have been reading online
and in rajeev’s book about using IopCompleteRequest if the request was
sent in synchronous mode. Is this the problem? There is also mention
in the book that if a paging request is being satisfied then the
driver must not issue any APCs. This is my current guess as to why
the system cannot get past boot. If this is correct, does anyone know
the solution? Sorry for the long email.

Thanks,
-Nick Kidd

Couple problems here. First, the call to IoSetCompletionRoutine must
come AFTER the call to IoCopyCurrentIrpStackLocationToNext. Otherwise,
your completion routine will never be called (since
IoCopyCurrentIrpStackLocationToNext zeroes out the ‘Control’ member of
the next stack location).

Second, you don’t need this line:

pIrp->IoStatus.Status = status; // FIXME: is this right?

This will cause problems in the case where IoCallDriver returns
STATUS_PENDING. You should return the value of pIrp->IoStatus from your
dispatch function like this:

status = pIrp->IoStatus.Status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;

Third, if you are returning STATUS_MORE_PROCESSING_REQUIRED from a
completion routine, you should not call IoMarkIrpPending (see docs for
this function).

You should get a copy of OSR’s book - it explains all of this in
excruciating detail, and there are many variations. (I think I’ve got it
right, I left my copy at work so I’m flying by wire here).

  • Nicholas Ryan

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Nicholas Kidd
Sent: Wednesday, December 11, 2002 3:00 PM
To: File Systems Developers
Subject: [ntfsd] System hang at boot time

hi-

I have a volume upper filter driver that was working great.
it kept stats about the number of reads/writes sent to the
volume(disk), and other information like the byte offset and
the size of the request. I just took the toaster filter
sample (from the XPDDK) and modified it to suit my needs.

Now, I wanted to add a completion routine that could inspect
data after a read request has been completed. The routine is
as follows:

NTSTATUS
StatFilterReadCompRoutine(PDEVICE_OBJECT DeviceObject, PIRP pIrp,
PVOID Context) {
PKEVENT event = (PKEVENT)Context;
if(pIrp->PendingReturned) {
IoMarkIrpPending(pIrp);
}
KeSetEvent(event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

This routine is set in StatFilterRead(…) like follows:

NTSTATUS
StatFilterRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp ) {

/* set the completion routine */
IoSetCompletionRoutine(pIrp, StatFilterReadCompRoutine,
&(deviceExtension->eventdude), TRUE, TRUE, TRUE);

/* initialize the event */
KeInitializeEvent(&(deviceExtension->event),
NotificationEvent, FALSE);

/* IoCopy because we set the completion routine */
IoCopyCurrentIrpStackLocationToNext(pIrp);
status = IoCallDriver(deviceExtension->NextLowerDriver, pIrp);
KeWaitForSingleObject(&(deviceExtension->eventdude), Executive,
KernelMode, FALSE, NULL);

pIrp->IoStatus.Status = status; // FIXME: is this right?

if( NT_SUCCESS(status) ) {
/* inspect the contents of the read request */
}
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}

As you can see, the two functions do anything currently. I
just wanted to get the completion routine stuff to work and
get control back the the read dispatch routine. However, the
system hangs during boot. The only changes to the code are
the completion routine stuff. Nothing in the driver is in
paged memory. I have been reading online and in rajeev’s
book about using IopCompleteRequest if the request was sent
in synchronous mode. Is this the problem? There is also
mention in the book that if a paging request is being
satisfied then the driver must not issue any APCs. This is
my current guess as to why the system cannot get past boot.
If this is correct, does anyone know the solution? Sorry for
the long email.

Thanks,
-Nick Kidd


You are currently subscribed to ntfsd as: xxxxx@nryan.com
To unsubscribe send a blank email to %%email.unsub%%

Nicholas-

You are a godsend.

Thanks,
-nick

oh yeah, she is a booting again… :slight_smile:

On Wed, Dec 11, 2002 at 10:11:08PM -0800, Nicholas Ryan wrote:

Couple problems here. First, the call to IoSetCompletionRoutine must
come AFTER the call to IoCopyCurrentIrpStackLocationToNext. Otherwise,
your completion routine will never be called (since
IoCopyCurrentIrpStackLocationToNext zeroes out the ‘Control’ member of
the next stack location).

Second, you don’t need this line:

pIrp->IoStatus.Status = status; // FIXME: is this right?

This will cause problems in the case where IoCallDriver returns
STATUS_PENDING. You should return the value of pIrp->IoStatus from your
dispatch function like this:

status = pIrp->IoStatus.Status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;

Third, if you are returning STATUS_MORE_PROCESSING_REQUIRED from a
completion routine, you should not call IoMarkIrpPending (see docs for
this function).

You should get a copy of OSR’s book - it explains all of this in
excruciating detail, and there are many variations. (I think I’ve got it
right, I left my copy at work so I’m flying by wire here).

  • Nicholas Ryan

> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Nicholas Kidd
> Sent: Wednesday, December 11, 2002 3:00 PM
> To: File Systems Developers
> Subject: [ntfsd] System hang at boot time
>
>
> hi-
>
> I have a volume upper filter driver that was working great.
> it kept stats about the number of reads/writes sent to the
> volume(disk), and other information like the byte offset and
> the size of the request. I just took the toaster filter
> sample (from the XPDDK) and modified it to suit my needs.
>
> Now, I wanted to add a completion routine that could inspect
> data after a read request has been completed. The routine is
> as follows:
>
>
> NTSTATUS
> StatFilterReadCompRoutine(PDEVICE_OBJECT DeviceObject, PIRP pIrp,
> PVOID Context) {
> PKEVENT event = (PKEVENT)Context;
> if(pIrp->PendingReturned) {
> IoMarkIrpPending(pIrp);
> }
> KeSetEvent(event, 0, FALSE);
> return STATUS_MORE_PROCESSING_REQUIRED;
> }
>
> This routine is set in StatFilterRead(…) like follows:
>
> NTSTATUS
> StatFilterRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp ) {
> …
>
> /* set the completion routine */
> IoSetCompletionRoutine(pIrp, StatFilterReadCompRoutine,
> &(deviceExtension->eventdude), TRUE, TRUE, TRUE);
>
> /* initialize the event */
> KeInitializeEvent(&(deviceExtension->event),
> NotificationEvent, FALSE);
>
> /* IoCopy because we set the completion routine */
> IoCopyCurrentIrpStackLocationToNext(pIrp);
> status = IoCallDriver(deviceExtension->NextLowerDriver, pIrp);
> KeWaitForSingleObject(&(deviceExtension->eventdude), Executive,
> KernelMode, FALSE, NULL);
>
> pIrp->IoStatus.Status = status; // FIXME: is this right?
>
> if( NT_SUCCESS(status) ) {
> /* inspect the contents of the read request */
> }
> IoCompleteRequest(pIrp, IO_NO_INCREMENT);
> return status;
> }
>
> As you can see, the two functions do anything currently. I
> just wanted to get the completion routine stuff to work and
> get control back the the read dispatch routine. However, the
> system hangs during boot. The only changes to the code are
> the completion routine stuff. Nothing in the driver is in
> paged memory. I have been reading online and in rajeev’s
> book about using IopCompleteRequest if the request was sent
> in synchronous mode. Is this the problem? There is also
> mention in the book that if a paging request is being
> satisfied then the driver must not issue any APCs. This is
> my current guess as to why the system cannot get past boot.
> If this is correct, does anyone know the solution? Sorry for
> the long email.
>
> Thanks,
> -Nick Kidd
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@nryan.com
> To unsubscribe send a blank email to %%email.unsub%%
>


You are currently subscribed to ntfsd as: kidd@cs.wisc.edu
To unsubscribe send a blank email to %%email.unsub%%

> if(pIrp->PendingReturned) {

IoMarkIrpPending(pIrp);
}

Remove this. It is not needed if you use
STATUS_MORE_PROCESSING_REQUIRED.

Max