target: Split transport_send_check_condition_and_sense()
Move the code for translating a sense_reason_t code into a SCSI status ASC and ASCQ codes from transport_send_check_condition_and_sense() into the new function translate_sense_reason(). Convert the switch statement that performs the translation into table-driven code. Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com> Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
46d5bd62ef
commit
ab78fef4d5
1 changed files with 148 additions and 235 deletions
|
@ -2628,13 +2628,155 @@ void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector)
|
||||||
put_unaligned_be64(bad_sector, &buffer[12]);
|
put_unaligned_be64(bad_sector, &buffer[12]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sense_info {
|
||||||
|
u8 key;
|
||||||
|
u8 asc;
|
||||||
|
u8 ascq;
|
||||||
|
bool add_sector_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sense_info sense_info_table[] = {
|
||||||
|
[TCM_NO_SENSE] = {
|
||||||
|
.key = NOT_READY
|
||||||
|
},
|
||||||
|
[TCM_NON_EXISTENT_LUN] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x25 /* LOGICAL UNIT NOT SUPPORTED */
|
||||||
|
},
|
||||||
|
[TCM_UNSUPPORTED_SCSI_OPCODE] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x20, /* INVALID COMMAND OPERATION CODE */
|
||||||
|
},
|
||||||
|
[TCM_SECTOR_COUNT_TOO_MANY] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x20, /* INVALID COMMAND OPERATION CODE */
|
||||||
|
},
|
||||||
|
[TCM_UNKNOWN_MODE_PAGE] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x24, /* INVALID FIELD IN CDB */
|
||||||
|
},
|
||||||
|
[TCM_CHECK_CONDITION_ABORT_CMD] = {
|
||||||
|
.key = ABORTED_COMMAND,
|
||||||
|
.asc = 0x29, /* BUS DEVICE RESET FUNCTION OCCURRED */
|
||||||
|
.ascq = 0x03,
|
||||||
|
},
|
||||||
|
[TCM_INCORRECT_AMOUNT_OF_DATA] = {
|
||||||
|
.key = ABORTED_COMMAND,
|
||||||
|
.asc = 0x0c, /* WRITE ERROR */
|
||||||
|
.ascq = 0x0d, /* NOT ENOUGH UNSOLICITED DATA */
|
||||||
|
},
|
||||||
|
[TCM_INVALID_CDB_FIELD] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x24, /* INVALID FIELD IN CDB */
|
||||||
|
},
|
||||||
|
[TCM_INVALID_PARAMETER_LIST] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */
|
||||||
|
},
|
||||||
|
[TCM_PARAMETER_LIST_LENGTH_ERROR] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */
|
||||||
|
},
|
||||||
|
[TCM_UNEXPECTED_UNSOLICITED_DATA] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x0c, /* WRITE ERROR */
|
||||||
|
.ascq = 0x0c, /* UNEXPECTED_UNSOLICITED_DATA */
|
||||||
|
},
|
||||||
|
[TCM_SERVICE_CRC_ERROR] = {
|
||||||
|
.key = ABORTED_COMMAND,
|
||||||
|
.asc = 0x47, /* PROTOCOL SERVICE CRC ERROR */
|
||||||
|
.ascq = 0x05, /* N/A */
|
||||||
|
},
|
||||||
|
[TCM_SNACK_REJECTED] = {
|
||||||
|
.key = ABORTED_COMMAND,
|
||||||
|
.asc = 0x11, /* READ ERROR */
|
||||||
|
.ascq = 0x13, /* FAILED RETRANSMISSION REQUEST */
|
||||||
|
},
|
||||||
|
[TCM_WRITE_PROTECTED] = {
|
||||||
|
.key = DATA_PROTECT,
|
||||||
|
.asc = 0x27, /* WRITE PROTECTED */
|
||||||
|
},
|
||||||
|
[TCM_ADDRESS_OUT_OF_RANGE] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x21, /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
|
||||||
|
},
|
||||||
|
[TCM_CHECK_CONDITION_UNIT_ATTENTION] = {
|
||||||
|
.key = UNIT_ATTENTION,
|
||||||
|
},
|
||||||
|
[TCM_CHECK_CONDITION_NOT_READY] = {
|
||||||
|
.key = NOT_READY,
|
||||||
|
},
|
||||||
|
[TCM_MISCOMPARE_VERIFY] = {
|
||||||
|
.key = MISCOMPARE,
|
||||||
|
.asc = 0x1d, /* MISCOMPARE DURING VERIFY OPERATION */
|
||||||
|
.ascq = 0x00,
|
||||||
|
},
|
||||||
|
[TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x10,
|
||||||
|
.ascq = 0x01, /* LOGICAL BLOCK GUARD CHECK FAILED */
|
||||||
|
.add_sector_info = true,
|
||||||
|
},
|
||||||
|
[TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x10,
|
||||||
|
.ascq = 0x02, /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */
|
||||||
|
.add_sector_info = true,
|
||||||
|
},
|
||||||
|
[TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED] = {
|
||||||
|
.key = ILLEGAL_REQUEST,
|
||||||
|
.asc = 0x10,
|
||||||
|
.ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
|
||||||
|
.add_sector_info = true,
|
||||||
|
},
|
||||||
|
[TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = {
|
||||||
|
/*
|
||||||
|
* Returning ILLEGAL REQUEST would cause immediate IO errors on
|
||||||
|
* Solaris initiators. Returning NOT READY instead means the
|
||||||
|
* operations will be retried a finite number of times and we
|
||||||
|
* can survive intermittent errors.
|
||||||
|
*/
|
||||||
|
.key = NOT_READY,
|
||||||
|
.asc = 0x08, /* LOGICAL UNIT COMMUNICATION FAILURE */
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason)
|
||||||
|
{
|
||||||
|
const struct sense_info *si;
|
||||||
|
u8 *buffer = cmd->sense_buffer;
|
||||||
|
int r = (__force int)reason;
|
||||||
|
u8 asc, ascq;
|
||||||
|
|
||||||
|
if (r < ARRAY_SIZE(sense_info_table) && sense_info_table[r].key)
|
||||||
|
si = &sense_info_table[r];
|
||||||
|
else
|
||||||
|
si = &sense_info_table[(__force int)
|
||||||
|
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE];
|
||||||
|
|
||||||
|
buffer[SPC_SENSE_KEY_OFFSET] = si->key;
|
||||||
|
if (reason == TCM_CHECK_CONDITION_UNIT_ATTENTION) {
|
||||||
|
core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
|
||||||
|
WARN_ON_ONCE(asc == 0);
|
||||||
|
} else if (si->asc == 0) {
|
||||||
|
WARN_ON_ONCE(cmd->scsi_asc == 0);
|
||||||
|
asc = cmd->scsi_asc;
|
||||||
|
ascq = cmd->scsi_ascq;
|
||||||
|
} else {
|
||||||
|
asc = si->asc;
|
||||||
|
ascq = si->ascq;
|
||||||
|
}
|
||||||
|
buffer[SPC_ASC_KEY_OFFSET] = asc;
|
||||||
|
buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
|
||||||
|
if (si->add_sector_info)
|
||||||
|
transport_err_sector_info(cmd->sense_buffer, cmd->bad_sector);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
transport_send_check_condition_and_sense(struct se_cmd *cmd,
|
transport_send_check_condition_and_sense(struct se_cmd *cmd,
|
||||||
sense_reason_t reason, int from_transport)
|
sense_reason_t reason, int from_transport)
|
||||||
{
|
{
|
||||||
unsigned char *buffer = cmd->sense_buffer;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u8 asc = 0, ascq = 0;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||||
if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
|
if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
|
||||||
|
@ -2644,242 +2786,13 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
|
||||||
cmd->se_cmd_flags |= SCF_SENT_CHECK_CONDITION;
|
cmd->se_cmd_flags |= SCF_SENT_CHECK_CONDITION;
|
||||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||||
|
|
||||||
if (!reason && from_transport)
|
if (!from_transport) {
|
||||||
goto after_reason;
|
|
||||||
|
|
||||||
if (!from_transport)
|
|
||||||
cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE;
|
cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE;
|
||||||
|
translate_sense_reason(cmd, reason);
|
||||||
/*
|
|
||||||
* Actual SENSE DATA, see SPC-3 7.23.2 SPC_SENSE_KEY_OFFSET uses
|
|
||||||
* SENSE KEY values from include/scsi/scsi.h
|
|
||||||
*/
|
|
||||||
switch (reason) {
|
|
||||||
case TCM_NO_SENSE:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* Not Ready */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
|
|
||||||
/* NO ADDITIONAL SENSE INFORMATION */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0;
|
|
||||||
break;
|
|
||||||
case TCM_NON_EXISTENT_LUN:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* LOGICAL UNIT NOT SUPPORTED */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x25;
|
|
||||||
break;
|
|
||||||
case TCM_UNSUPPORTED_SCSI_OPCODE:
|
|
||||||
case TCM_SECTOR_COUNT_TOO_MANY:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* INVALID COMMAND OPERATION CODE */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x20;
|
|
||||||
break;
|
|
||||||
case TCM_UNKNOWN_MODE_PAGE:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* INVALID FIELD IN CDB */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x24;
|
|
||||||
break;
|
|
||||||
case TCM_CHECK_CONDITION_ABORT_CMD:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ABORTED COMMAND */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
|
||||||
/* BUS DEVICE RESET FUNCTION OCCURRED */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x29;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x03;
|
|
||||||
break;
|
|
||||||
case TCM_INCORRECT_AMOUNT_OF_DATA:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ABORTED COMMAND */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
|
||||||
/* WRITE ERROR */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
|
|
||||||
/* NOT ENOUGH UNSOLICITED DATA */
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x0d;
|
|
||||||
break;
|
|
||||||
case TCM_INVALID_CDB_FIELD:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* INVALID FIELD IN CDB */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x24;
|
|
||||||
break;
|
|
||||||
case TCM_INVALID_PARAMETER_LIST:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* INVALID FIELD IN PARAMETER LIST */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x26;
|
|
||||||
break;
|
|
||||||
case TCM_PARAMETER_LIST_LENGTH_ERROR:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* PARAMETER LIST LENGTH ERROR */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x1a;
|
|
||||||
break;
|
|
||||||
case TCM_UNEXPECTED_UNSOLICITED_DATA:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ABORTED COMMAND */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
|
||||||
/* WRITE ERROR */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
|
|
||||||
/* UNEXPECTED_UNSOLICITED_DATA */
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x0c;
|
|
||||||
break;
|
|
||||||
case TCM_SERVICE_CRC_ERROR:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ABORTED COMMAND */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
|
||||||
/* PROTOCOL SERVICE CRC ERROR */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x47;
|
|
||||||
/* N/A */
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x05;
|
|
||||||
break;
|
|
||||||
case TCM_SNACK_REJECTED:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ABORTED COMMAND */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
|
||||||
/* READ ERROR */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x11;
|
|
||||||
/* FAILED RETRANSMISSION REQUEST */
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x13;
|
|
||||||
break;
|
|
||||||
case TCM_WRITE_PROTECTED:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* DATA PROTECT */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
|
|
||||||
/* WRITE PROTECTED */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x27;
|
|
||||||
break;
|
|
||||||
case TCM_ADDRESS_OUT_OF_RANGE:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* LOGICAL BLOCK ADDRESS OUT OF RANGE */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x21;
|
|
||||||
break;
|
|
||||||
case TCM_CHECK_CONDITION_UNIT_ATTENTION:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* UNIT ATTENTION */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
|
|
||||||
core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = asc;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
|
|
||||||
break;
|
|
||||||
case TCM_CHECK_CONDITION_NOT_READY:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* Not Ready */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = cmd->scsi_asc;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = cmd->scsi_ascq;
|
|
||||||
break;
|
|
||||||
case TCM_MISCOMPARE_VERIFY:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = MISCOMPARE;
|
|
||||||
/* MISCOMPARE DURING VERIFY OPERATION */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x1d;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x00;
|
|
||||||
break;
|
|
||||||
case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* LOGICAL BLOCK GUARD CHECK FAILED */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x01;
|
|
||||||
transport_err_sector_info(buffer, cmd->bad_sector);
|
|
||||||
break;
|
|
||||||
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x02;
|
|
||||||
transport_err_sector_info(buffer, cmd->bad_sector);
|
|
||||||
break;
|
|
||||||
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/* ILLEGAL REQUEST */
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
||||||
/* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
|
|
||||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x03;
|
|
||||||
transport_err_sector_info(buffer, cmd->bad_sector);
|
|
||||||
break;
|
|
||||||
case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
|
|
||||||
default:
|
|
||||||
/* CURRENT ERROR */
|
|
||||||
buffer[0] = 0x70;
|
|
||||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
|
||||||
/*
|
|
||||||
* Returning ILLEGAL REQUEST would cause immediate IO errors on
|
|
||||||
* Solaris initiators. Returning NOT READY instead means the
|
|
||||||
* operations will be retried a finite number of times and we
|
|
||||||
* can survive intermittent errors.
|
|
||||||
*/
|
|
||||||
buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
|
|
||||||
/* LOGICAL UNIT COMMUNICATION FAILURE */
|
|
||||||
buffer[SPC_ASC_KEY_OFFSET] = 0x08;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* This code uses linux/include/scsi/scsi.h SAM status codes!
|
|
||||||
*/
|
|
||||||
cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
|
cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
|
||||||
/*
|
|
||||||
* Automatically padded, this value is encoded in the fabric's
|
|
||||||
* data_length response PDU containing the SCSI defined sense data.
|
|
||||||
*/
|
|
||||||
cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER;
|
cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
after_reason:
|
|
||||||
trace_target_cmd_complete(cmd);
|
trace_target_cmd_complete(cmd);
|
||||||
return cmd->se_tfo->queue_status(cmd);
|
return cmd->se_tfo->queue_status(cmd);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue