Sense handling improvements

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4408 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2012-07-18 21:28:57 +00:00
parent 408b67c80f
commit 955113f493
16 changed files with 230 additions and 131 deletions
+1 -1
View File
@@ -249,7 +249,7 @@ static int send_rsp(struct iu_entry *iue, struct scst_cmd *sc,
int sense_data_len;
sc_sense = scst_cmd_get_sense_buffer(sc);
if (SCST_SENSE_VALID(sc_sense)) {
if (scst_sense_valid(sc_sense)) {
sense_data_len
= min(scst_cmd_get_sense_buffer_len(sc),
SRP_RSP_SENSE_DATA_LEN);
+1 -1
View File
@@ -979,7 +979,7 @@ static void iscsi_init_status_rsp(struct iscsi_cmnd *rsp,
rsp_hdr->cmd_status = status;
rsp_hdr->itt = cmnd_hdr(req)->itt;
if (SCST_SENSE_VALID(sense_buf)) {
if (scst_sense_valid(sense_buf)) {
TRACE_DBG("%s", "SENSE VALID");
sg = rsp->sg = rsp->rsp_sg;
+1 -1
View File
@@ -1641,7 +1641,7 @@ mpt_xmit_response(struct scst_cmd *scst_cmd)
goto out_tgt_free;
}
if (SCST_SENSE_VALID(prm.sense_buffer)) {
if (scst_sense_valid(prm.sense_buffer)) {
mpt_set_sense_info(prm.tgt->priv, prm.cmd->CMD,
prm.sense_buffer_len, prm.sense_buffer);
}
+4 -4
View File
@@ -440,7 +440,7 @@ static int mvst_prep_resp_frame(struct mvst_prm *prm,
req_len += sizeof(struct ssp_frame_header);
req_len += 24;
if (datapres == SENSE_DATA) {
if (SCST_SENSE_VALID(prm->sense_buffer))
if (scst_sense_valid(prm->sense_buffer))
req_len += prm->sense_buffer_len;
else
datapres = 0;
@@ -605,7 +605,7 @@ static int mvst_prep_data_frame(struct mvst_prm *prm,
delivery_q->slot_nm = tag;
if (datapres == SENSE_DATA) {
if (SCST_SENSE_VALID(prm->sense_buffer))
if (scst_sense_valid(prm->sense_buffer))
datapres = SENSE_DATA;
else
datapres = 0;
@@ -1791,11 +1791,11 @@ static int mvst_notify_unit_attention(struct scst_aen *aen)
TRACE_ENTRY();
if (aen->aen_sense[0] == 0x72) {
if (scst_sense_response_code(aen->aen_sense) == 0x72) {
key = aen->aen_sense[1]; /* Sense Key */
asc = aen->aen_sense[2]; /* ASC */
ascq = aen->aen_sense[3]; /* ASCQ */
} else if (aen->aen_sense[0] == 0x70) {
} else if (scst_sense_response_code(aen->aen_sense) == 0x70) {
key = aen->aen_sense[2]; /* Sense Key */
asc = aen->aen_sense[12]; /* ASC */
ascq = aen->aen_sense[13]; /* ASCQ */
+3 -3
View File
@@ -2528,7 +2528,7 @@ static int q2t_pre_xmit_response(struct q2t_cmd *cmd,
* in *xmit_response() below
*/
if (q2t_has_data(cmd)) {
if (SCST_SENSE_VALID(prm->sense_buffer) ||
if (scst_sense_valid(prm->sense_buffer) ||
(IS_FWI2_CAPABLE(ha) &&
(prm->rq_result != 0))) {
prm->add_status_pkt = 1;
@@ -2589,7 +2589,7 @@ static void q2x_init_ctio_ret_entry(ctio_ret_entry_t *ctio_m1,
ctio_m1->scsi_status = cpu_to_le16(prm->rq_result);
ctio_m1->residual = cpu_to_le32(prm->residual);
if (SCST_SENSE_VALID(prm->sense_buffer)) {
if (scst_sense_valid(prm->sense_buffer)) {
if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 1))
ctio_m1->flags |= cpu_to_le16(OF_EXPL_CONF | OF_CONF_REQ);
ctio_m1->scsi_status |= cpu_to_le16(SS_SENSE_LEN_VALID);
@@ -2795,7 +2795,7 @@ static void q24_init_ctio_ret_entry(ctio7_status0_entry_t *ctio,
}
ctio->residual = cpu_to_le32(prm->residual);
ctio->scsi_status = cpu_to_le16(prm->rq_result);
if (SCST_SENSE_VALID(prm->sense_buffer)) {
if (scst_sense_valid(prm->sense_buffer)) {
int i;
ctio1 = (ctio7_status1_entry_t *)ctio;
if (q2t_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) {
+6
View File
@@ -4149,6 +4149,12 @@ int scst_alloc_set_sense(struct scst_cmd *cmd, int atomic,
int scst_set_sense(uint8_t *buffer, int len, bool d_sense,
int key, int asc, int ascq);
#define SCST_INVAL_FIELD_BIT_OFFS_VALID 0x8000
int scst_set_invalid_field_in_cdb(struct scst_cmd *cmd, int field_offs,
int bit_offs);
int scst_set_invalid_field_in_parm_list(struct scst_cmd *cmd, int field_offs,
int bit_offs);
bool scst_is_ua_sense(const uint8_t *sense, int len);
bool scst_analyze_sense(const uint8_t *sense, int len,
+18 -6
View File
@@ -5,7 +5,8 @@
* Copyright (C) 2007 - 2010 ID7 Ltd.
* Copyright (C) 2010 - 2012 SCST Ltd.
*
* Contains common SCST constants.
* Contains common SCST constants. This file supposed to be included
* from both kernel and user spaces.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -73,7 +74,7 @@
#define SCST_STANDARD_SENSE_LEN 18
/* Max size of sense */
#define SCST_SENSE_BUFFERSIZE 96
#define SCST_SENSE_BUFFERSIZE 252
/*************************************************************
** Allowed delivery statuses for cmd's delivery_status
@@ -250,11 +251,20 @@ enum scst_cdb_flags {
*************************************************************/
#define SCST_LOAD_SENSE(key_asc_ascq) key_asc_ascq
#define SCST_SENSE_VALID(sense) ((sense != NULL) && \
((((const uint8_t *)(sense))[0] & 0x70) == 0x70))
static inline int scst_sense_valid(const uint8_t *sense)
{
return ((sense != NULL) && ((sense[0] & 0x70) == 0x70));
}
#define SCST_NO_SENSE(sense) ((sense != NULL) && \
(((const uint8_t *)(sense))[2] == 0))
static inline int scst_no_sense(const uint8_t *sense)
{
return ((sense != NULL) && (sense[2] == 0));
}
static inline int scst_sense_response_code(const uint8_t *sense)
{
return sense[0] & 0x7F;
}
/*************************************************************
** Sense data for the appropriate errors. Can be used with
@@ -266,8 +276,10 @@ enum scst_cdb_flags {
#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0
#define scst_sense_invalid_opcode ILLEGAL_REQUEST, 0x20, 0
#define scst_sense_block_out_range_error ILLEGAL_REQUEST, 0x21, 0
/* Don't use it directly, use scst_set_invalid_field_in_cdb() instead! */
#define scst_sense_invalid_field_in_cdb ILLEGAL_REQUEST, 0x24, 0
#define scst_sense_lun_not_supported ILLEGAL_REQUEST, 0x25, 0
/* Don't use it directly, use scst_set_invalid_field_in_parm_list() instead! */
#define scst_sense_invalid_field_in_parm_list ILLEGAL_REQUEST, 0x26, 0
#define scst_sense_parameter_value_invalid ILLEGAL_REQUEST, 0x26, 2
#define scst_sense_invalid_release ILLEGAL_REQUEST, 0x26, 4
+4 -4
View File
@@ -285,14 +285,14 @@ static int tape_done(struct scst_cmd *cmd)
if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET))
res = scst_tape_generic_dev_done(cmd, tape_set_block_size);
else if ((status == SAM_STAT_CHECK_CONDITION) &&
SCST_SENSE_VALID(cmd->sense)) {
scst_sense_valid(cmd->sense)) {
struct tape_params *params;
TRACE_DBG("Extended sense %x", cmd->sense[0] & 0x7F);
TRACE_DBG("Extended sense %x", scst_sense_response_code(cmd->sense));
if ((cmd->sense[0] & 0x7F) != 0x70) {
if (scst_sense_response_code(cmd->sense) != 0x70) {
PRINT_ERROR("Sense format 0x%x is not supported",
cmd->sense[0] & 0x7F);
scst_sense_response_code(cmd->sense));
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
goto out;
+27 -39
View File
@@ -1883,7 +1883,7 @@ static int vdisk_unmap_range(struct scst_cmd *cmd,
PRINT_ERROR("Device %s: attempt to write beyond max "
"size", virt_dev->name);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
SCST_LOAD_SENSE(scst_sense_block_out_range_error));
res = -EINVAL;
goto out;
}
@@ -1989,15 +1989,15 @@ static enum compl_status_e vdisk_exec_write_same(struct vdisk_cmd_params *p)
if (unlikely(cmd->cdb[1] & 1)) {
TRACE_DBG("%s", "ANCHOR not supported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out;
}
if (unlikely(cmd->cdb[1] & 0xE0)) {
TRACE_DBG("%s", "WRPROTECT not supported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 5);
goto out;
}
@@ -2032,8 +2032,8 @@ static enum compl_status_e vdisk_exec_unmap(struct vdisk_cmd_params *p)
if (unlikely(cmd->cdb[1] & 1)) {
TRACE_DBG("%s", "ANCHOR not supported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out;
}
@@ -2142,8 +2142,8 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
if (cmd->cdb[1] & CMDDT) {
TRACE_DBG("%s", "INQUIRY: CMDDT is unsupported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 1);
goto out_put;
}
@@ -2327,10 +2327,8 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
buf[5] = 0x80;
resp_len = buf[3] + 4;
} else {
TRACE_DBG("INQUIRY: Unsupported EVPD page %x",
cmd->cdb[2]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
TRACE_DBG("INQUIRY: Unsupported EVPD page %x", cmd->cdb[2]);
scst_set_invalid_field_in_cdb(cmd, 2, 0);
goto out_put;
}
} else {
@@ -2338,8 +2336,7 @@ static enum compl_status_e vdisk_exec_inquiry(struct vdisk_cmd_params *p)
if (cmd->cdb[2] != 0) {
TRACE_DBG("INQUIRY: Unsupported page %x", cmd->cdb[2]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2, 0);
goto out_put;
}
@@ -2691,8 +2688,7 @@ static enum compl_status_e vdisk_exec_mode_sense(struct vdisk_cmd_params *p)
if (0 != subpcode) {
/* TODO: Control Extension page */
TRACE_DBG("%s", "MODE SENSE: Only subpage 0 is supported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 3, 0);
goto out_put;
}
@@ -2783,8 +2779,7 @@ out:
out_not_sup:
TRACE(TRACE_MINOR, "MODE SENSE: Unsupported page %x", pcode);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2, SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out_put;
}
@@ -2886,8 +2881,7 @@ static enum compl_status_e vdisk_exec_mode_select(struct vdisk_cmd_params *p)
TRACE(TRACE_MINOR|TRACE_SCSI, "MODE SELECT: Unsupported "
"value(s) of PF and/or SP bits (cdb[1]=%x)",
cmd->cdb[1]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1, 0);
goto out_put;
}
@@ -2899,18 +2893,16 @@ static enum compl_status_e vdisk_exec_mode_select(struct vdisk_cmd_params *p)
if (address[offset - 1] == 8) {
offset += 8;
} else if (address[offset - 1] != 0) {
PRINT_ERROR("%s", "MODE SELECT: Wrong parameters list "
"lenght");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
PRINT_ERROR("%s", "MODE SELECT: Wrong parameters list lenght");
scst_set_invalid_field_in_parm_list(cmd, offset-1, 0);
goto out_put;
}
while (length > offset + 2) {
if (address[offset] & PS) {
PRINT_ERROR("%s", "MODE SELECT: Illegal PS bit");
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, offset,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 7);
goto out_put;
}
if (((address[offset] & 0x3f) == 0x8) && (type != TYPE_ROM)) {
@@ -2918,8 +2910,7 @@ static enum compl_status_e vdisk_exec_mode_select(struct vdisk_cmd_params *p)
if (address[offset + 1] != 18) {
PRINT_ERROR("%s", "MODE SELECT: Invalid "
"caching page request");
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, offset+1, 0);
goto out_put;
}
if (vdisk_set_wt(virt_dev,
@@ -2933,16 +2924,15 @@ static enum compl_status_e vdisk_exec_mode_select(struct vdisk_cmd_params *p)
if (address[offset + 1] != 0xA) {
PRINT_ERROR("%s", "MODE SELECT: Invalid "
"control page request");
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, offset+1, 0);
goto out_put;
}
vdisk_ctrl_m_pg_select(&address[offset], virt_dev, cmd);
} else {
TRACE(TRACE_MINOR, "MODE SELECT: Invalid request %x",
address[offset] & 0x3f);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, offset,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out_put;
}
offset += address[offset + 1];
@@ -2963,8 +2953,7 @@ static enum compl_status_e vdisk_exec_log(struct vdisk_cmd_params *p)
TRACE_ENTRY();
/* No log pages are supported */
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2, SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
TRACE_EXIT();
return CMD_SUCCEEDED;
@@ -3195,8 +3184,8 @@ static enum compl_status_e vdisk_exec_read_toc(struct vdisk_cmd_params *p)
if (cmd->cdb[2] & 0x0e/*Format*/) {
PRINT_ERROR("%s", "READ TOC: invalid requested data format");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 5);
goto out;
}
@@ -3204,8 +3193,7 @@ static enum compl_status_e vdisk_exec_read_toc(struct vdisk_cmd_params *p)
(cmd->cdb[6] > 1 && cmd->cdb[6] != 0xAA)) {
PRINT_ERROR("READ TOC: invalid requested track number %x",
cmd->cdb[6]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 6, 0);
goto out;
}
+119 -29
View File
@@ -1470,7 +1470,7 @@ static int scst_set_lun_not_supported_request_sense(struct scst_cmd *cmd,
goto out;
}
if ((cmd->sg != NULL) && SCST_SENSE_VALID(sg_virt(cmd->sg))) {
if ((cmd->sg != NULL) && scst_sense_valid(sg_virt(cmd->sg))) {
TRACE_MGMT_DBG("cmd %p already has sense set", cmd);
res = -EEXIST;
goto out;
@@ -1645,7 +1645,6 @@ do_sense:
cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
scst_get_cmd_dev_d_sense(cmd), key, asc, ascq);
TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
out:
TRACE_EXIT_RES(res);
@@ -1653,6 +1652,89 @@ out:
}
EXPORT_SYMBOL(scst_set_cmd_error);
static void scst_fill_field_pointer_sense(uint8_t *fp_sense, int field_offs,
int bit_offs, bool cdb)
{
/* Sense key specific */
fp_sense[0] = 0x80; /* SKSV */
if (cdb)
fp_sense[0] |= 0x40; /* C/D */
if ((bit_offs & SCST_INVAL_FIELD_BIT_OFFS_VALID) != 0)
fp_sense[0] |= (8 | (bit_offs & 7));
put_unaligned_be16(field_offs, &fp_sense[1]);
return;
}
static int scst_set_invalid_field_in(struct scst_cmd *cmd, int field_offs,
int bit_offs, bool cdb)
{
int res, asc = cdb ? 0x24 : 0x26; /* inval field in CDB or param list */
int d_sense = scst_get_cmd_dev_d_sense(cmd);
TRACE_ENTRY();
TRACE_DBG("cmd %p, cdb %d, bit_offs %d, field_offs %d (d_sense %d)",
cmd, cdb, bit_offs, field_offs, d_sense);
res = scst_set_cmd_error_status(cmd, SAM_STAT_CHECK_CONDITION);
if (res != 0)
goto out;
res = scst_alloc_sense(cmd, 1);
if (res != 0) {
PRINT_ERROR("Lost %s sense data", cdb ? "INVALID FIELD IN CDB" :
"INVALID FIELD IN PARAMETERS LIST");
goto out;
}
sBUG_ON(cmd->sense_buflen < 18);
BUILD_BUG_ON(SCST_SENSE_BUFFERSIZE < 18);
if (d_sense) {
/* Descriptor format */
cmd->sense[0] = 0x72;
cmd->sense[1] = ILLEGAL_REQUEST;
cmd->sense[2] = asc;
cmd->sense[3] = 0; /* ASCQ */
cmd->sense[7] = 8; /* additional Sense Length */
cmd->sense[8] = 2; /* sense key specific descriptor */
cmd->sense[9] = 6;
scst_fill_field_pointer_sense(&cmd->sense[12], field_offs,
bit_offs, cdb);
cmd->sense_valid_len = 16;
} else {
/* Fixed format */
cmd->sense[0] = 0x70;
cmd->sense[2] = ILLEGAL_REQUEST;
cmd->sense[7] = 0x0a; /* additional Sense Length */
cmd->sense[12] = asc;
cmd->sense[13] = 0; /* ASCQ */
scst_fill_field_pointer_sense(&cmd->sense[15], field_offs,
bit_offs, cdb);
cmd->sense_valid_len = 18;
}
TRACE_BUFFER("Sense set", cmd->sense, cmd->sense_valid_len);
out:
TRACE_EXIT_RES(res);
return res;
}
int scst_set_invalid_field_in_cdb(struct scst_cmd *cmd, int field_offs,
int bit_offs)
{
return scst_set_invalid_field_in(cmd, field_offs, bit_offs, true);
}
EXPORT_SYMBOL(scst_set_invalid_field_in_cdb);
int scst_set_invalid_field_in_parm_list(struct scst_cmd *cmd, int field_offs,
int bit_offs)
{
return scst_set_invalid_field_in(cmd, field_offs, bit_offs, false);
}
EXPORT_SYMBOL(scst_set_invalid_field_in_parm_list);
/**
* scst_set_sense() - set sense from KEY/ASC/ASCQ numbers
*
@@ -1730,7 +1812,8 @@ bool scst_analyze_sense(const uint8_t *sense, int len, unsigned int valid_mask,
bool res = false;
/* Response Code */
if ((sense[0] == 0x70) || (sense[0] == 0x71)) {
if ((scst_sense_response_code(sense) == 0x70) ||
(scst_sense_response_code(sense) == 0x71)) {
/* Fixed format */
/* Sense Key */
@@ -1756,7 +1839,8 @@ bool scst_analyze_sense(const uint8_t *sense, int len, unsigned int valid_mask,
if (sense[13] != ascq)
goto out;
}
} else if ((sense[0] == 0x72) || (sense[0] == 0x73)) {
} else if ((scst_sense_response_code(sense) == 0x72) ||
(scst_sense_response_code(sense) == 0x73)) {
/* Descriptor format */
/* Sense Key */
@@ -1782,8 +1866,11 @@ bool scst_analyze_sense(const uint8_t *sense, int len, unsigned int valid_mask,
if (sense[3] != ascq)
goto out;
}
} else
} else {
PRINT_ERROR("Unknown sense response code 0x%x",
scst_sense_response_code(sense));
goto out;
}
res = true;
@@ -1801,7 +1888,7 @@ EXPORT_SYMBOL(scst_analyze_sense);
*/
bool scst_is_ua_sense(const uint8_t *sense, int len)
{
if (SCST_SENSE_VALID(sense))
if (scst_sense_valid(sense))
return scst_analyze_sense(sense, len,
SCST_SENSE_KEY_VALID, UNIT_ATTENTION, 0, 0);
else
@@ -1829,6 +1916,10 @@ bool scst_is_ua_global(const uint8_t *sense, int len)
*
* Checks if sense in the sense buffer, if any, is in the correct format.
* If not, converts it in the correct format.
*
* WARNING! This function converts only RESPONSE CODE, ASC and ASC codes,
* dropping enverything else, including corresponding descriptors from
* descriptor format sense! ToDo: fix it.
*/
void scst_check_convert_sense(struct scst_cmd *cmd)
{
@@ -1839,19 +1930,19 @@ void scst_check_convert_sense(struct scst_cmd *cmd)
if ((cmd->sense == NULL) || (cmd->status != SAM_STAT_CHECK_CONDITION))
goto out;
/*
* The RESPONSE CODE field shall be set to 70h in all unit attention
* condition sense data in which:
* a) the ADDITIONAL SENSE CODE field is set to 29h; or
* b) the additional sense code is set to MODE PARAMETERS CHANGED.
*/
d_sense = scst_get_cmd_dev_d_sense(cmd);
if (d_sense && ((cmd->sense[0] == 0x70) || (cmd->sense[0] == 0x71)) &&
if (d_sense && ((scst_sense_response_code(cmd->sense) == 0x70) ||
(scst_sense_response_code(cmd->sense) == 0x71)) &&
/*
* The RESPONSE CODE field shall be set to 70h in all unit attention
* condition sense data in which:
* a) the ADDITIONAL SENSE CODE field is set to 29h; or
* b) the additional sense code is set to MODE PARAMETERS CHANGED.
*/
!((cmd->sense[2] == UNIT_ATTENTION) &&
((cmd->sense[12] == 0x29) ||
((cmd->sense[12] == 0x2A) && (cmd->sense[13] == 1))))) {
TRACE_MGMT_DBG("Converting fixed sense to descriptor (cmd %p)",
cmd);
TRACE_MGMT_DBG("Converting fixed sense to descriptor (cmd %p)", cmd);
if ((cmd->sense_valid_len < 18)) {
PRINT_ERROR("Sense too small to convert (%d, "
"type: fixed)", cmd->sense_buflen);
@@ -1859,8 +1950,8 @@ void scst_check_convert_sense(struct scst_cmd *cmd)
}
cmd->sense_valid_len = scst_set_sense(cmd->sense, cmd->sense_buflen,
d_sense, cmd->sense[2], cmd->sense[12], cmd->sense[13]);
} else if (!d_sense && ((cmd->sense[0] == 0x72) ||
(cmd->sense[0] == 0x73))) {
} else if (!d_sense && ((scst_sense_response_code(cmd->sense) == 0x72) ||
(scst_sense_response_code(cmd->sense) == 0x73))) {
TRACE_MGMT_DBG("Converting descriptor sense to fixed (cmd %p)",
cmd);
if ((cmd->sense_buflen < 18) || (cmd->sense_valid_len < 8)) {
@@ -4474,7 +4565,7 @@ static void scst_complete_request_sense(struct scst_cmd *req_cmd)
len = scst_get_buf_full(req_cmd, &buf);
if (scsi_status_is_good(req_cmd->status) && (len > 0) &&
SCST_SENSE_VALID(buf) && (!SCST_NO_SENSE(buf))) {
scst_sense_valid(buf) && !scst_no_sense(buf)) {
PRINT_BUFF_FLAG(TRACE_SCSI, "REQUEST SENSE returned",
buf, len);
scst_alloc_set_sense(orig_cmd, scst_cmd_atomic(req_cmd), buf,
@@ -4677,14 +4768,14 @@ static void scst_ws_write_cmd_finished(struct scst_cmd *cmd)
sBUG_ON(cmd->resp_data_len != 0);
if (cmd->status == SAM_STAT_CHECK_CONDITION)
rc = scst_set_cmd_error_sense(ws_cmd, cmd->sense,
cmd->sense_buflen);
cmd->sense_valid_len);
else {
sBUG_ON(cmd->sense != NULL);
rc = scst_set_cmd_error_status(ws_cmd, cmd->status);
}
if (rc != 0) {
/* Requeue possible UA */
if (scst_is_ua_sense(cmd->sense, cmd->sense_buflen))
if (scst_is_ua_sense(cmd->sense, cmd->sense_valid_len))
scst_requeue_ua(cmd, NULL, 0);
}
}
@@ -4778,7 +4869,7 @@ void scst_write_same(struct scst_cmd *cmd)
}
if (((cmd->cdb[1] & 0x6) == 0x6) || ((cmd->cdb[1] & 0xE0) != 0)) {
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1, 0);
goto out_done;
}
@@ -6121,7 +6212,7 @@ static int get_cdb_info_read_pos(struct scst_cmd *cmd,
PRINT_ERROR("READ POSITION: Invalid non-zero (%d) "
"allocation length for service action %x",
cmd->bufflen, cmd->cdb[1] & 0x1f);
goto out_inval;
goto out_inval_field1;
}
break;
}
@@ -6140,7 +6231,7 @@ static int get_cdb_info_read_pos(struct scst_cmd *cmd,
default:
PRINT_ERROR("READ POSITION: Invalid service action %x",
cmd->cdb[1] & 0x1f);
goto out_inval;
goto out_inval_field1;
}
cmd->data_len = cmd->bufflen;
@@ -6148,9 +6239,8 @@ static int get_cdb_info_read_pos(struct scst_cmd *cmd,
out:
return res;
out_inval:
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
out_inval_field1:
scst_set_invalid_field_in_cdb(cmd, 1, 0);
res = 1;
goto out;
}
@@ -8090,13 +8180,13 @@ int scst_obtain_device_parameters(struct scst_device *dev)
sizeof(sense_buffer));
#if 0
if ((status_byte(rc) == CHECK_CONDITION) &&
SCST_SENSE_VALID(sense_buffer)) {
scst_sense_valid(sense_buffer)) {
#else
/*
* 3ware controller is buggy and returns CONDITION_GOOD
* instead of CHECK_CONDITION
*/
if (SCST_SENSE_VALID(sense_buffer)) {
if (scst_sense_valid(sense_buffer)) {
#endif
PRINT_BUFF_FLAG(TRACE_SCSI, "Returned sense "
"data", sense_buffer,
@@ -8185,7 +8275,7 @@ void scst_store_sense(struct scst_cmd *cmd)
{
TRACE_ENTRY();
if (SCST_SENSE_VALID(cmd->sense) &&
if (scst_sense_valid(cmd->sense) &&
!test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags) &&
(cmd->tgt_dev != NULL)) {
struct scst_tgt_dev *tgt_dev = cmd->tgt_dev;
+16 -20
View File
@@ -1189,8 +1189,7 @@ static int scst_pr_register_with_spec_i_pt(struct scst_cmd *cmd,
if ((offset + tid_size(transport_id)) > ext_size) {
TRACE_PR("Invalid transport_id size %d (max %d)",
tid_size(transport_id), ext_size - offset);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, 24, 0);
res = -EINVAL;
goto out;
}
@@ -1513,8 +1512,8 @@ void scst_pr_register(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
#ifdef CONFIG_SCST_PROC
if (aptpl) {
TRACE_PR("%s", "APTL not supported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, 20,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out;
}
#endif
@@ -1603,8 +1602,8 @@ void scst_pr_register_and_ignore(struct scst_cmd *cmd, uint8_t *buffer,
#ifdef CONFIG_SCST_PROC
if (aptpl) {
TRACE_PR("%s", "APTL not supported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, 20,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out;
}
#endif
@@ -1675,8 +1674,8 @@ void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
#ifdef CONFIG_SCST_PROC
if (aptpl) {
TRACE_PR("%s", "APTL not supported");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, 17,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out;
}
#endif
@@ -1729,8 +1728,7 @@ void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
if (action_key == 0) {
TRACE_PR("%s", "Action key must be non-zero");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 8, 0);
goto out;
}
@@ -1758,8 +1756,7 @@ void scst_pr_register_and_move(struct scst_cmd *cmd, uint8_t *buffer,
if (tid_equal(transport_id, transport_id_move)) {
TRACE_PR("%s", "Equal transport id's");
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, 24, 0);
goto out;
}
@@ -1825,15 +1822,15 @@ void scst_pr_reserve(struct scst_cmd *cmd, uint8_t *buffer, int buffer_size)
if (!scst_pr_type_valid(type)) {
TRACE_PR("Invalid reservation type %d", type);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out;
}
if (((cmd->cdb[2] & 0x0f) >> 4) != SCOPE_LU) {
TRACE_PR("Invalid reservation scope %d", scope);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 4);
goto out;
}
@@ -2040,8 +2037,8 @@ static void scst_pr_do_preempt(struct scst_cmd *cmd, uint8_t *buffer,
if (!scst_pr_type_valid(type)) {
TRACE_PR("Invalid reservation type %d", type);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out;
}
@@ -2117,8 +2114,7 @@ static void scst_pr_do_preempt(struct scst_cmd *cmd, uint8_t *buffer,
if (dev->pr_holder->key != action_key) {
if (action_key == 0) {
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_parm_list));
scst_set_invalid_field_in_parm_list(cmd, 8, 0);
goto out;
} else {
scst_pr_find_registrants_list_key(dev, action_key,
+22 -21
View File
@@ -690,11 +690,11 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
goto out_done;
}
if (unlikely(cmd->cdb[cmd->cdb_len - 1] & CONTROL_BYTE_LINK_BIT)) {
if (unlikely(cmd->cdb[cmd->cdb_len-1] & CONTROL_BYTE_LINK_BIT)) {
PRINT_ERROR("Linked commands are not supported "
"(opcode 0x%02x)", cmd->cdb[0]);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, cmd->cdb_len-1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out_done;
}
@@ -1887,8 +1887,9 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
TRACE(TRACE_SCSI, "%s: Returning stored/UA sense", cmd->op_name);
if (((tgt_dev->tgt_dev_sense[0] == 0x70) ||
(tgt_dev->tgt_dev_sense[0] == 0x71)) && (cmd->cdb[1] & 1)) {
if (((scst_sense_response_code(tgt_dev->tgt_dev_sense) == 0x70) ||
(scst_sense_response_code(tgt_dev->tgt_dev_sense) == 0x71)) &&
(cmd->cdb[1] & 1)) {
PRINT_WARNING("%s: Fixed format of the saved sense, but "
"descriptor format requested. Conversion will "
"truncated data", cmd->op_name);
@@ -1899,11 +1900,12 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
sl = scst_set_sense(buffer, buffer_size, true,
tgt_dev->tgt_dev_sense[2], tgt_dev->tgt_dev_sense[12],
tgt_dev->tgt_dev_sense[13]);
} else if (((tgt_dev->tgt_dev_sense[0] == 0x72) ||
(tgt_dev->tgt_dev_sense[0] == 0x73)) && !(cmd->cdb[1] & 1)) {
} else if (((scst_sense_response_code(tgt_dev->tgt_dev_sense) == 0x72) ||
(scst_sense_response_code(tgt_dev->tgt_dev_sense) == 0x73)) &&
!(cmd->cdb[1] & 1)) {
PRINT_WARNING("%s: Descriptor format of the "
"saved sense, but fixed format requested. Conversion "
"will truncated data", cmd->op_name);
"will truncate data", cmd->op_name);
PRINT_BUFFER("Original sense", tgt_dev->tgt_dev_sense,
tgt_dev->tgt_dev_valid_sense_len);
@@ -1968,8 +1970,8 @@ static int scst_reserve_local(struct scst_cmd *cmd)
if ((cmd->cdb[0] == RESERVE_10) && (cmd->cdb[2] & SCST_RES_3RDPTY)) {
PRINT_ERROR("RESERVE_10: 3rdPty RESERVE not implemented "
"(lun=%lld)", (long long unsigned int)cmd->lun);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 2,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 4);
goto out_done;
}
@@ -2180,7 +2182,7 @@ static int scst_persistent_reserve_in_local(struct scst_cmd *cmd)
default:
PRINT_ERROR("Unsupported action %x", action);
scst_pr_write_unlock(dev);
goto out_err;
goto out_unsup_act;
}
out_complete:
@@ -2197,9 +2199,9 @@ out_done:
TRACE_EXIT_RES(SCST_EXEC_COMPLETED);
return SCST_EXEC_COMPLETED;
out_err:
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
out_unsup_act:
scst_set_invalid_field_in_cdb(cmd, 1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out_complete;
}
@@ -2287,8 +2289,8 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
if ((action != PR_REGISTER) && (action != PR_REGISTER_AND_IGNORE) &&
(action != PR_REGISTER_AND_MOVE) && ((buffer[20] >> 2) & 0x01)) {
TRACE_PR("ALL_TG_PT must be zero for action %x", action);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_cdb));
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_put_buf_full;
}
@@ -2327,8 +2329,8 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
scst_pr_register_and_move(cmd, buffer, buffer_size);
break;
default:
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
scst_set_invalid_field_in_cdb(cmd, 1,
SCST_INVAL_FIELD_BIT_OFFS_VALID | 0);
goto out_unlock;
}
@@ -2987,7 +2989,7 @@ static int scst_check_sense(struct scst_cmd *cmd)
}
if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
SCST_SENSE_VALID(cmd->sense)) {
scst_sense_valid(cmd->sense)) {
PRINT_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense,
cmd->sense_valid_len);
@@ -3060,8 +3062,7 @@ static bool scst_check_auto_sense(struct scst_cmd *cmd)
TRACE_ENTRY();
if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
(!SCST_SENSE_VALID(cmd->sense) ||
SCST_NO_SENSE(cmd->sense))) {
(!scst_sense_valid(cmd->sense) || scst_no_sense(cmd->sense))) {
TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "CHECK_CONDITION, "
"but no sense: cmd->status=%x, cmd->msg_status=%x, "
"cmd->host_status=%x, cmd->driver_status=%x (cmd %p)",
+1 -1
View File
@@ -905,7 +905,7 @@ static int scst_local_send_resp(struct scsi_cmnd *cmnd,
scst_check_restore_sg_buff(scst_cmnd);
/* Simulate autosense by this driver */
if (unlikely(SCST_SENSE_VALID(scst_cmnd->sense)))
if (unlikely(scst_sense_valid(scst_cmnd->sense)))
copy_sense(cmnd, scst_cmnd);
}
+1 -1
View File
@@ -1612,7 +1612,7 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
srp_rsp->tag = tag;
srp_rsp->status = status;
if (!SCST_SENSE_VALID(sense_data))
if (!scst_sense_valid(sense_data))
sense_data_len = 0;
else {
BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
+5
View File
@@ -75,6 +75,11 @@ static int set_sense(uint8_t *buffer, int len, int key, int asc, int ascq)
return res;
}
/*
* ToDo: implement analogs of scst_set_invalid_field_in_cdb() and
* scst_set_invalid_field_in_parm_list()
*/
void set_cmd_error(struct vdisk_cmd *vcmd, int key, int asc, int ascq)
{
struct scst_user_scsi_cmd_reply_exec *reply = &vcmd->reply->exec_reply;
+1
View File
@@ -17,6 +17,7 @@
*/
#include <stdint.h>
#include <stddef.h>
#include <scst_user.h>