scsi: explicitly list guest-recoverable sense codes
It's not really possible to fit all sense codes into errno codes, especially in such a way that sense codes can be properly categorized as either guest-recoverable or host-handled. Create a new function that checks for guest recoverable sense, then scsi_sense_buf_to_errno only needs to be called for host handled sense codes. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
d31347f5ff
commit
bdf9613b7f
@ -454,14 +454,13 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||||
* pause the host.
|
||||
*/
|
||||
assert(r->status && *r->status);
|
||||
error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
|
||||
if (error == ECANCELED || error == EAGAIN || error == ENOTCONN ||
|
||||
error == 0) {
|
||||
if (scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) {
|
||||
/* These errors are handled by guest. */
|
||||
sdc->update_sense(&r->req);
|
||||
scsi_req_complete(&r->req, *r->status);
|
||||
return true;
|
||||
}
|
||||
error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
|
||||
break;
|
||||
case ENOMEDIUM:
|
||||
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
|
||||
|
@ -106,6 +106,7 @@ extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
|
||||
|
||||
int scsi_sense_to_errno(int key, int asc, int ascq);
|
||||
int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size);
|
||||
bool scsi_sense_buf_is_guest_recoverable(const uint8_t *sense, size_t sense_size);
|
||||
|
||||
int scsi_convert_sense(uint8_t *in_buf, int in_len,
|
||||
uint8_t *buf, int len, bool fixed);
|
||||
|
43
scsi/utils.c
43
scsi/utils.c
@ -336,6 +336,38 @@ int scsi_convert_sense(uint8_t *in_buf, int in_len,
|
||||
}
|
||||
}
|
||||
|
||||
static bool scsi_sense_is_guest_recoverable(int key, int asc, int ascq)
|
||||
{
|
||||
switch (key) {
|
||||
case NO_SENSE:
|
||||
case RECOVERED_ERROR:
|
||||
case UNIT_ATTENTION:
|
||||
case ABORTED_COMMAND:
|
||||
return true;
|
||||
case NOT_READY:
|
||||
case ILLEGAL_REQUEST:
|
||||
case DATA_PROTECT:
|
||||
/* Parse ASCQ */
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ((asc << 8) | ascq) {
|
||||
case 0x1a00: /* PARAMETER LIST LENGTH ERROR */
|
||||
case 0x2000: /* INVALID OPERATION CODE */
|
||||
case 0x2400: /* INVALID FIELD IN CDB */
|
||||
case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */
|
||||
case 0x2600: /* INVALID FIELD IN PARAMETER LIST */
|
||||
|
||||
case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */
|
||||
case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_sense_to_errno(int key, int asc, int ascq)
|
||||
{
|
||||
switch (key) {
|
||||
@ -391,6 +423,17 @@ int scsi_sense_buf_to_errno(const uint8_t *in_buf, size_t in_len)
|
||||
return scsi_sense_to_errno(sense.key, sense.asc, sense.ascq);
|
||||
}
|
||||
|
||||
bool scsi_sense_buf_is_guest_recoverable(const uint8_t *in_buf, size_t in_len)
|
||||
{
|
||||
SCSISense sense;
|
||||
if (in_len < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sense = scsi_parse_sense_buf(in_buf, in_len);
|
||||
return scsi_sense_is_guest_recoverable(sense.key, sense.asc, sense.ascq);
|
||||
}
|
||||
|
||||
const char *scsi_command_name(uint8_t cmd)
|
||||
{
|
||||
static const char *names[] = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user