Ah yes, I see what you’re saying. I was thinking I shouldn’t need to return
pending (because I am forcing the irp to be synchronous, after all), but I
ran into a bug where NT4 NTFS actually did return pending, I didn’t, and
KABOOM! The reason, as I now see, was that I was marking the irp pending in
completion and returning a non -pending return code (not that I wasn’t
returning pending). Here is what I now think the code should look like:
NTSTATUS Create(PDEVICE_OBJECT pDev, PIRP pIrp)
{
NTSTATUS ntRet;
PDEVICE_OBJECT pNextDevice;
KEVENT event;
//event used to make call synchronous even if the fsd pends the
operation
KeInitializeEvent(&event, NotificationEvent, FALSE);
//get the deviced we are attached to from the device extension
pNextDevice =
((PDEVICE_EXTENSION)(pDev->DeviceExtension))->NextDriverDeviceObject;
IoCopyCurrentIrpStackLocationToNext(pIrp);
//set a completion routine
IoSetCompletionRoutine(pIrp,
CreateComplete,
&event,
TRUE,
TRUE,
TRUE);
//pass the irp down
ntRet = IoCallDriver(pNextDevice, pIrp);
if (ntRet == STATUS_PENDING)
{
//wait for the event that is signalled in our completion
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
//get the real success code - we will not need to return
STATUS_PENDING
//because we are forcing the thread to block, after all
ntRet = pIrp->IoStatus.Status;
}
//if the file was opened
if (NT_SUCCESS(ntRet))
{
//do some stuff that I didn’t want to do in the completion
routine
}
//we are done with the irp and ready to complete the request.
IoCompleteRequest(pIrp, IO_DISK_INCREMENT);
//don’t worry about returning STATUS_PENDING
return ntRet;
}
NTSTATUS CreateComplete(PDEVICE_OBJECT pDev, PIRP pIrp, PKEVENT pContext)
{
//alert the mainline thread that the io was completed
KeSetEvent((PKEVENT)pContext, IO_NO_INCREMENT, FALSE);
//we need to hold onto this irp for whatever reason
return (STATUS_MORE_PROCESSING_REQUIRED);
}
-----Original Message-----
From: Pavel Hrdina [mailto:xxxxx@sodatsw.cz]
Sent: Tuesday, August 01, 2000 3:04 PM
To: File Systems Developers
Subject: [ntfsd] RE: using STATUS_MORE_PROCESSING_REQUIRED: am I using it
correctly??
Dear Joel !
Also you do not need (and you can’t do that) to mark the IRP pending
in your completion routine. This is because you are blocking the requesting
thread and the processing continues after the lover level driver calls
IoCompleteRequest. But this implies you’re always processing this
request synchronously - and thus you’re “eating” the IRP pending flag
below you.
In Create dispatch routine you have to always return value different
from STATUS_PENDING. Thus the last line should look like this:
return ntRet;
instead of your:
return pIrp->PendingReturned ? STATUS_PENDING : ntRet;
Paul
-----P?vodn? zpr?va-----
Od: Smith, Joel [SMTP:xxxxx@ntpsoftware.com]
Odesl?no: 31. ?ervence 2000 22:24
Komu: File Systems Developers
P?edm?t: [ntfsd] using STATUS_MORE_PROCESSING_REQUIRED: am I using
it correctly??Hello,
I’ve just want to be sure I am using
STATUS_MORE_PROCESSING_REQUIRED correctly. My code seems to work fine
(code sample is pased below), but I’m nervous because of a footnote in
‘File System Internals’ (page 165). The footnote contains these
sentences:“The problem, through, is that there is a lot of post processing
required on that IRP that will have been abrubtly interrupted due to you
returning such a status code from your completion routine. You driver
will then have to device a method whereby such postprocessing can be
resumed later; this is not a trivial task.”Well, just calling IoCompleteRequest on the irp certainly seems
trivial, so I am wondering if I am handling this correctly or are there
more steps I should be doing (note that everything seems to work just
fine). Aside from Nagar’s book, there isn’t much documentation on how to
handle STATUS_MORE_PROCESSING_REQUIRED. Here is some code, with all of
the irrelevant domain specific stuff stripped out. Am I doing this right?Thanks,
JoelNTSTATUS Create(PDEVICE_OBJECT pDev, PIRP pIrp)
{
NTSTATUS ntRet;
PDEVICE_OBJECT pNextDevice;
KEVENT event;//event used to make call synchronous even if the fsd pends the
operation
KeInitializeEvent(&event, NotificationEvent, FALSE);//get the deviced we are attached to from the device extension
pNextDevice =
((PDEVICE_EXTENSION)(pDev->DeviceExtension))->NextDriverDeviceObject;IoCopyCurrentIrpStackLocationToNext(pIrp);
//set a completion routine
IoSetCompletionRoutine(pIrp,
CreateComplete,
&event,
TRUE,
TRUE,
TRUE);//pass the irp down
ntRet = IoCallDriver(pNextDevice, pIrp);if (ntRet == STATUS_PENDING)
{
//wait for the event that is signalled in our completion
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);//get the real success code
ntRet = pIrp->IoStatus.Status;
}//if the file was opened
if (NT_SUCCESS(ntRet))
{
//do some stuff that I didn’t want to do in the completion
routine
}//we are done with the irp and ready to complete the request.
IoCompleteRequest(pIrp, IO_DISK_INCREMENT);//done - should I always mark pending and return pending to
prevent the inherently synchronous io
//problem Nagar talks about?
return pIrp->PendingReturned ? STATUS_PENDING : ntRet;
}NTSTATUS CreateComplete(PDEVICE_OBJECT pDev, PIRP pIrp, PKEVENT pContext)
{
//propogate the pending returned flag
if (pIrp->PendingReturned)
{
IoMarkIrpPending(pIrp);
}//alert the mainline thread that the io was completed
KeSetEvent((PKEVENT)pContext, IO_NO_INCREMENT, FALSE);//we need to hold onto this irp for whatever reason
return (STATUS_MORE_PROCESSING_REQUIRED);
}
You are currently subscribed to ntfsd as: xxxxx@ntpsoftware.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)