|
|
|
[RFC] Rearrange code in scsi_io_completion | |
| [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] | |
Here's a new patch to rework scsi_io_completion. I tried to take into
account comments on the old patch set.
A lot of the old code turned out to be redundant and got removed. And
some of the remaining code is present only to add some error messages
to the log; I'm not at all sure they are really needed.
Perhaps most significantly, the test for host_byte(result) == DID_RESET
was moved in front of the other analysis code. This seemed to be the
proper place for it; please tell me if it isn't.
This has hardly been tested at all. All I can say for sure is that it
works if no commands fail... :-)
Alan Stern
Index: usb-2.6/drivers/scsi/scsi_lib.c
===================================================================
--- usb-2.6.orig/drivers/scsi/scsi_lib.c
+++ usb-2.6/drivers/scsi/scsi_lib.c
@@ -859,6 +859,8 @@ void scsi_io_completion(struct scsi_cmnd
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int sense_deferred = 0;
+ enum {ACTION_FAIL, ACTION_REQUEUE, ACTION_RETRY,
+ ACTION_DELAYED_RETRY} action;
if (result) {
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
@@ -909,11 +911,15 @@ void scsi_io_completion(struct scsi_cmnd
if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
return;
this_count = blk_rq_bytes(req);
+ action = ACTION_FAIL;
- /* good_bytes = 0, or (inclusive) there were leftovers and
- * result = 0, so scsi_end_request couldn't retry.
- */
- if (sense_valid && !sense_deferred) {
+ if (host_byte(result) == DID_RESET) {
+ /* Third party bus reset or reset for error recovery
+ * reasons. Just retry the command and see what
+ * happens.
+ */
+ action = ACTION_RETRY;
+ } else if (sense_valid && !sense_deferred) {
switch (sshdr.sense_key) {
case UNIT_ATTENTION:
if (cmd->device->removable) {
@@ -921,16 +927,13 @@ void scsi_io_completion(struct scsi_cmnd
* and quietly refuse further access.
*/
cmd->device->changed = 1;
- scsi_end_request(cmd, -EIO, this_count, 1);
- return;
} else {
/* Must have been a power glitch, or a
* bus reset. Could not have been a
* media change, so we just retry the
- * request and see what happens.
+ * command and see what happens.
*/
- scsi_requeue_command(q, cmd);
- return;
+ action = ACTION_RETRY;
}
break;
case ILLEGAL_REQUEST:
@@ -946,22 +949,13 @@ void scsi_io_completion(struct scsi_cmnd
sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
(cmd->cmnd[0] == READ_10 ||
cmd->cmnd[0] == WRITE_10)) {
+ /* This will issue a new 6-byte command. */
cmd->device->use_10_for_rw = 0;
- /* This will cause a retry with a
- * 6-byte command.
- */
- scsi_requeue_command(q, cmd);
- } else if (sshdr.asc == 0x10) /* DIX */
- scsi_end_request(cmd, -EIO, this_count, 0);
- else
- scsi_end_request(cmd, -EIO, this_count, 1);
- return;
- case ABORTED_COMMAND:
- if (sshdr.asc == 0x10) { /* DIF */
- scsi_end_request(cmd, -EIO, this_count, 0);
- return;
+ action = ACTION_REQUEUE;
}
break;
+ case ABORTED_COMMAND:
+ break;
case NOT_READY:
/* If the device is in the process of becoming
* ready, or has a temporary blockage, retry.
@@ -975,19 +969,16 @@ void scsi_io_completion(struct scsi_cmnd
case 0x07: /* operation in progress */
case 0x08: /* Long write in progress */
case 0x09: /* self test in progress */
- scsi_requeue_command(q, cmd);
- return;
- default:
+ action = ACTION_DELAYED_RETRY;
break;
}
}
- if (!(req->cmd_flags & REQ_QUIET))
+ if (!(req->cmd_flags & REQ_QUIET) &&
+ action == ACTION_FAIL)
scsi_cmd_print_sense_hdr(cmd,
"Device not ready",
&sshdr);
-
- scsi_end_request(cmd, -EIO, this_count, 1);
- return;
+ break;
case VOLUME_OVERFLOW:
if (!(req->cmd_flags & REQ_QUIET)) {
scmd_printk(KERN_INFO, cmd,
@@ -996,28 +987,38 @@ void scsi_io_completion(struct scsi_cmnd
scsi_print_sense("", cmd);
}
/* See SSC3rXX or current. */
- scsi_end_request(cmd, -EIO, this_count, 1);
- return;
- default:
break;
}
}
- if (host_byte(result) == DID_RESET) {
- /* Third party bus reset or reset for error recovery
- * reasons. Just retry the request and see what
- * happens.
+
+ switch (action) {
+ case ACTION_FAIL:
+ /* Give up and fail the remainder of the request */
+ if (result) {
+ if (!(req->cmd_flags & REQ_QUIET)) {
+ scsi_print_result(cmd);
+ if (driver_byte(result) & DRIVER_SENSE)
+ scsi_print_sense("", cmd);
+ }
+ }
+ blk_end_request(req, -EIO, blk_rq_bytes(req));
+ scsi_next_command(cmd);
+ break;
+ case ACTION_REQUEUE:
+ /* Put the request back at the head of the queue.
+ * A new command will be prepared and issued.
*/
scsi_requeue_command(q, cmd);
- return;
- }
- if (result) {
- if (!(req->cmd_flags & REQ_QUIET)) {
- scsi_print_result(cmd);
- if (driver_byte(result) & DRIVER_SENSE)
- scsi_print_sense("", cmd);
- }
+ break;
+ case ACTION_RETRY:
+ /* Retry the same command immediately */
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
+ break;
+ case ACTION_DELAYED_RETRY:
+ /* Retry the same command after a delay */
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
+ break;
}
- scsi_end_request(cmd, -EIO, this_count, !result);
}
static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[Site Home] [Kernel Newbies] [Linux SCSI Target Infrastructure] [Share Photos] [IDE] [Security] [Git] [Netfilter] [Bugtraq] [Rubini] [Photo] [Yosemite] [Yosemite News] [MIPS Linux] [ARM Linux] [Linux Security] [Linux RAID] [Linux ATA RAID] [Samba] [Video 4 Linux] [Device Mapper] [Linux Resources]
![]() |
![]() |