Skip to contentSkip to conversation

requeuing a Scsi_Cmnd?

DISCUSSION Jeff Garzik 4 participants 7 messages May 11, 2003 – Oct 30, 2003 SCSI

lore
Share & tools
lore
#0 lore raw

This question applies to 2.4 as well as 2.5 (I believe the strategies are different for the two?)

Suppose I am passed several Scsi_Cmnd structures via ->queuecommand. TCQ depth is >1. An event causes the entire queue to be aborted, but I know that the majority of the queue was actually ok. So, my LLD would need to requeue and resend most of the recently-aborted Scsi_Cmnds.

How do I tell the SCSI layer to requeue and resend a Scsi_Cmnd [almost] immediately?

Thanks,

Jeff

#1 lore raw
Quoted 2 lines · Jeff Garzik

Suppose I am passed several Scsi_Cmnd structures via ->queuecommand. TCQ depth is >1. An event causes the entire queue to be aborted, but I know that the majority of the queue was actually ok.

If the event was generated by the application client/SCSI Core, then the normal logic applies -- either cancel all commands, or cancel those which were not completed and finish those which were. I personally prefer the first option (unconditionally cancel all commands on abort/clear task set) since this is what the the spec says.

If the event was generated by other means, i.e. NOT by the application client/SCSI Core, you can error out the unfinished commands and return ok for the finished ones (i.e. finish them).

Quoted 4 lines

So, my LLD would need
to requeue and resend most of the recently-aborted Scsi_Cmnds.

How do I tell the SCSI layer to requeue and resend a Scsi_Cmnd [almost] immediately?

Return BUSY for the task(s) or TASK SET FULL for the task(s), which you want to be requeued almost immediately. There's a difference between those two status codes as to their meaning, as per the spec.

In 2.4, if you return BUSY, the command is tried almost immediately, and if you return TASK SET FULL, it is also tried but things get too convoluted... so you're better off with BUSY.

In 2.5, BUSY and TASK SET FULL are treated the same, so you can either go by the spec and return whichever makes sense, or just return BUSY and you'll be fine for 2.4 and 2.5.

On a side note: remember that, as far as SCSI Transports are concerned, after a task is cancelled (initiator sends ABORT TASK to the TARGET) successfully, the target should NOT send any status/response for that task, as the initiator is NOT expecting ANY responses for a cancelled task (across a transport, i.e. ``below'' a LLDD).

Signature · 1 line
Luben
#2 lore raw
In reply to Jeff Garzik
Quoted 7 lines · Jeff Garzik

This question applies to 2.4 as well as 2.5 (I believe the strategies are different for the two?)

Suppose I am passed several Scsi_Cmnd structures via ->queuecommand. TCQ depth is >1. An event causes the entire queue to be aborted, but I know that the majority of the queue was actually ok. So, my LLD would need to requeue and resend most of the recently-aborted Scsi_Cmnds.

You keep finding these unhandled condidions, sigh. The correct thing to do (since this is a situation identical to QErr set) is to return a check condition to the failing command and to return a status of TASK ABORTED for all the others (SPC3). Of course, the SCSI-2 behaviour was just to expect all tasks to be silently aborted on QErr=1. Neither of these, of course, is coded into the mid-layer.

Quoted 2 lines

How do I tell the SCSI layer to requeue and resend a Scsi_Cmnd [almost] immediately?

Probably the best thing to do is to return DID_BUS_BUSY which will force a fast retry. Note, that's the driver return, *not* the status BUSY, which will force a requeue and take longer---DID_BUS_BUSY will retry immediately from the SCSI tasklet.

James

#3 lore raw
Quoted 7 lines · James Bottomley
Quoted 3 lines · Jeff Garzik

This question applies to 2.4 as well as 2.5 (I believe the strategies are different for the two?)

Suppose I am passed several Scsi_Cmnd structures via ->queuecommand. TCQ depth is >1. An event causes the entire queue to be aborted, but I know that the majority of the queue was actually ok. So, my LLD would need to requeue and resend most of the recently-aborted Scsi_Cmnds.

Quoted 6 lines

You keep finding these unhandled condidions, sigh. The correct thing to do (since this is a situation identical to QErr set) is to return a check condition to the failing command and to return a status of TASK ABORTED for all the others (SPC3). Of course, the SCSI-2 behaviour was just to expect all tasks to be silently aborted on QErr=1. Neither of these, of course, is coded into the mid-layer.

Iff TAS is set and if TST is 001, and there is more than one initiator whose task are being nuked, then this is correct.

Jeff didn't give much information, but it sounds like ABORT/CLEAR TASK SET. Anyway, no point in speculating.

Quoted 7 lines
Quoted 1 line

How do I tell the SCSI layer to requeue and resend a Scsi_Cmnd [almost] immediately?

Probably the best thing to do is to return DID_BUS_BUSY which will force a fast retry. Note, that's the driver return, *not* the status BUSY, which will force a requeue and take longer---DID_BUS_BUSY will retry immediately from the SCSI tasklet.

Uuuuh... Shouldn't this be fixed?

The problem with this is that on BUSY, the LLDD _may_ get the task which got this condition out of order... Furthermore, there's no such thing as BUS BUSY anymore, it's an SPI left over. In case where the transport is unavailable, a service response of SERVICE DELIVERY OR TARGET FAILURE should be returned*. Currently SCSI Core has no facility to return a ``service response''.

