diff options
author | Hannes Reinecke <hare@suse.de> | 2011-01-18 04:13:11 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-12 11:33:08 -0500 |
commit | 63583cca745f440167bf27877182dc13e19d4bcf (patch) | |
tree | c1eb3ec5d35cd71c6373e82992710c91f2cb8bdd /drivers/scsi/scsi_lib.c | |
parent | 7a1e9d829f8bd821466c5ea834ad6f378740d2be (diff) |
[SCSI] Add detailed SCSI I/O errors
Instead of just passing 'EIO' for any I/O error we should be
notifying the upper layers with more details about the cause
of this error.
Update the possible I/O errors to:
- ENOLINK: Link failure between host and target
- EIO: Retryable I/O error
- EREMOTEIO: Non-retryable I/O error
- EBADE: I/O error restricted to the I_T_L nexus
'Retryable' in this context means that an I/O error _might_ be
restricted to the I_T_L nexus (vulgo: path), so retrying on another
nexus / path might succeed.
'Non-retryable' in general refers to a target failure, so this
error will always be generated regardless of the I_T_L nexus
it was send on.
I/O errors restricted to the I_T_L nexus might be retried
on another nexus / path, but they should _not_ be queued
if no paths are available.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9045c52abd25..8d4ef8efa3cd 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -667,6 +667,30 @@ void scsi_release_buffers(struct scsi_cmnd *cmd) | |||
667 | } | 667 | } |
668 | EXPORT_SYMBOL(scsi_release_buffers); | 668 | EXPORT_SYMBOL(scsi_release_buffers); |
669 | 669 | ||
670 | static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result) | ||
671 | { | ||
672 | int error = 0; | ||
673 | |||
674 | switch(host_byte(result)) { | ||
675 | case DID_TRANSPORT_FAILFAST: | ||
676 | error = -ENOLINK; | ||
677 | break; | ||
678 | case DID_TARGET_FAILURE: | ||
679 | cmd->result |= (DID_OK << 16); | ||
680 | error = -EREMOTEIO; | ||
681 | break; | ||
682 | case DID_NEXUS_FAILURE: | ||
683 | cmd->result |= (DID_OK << 16); | ||
684 | error = -EBADE; | ||
685 | break; | ||
686 | default: | ||
687 | error = -EIO; | ||
688 | break; | ||
689 | } | ||
690 | |||
691 | return error; | ||
692 | } | ||
693 | |||
670 | /* | 694 | /* |
671 | * Function: scsi_io_completion() | 695 | * Function: scsi_io_completion() |
672 | * | 696 | * |
@@ -737,7 +761,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
737 | req->sense_len = len; | 761 | req->sense_len = len; |
738 | } | 762 | } |
739 | if (!sense_deferred) | 763 | if (!sense_deferred) |
740 | error = -EIO; | 764 | error = __scsi_error_from_host_byte(cmd, result); |
741 | } | 765 | } |
742 | 766 | ||
743 | req->resid_len = scsi_get_resid(cmd); | 767 | req->resid_len = scsi_get_resid(cmd); |
@@ -796,7 +820,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
796 | if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) | 820 | if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) |
797 | return; | 821 | return; |
798 | 822 | ||
799 | error = -EIO; | 823 | error = __scsi_error_from_host_byte(cmd, result); |
800 | 824 | ||
801 | if (host_byte(result) == DID_RESET) { | 825 | if (host_byte(result) == DID_RESET) { |
802 | /* Third party bus reset or reset for error recovery | 826 | /* Third party bus reset or reset for error recovery |