SL_PENDING_RETURNED

The purpose of PendingReturned is really to communicate the state of the latest SL_PENDING_RETURNED stack location to the completion routine or to IopsCompleteRequest tail.
The completion routine will use PendingReturned to propagate SL_PENDING_RETURNED to its current stack location, and also can use it for deciding whether it need to call KeSetEvent for a little bit of optimization.

At any completion routine level, PendingReturned needs to correspond to the most recent SL_PENDING_RETURNED, not to some accumulated SL_PENDING_RETURNED value.

> No. Well, not in the code I’m looking at in any case. It sets Irp->PendingReturned before calling the

completion routine based on whether the NEXT LOWER driver’s I/O stack Location has
SL_PENDING_RETURNED set.

Sorry Peter and Harald, but:

  1. as Harald correctly noticed, IoCompleteRequest does the following before calling each next CR:

Irp->PendingReturned = stackPointer->Control & SL_PENDING_RETURNED;

which is logically:

Irp->PendingReturned = IoMarkIrpPendingWasCalledOnThisStackLoc();

  1. There is a rule for CRs to do “if( Irp->PendingReturned ) IoMarkIrpPending(Irp);”.

  2. Imagine some IoMarkIrpPending was executed. Then the next IoCompleteRequest will (according to 1) set Irp->PendingReturned to TRUE. Then it will pop 1 stack location off the IRP and call the CR. The CR will, accoding to 2), call IoMarkIrpPending() on the previous SP.

  3. So the whole IRP is inwound, and the final state of Irp->PendingReturned is “TRUE if at least any IoMarkIrpPending was ever made on the IRP, FALSE otherwise”.

This is what I was speaking about.

To make this statement wrong, on what you insist, at least some CR must forget to do “if( Irp->PendingReturned ) IoMarkIrpPending(Irp);”.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

This does exactly what I said it did. Irp->PendingReturned is non-zero if SL_PENDING_RETURNED is set in the next lower stack location, and is zero otherwise. So, the statement that Irp->PendingReturned “once it is set, it is not cleared” is not correct.

Silly argument.

C’mon… you know how this works, and I know how this works. We’ve both known how this works for 20 years, I suspect. Why are we wasting our time and everyone else’s time with this discussion?

Suppose:

DISPATCH ROUTINE:
a) Clears an event.
b) Sets a completion routine, passing the event as context
c) IoCallDriver’s the IRP to the next driver
d) Waits on the (cleared/unsignaled) event

COMPLETION ROUTINE:
e) Gets the completion callback
f) Sets the event
g) returns STATUS_MORE_PROCESSING_REQUIRED from the completion routine

DISPATCH ROUTINE AGAIN:
f) Wakes up in the dispatch routine
g) Complete the IRP with STATUS_SUCCESS
h) returns STATUS_SUCCESS

We all know this is a super-common design pattern. It’s the IoForwardIrpSynchronously pattern.

Irp->PendingReturned is NOT set in this case. And you do NOT propagate the pending bit in this case. If you WERE to propagate the pending bit in this case, your code would be wrong.

Somebody stated this previously, but it’s worth restating: The rule is simply that if you return STATUS_PENDING from your Dispatch Routine, you MUST in all cases set SL_PENDING_RETURNED in your I/O Stack Location *before* the I/O Manager process that stack location.

Again… I don’t see how this thread is gaining anyone who reads the archives a better understanding of this complex topic. We have a group of people who are each trying to demonstrate their understanding by posting three sentences on a complex topic… sometimes as a barrage of out of order replies, in some cases without the necessary context to those sentences, and in some cases I suspect without bothering to carefully read the previous posts.

Given that we’re getting exactly nowhere, can we just let it be at this point?

Peter
OSR
@OSRDrivers