* The LLDD should try to reconnect/reestablish before returning this, of course.

I want newer LLDD to return the (task) status codes, so that we have less problems later. They are actually req'd to return (task) status codes by newer versions of their transport protocols.

Signature · 1 line
Luben
#4 lore raw
Quoted 1 line · Luben Tuikov

Uuuuh... Shouldn't this be fixed?

Not really, its design behaviour. BUSY or QUEUE_FULL return means the actual device couldn't accept the command, so we push back on the block queue and suspend until a returning I/O frees the queue. DID_BUS_BUSY indicates transient failures in the host side which are eligible for immediate requeueing

Quoted 2 lines

The problem with this is that on BUSY, the LLDD _may_ get the task which got this condition out of order... Furthermore, there's no

This would be why we don't support barriers.

Quoted 4 lines

such thing as BUS BUSY anymore, it's an SPI left over. In case where the transport is unavailable, a service response of SERVICE DELIVERY OR TARGET FAILURE should be returned*. Currently SCSI Core has no facility to return a ``service response''.

The service response are what the DID_ attributes are about. At the end of the day, though, the mid layer will either

1. Fail the command
2. retry immediately, or
3. retry after another command returns.

That's what the large set of case statements in
scsi_error.c:scsi_decide_disposition() is about.

James

#5 lore raw
In reply to Luben Tuikov
Quoted 18 lines · Luben Tuikov
Quoted 8 lines · James Bottomley
Quoted 3 lines · Jeff Garzik

This question applies to 2.4 as well as 2.5 (I believe the strategies are different for the two?)

Suppose I am passed several Scsi_Cmnd structures via ->queuecommand. TCQ depth is >1. An event causes the entire queue to be aborted, but I know that the majority of the queue was actually ok. So, my LLD would need to requeue and resend most of the recently-aborted Scsi_Cmnds.

Quoted 6 lines

You keep finding these unhandled condidions, sigh. The correct thing to do (since this is a situation identical to QErr set) is to return a check condition to the failing command and to return a status of TASK ABORTED for all the others (SPC3). Of course, the SCSI-2 behaviour was just to expect all tasks to be silently aborted on QErr=1. Neither of these, of course, is coded into the mid-layer.

Quoted 5 lines

Iff TAS is set and if TST is 001, and there is more than one initiator whose task are being nuked, then this is correct.

Jeff didn't give much information, but it sounds like ABORT/CLEAR TASK SET. Anyway, no point in speculating.

I'm working on a SCSI low-level driver that drives SATA host controllers. For ATAPI, it's mainly a passthru. The headache comes in the translation of SCSI->ATA, and in the error handling. The SCSI->ATA translator can be effectively considered a SCSI simulator (or at least that's how I look at it), so like iSCSI I'm creating a software target, and I want my target to be compliant to spec. (Which spec, you ask? Well, initially SCSI-2, but long term James has convinced me SCSI-3)

So for my specific example, I'm passed a bunch of Scsi_Cmnds. I queue them. And then according to spec, an error on the active command will cause the entire queue to abort. Clearly, I do not want to error-out the other probably-valid commands, only the specific one that caused the error. So, the remaining ones need to be retried.

Jeff

#6 lore raw

Jeff,

If the goal is to add a queue depth to hba's w/o a qdma ring, you need a whole pile of tasklets and thread queues.

If you have a hba with qdma ring(s) then it is just like standard scsi.

Cheers,

Andre Hedrick
LAD Storage Consulting Group

Quoted 53 lines · Jeff Garzik
Quoted 23 lines · Luben Tuikov
Quoted 13 lines · James Bottomley
Quoted 8 lines · Jeff Garzik

This question applies to 2.4 as well as 2.5 (I believe the strategies are different for the two?)

Suppose I am passed several Scsi_Cmnd structures via ->queuecommand. TCQ depth is >1. An event causes the entire queue to be aborted, but I know that the majority of the queue was actually ok. So, my LLD would need to requeue and resend most of the recently-aborted Scsi_Cmnds.

Quoted 6 lines

You keep finding these unhandled condidions, sigh. The correct thing to do (since this is a situation identical to QErr set) is to return a check condition to the failing command and to return a status of TASK ABORTED for all the others (SPC3). Of course, the SCSI-2 behaviour was just to expect all tasks to be silently aborted on QErr=1. Neither of these, of course, is coded into the mid-layer.

Quoted 5 lines

Iff TAS is set and if TST is 001, and there is more than one initiator whose task are being nuked, then this is correct.

Jeff didn't give much information, but it sounds like ABORT/CLEAR TASK SET. Anyway, no point in speculating.

I'm working on a SCSI low-level driver that drives SATA host controllers. For ATAPI, it's mainly a passthru. The headache comes in the translation of SCSI->ATA, and in the error handling. The SCSI->ATA translator can be effectively considered a SCSI simulator (or at least that's how I look at it), so like iSCSI I'm creating a software target, and I want my target to be compliant to spec. (Which spec, you ask? Well, initially SCSI-2, but long term James has convinced me SCSI-3)

So for my specific example, I'm passed a bunch of Scsi_Cmnds. I queue them. And then according to spec, an error on the active command will cause the entire queue to abort. Clearly, I do not want to error-out the other probably-valid commands, only the specific one that caused the error. So, the remaining ones need to be retried.

Jeff

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html