From 955113f493e5f44ec528e1bd3632bf18581cc03d Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Wed, 18 Jul 2012 21:28:57 +0000 Subject: [PATCH] Sense handling improvements git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4408 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- ibmvstgt/src/ibmvstgt.c | 2 +- iscsi-scst/kernel/iscsi.c | 2 +- mpt/mpt_scst.c | 2 +- mvsas_tgt/mv_tgt.c | 8 +- qla2x00t/qla2x00-target/qla2x00t.c | 6 +- scst/include/scst.h | 6 ++ scst/include/scst_const.h | 24 +++-- scst/src/dev_handlers/scst_tape.c | 8 +- scst/src/dev_handlers/scst_vdisk.c | 66 ++++++------- scst/src/scst_lib.c | 148 +++++++++++++++++++++++------ scst/src/scst_pres.c | 36 ++++--- scst/src/scst_targ.c | 43 +++++---- scst_local/scst_local.c | 2 +- srpt/src/ib_srpt.c | 2 +- usr/fileio/common.c | 5 + usr/fileio/common.h | 1 + 16 files changed, 230 insertions(+), 131 deletions(-) diff --git a/ibmvstgt/src/ibmvstgt.c b/ibmvstgt/src/ibmvstgt.c index 698e240e8..54d2d9ab9 100644 --- a/ibmvstgt/src/ibmvstgt.c +++ b/ibmvstgt/src/ibmvstgt.c @@ -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); diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 832975410..be7029392 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -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; diff --git a/mpt/mpt_scst.c b/mpt/mpt_scst.c index 0e5e33db9..6f0c66ce0 100644 --- a/mpt/mpt_scst.c +++ b/mpt/mpt_scst.c @@ -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); } diff --git a/mvsas_tgt/mv_tgt.c b/mvsas_tgt/mv_tgt.c index 68ac489cf..2dd7f603d 100644 --- a/mvsas_tgt/mv_tgt.c +++ b/mvsas_tgt/mv_tgt.c @@ -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 */ diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index 1b24e50ca..4b39f10d4 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -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)) { diff --git a/scst/include/scst.h b/scst/include/scst.h index ee37e8317..58188badf 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -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, diff --git a/scst/include/scst_const.h b/scst/include/scst_const.h index 294f926ce..92769e30c 100644 --- a/scst/include/scst_const.h +++ b/scst/include/scst_const.h @@ -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 diff --git a/scst/src/dev_handlers/scst_tape.c b/scst/src/dev_handlers/scst_tape.c index 8a5a82138..587903451 100644 --- a/scst/src/dev_handlers/scst_tape.c +++ b/scst/src/dev_handlers/scst_tape.c @@ -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; diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 55fcd03d5..ff94644aa 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -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; } diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 293f35cf7..f92366e3b 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -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; diff --git a/scst/src/scst_pres.c b/scst/src/scst_pres.c index f83b1eae6..f49dbc7e5 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -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, diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index a538b6729..fed3be651 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -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)", diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index 8e05fe276..b04c3ed58 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -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); } diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index b7173e791..1bf820c4c 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -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)); diff --git a/usr/fileio/common.c b/usr/fileio/common.c index 0f7374588..f773b541e 100644 --- a/usr/fileio/common.c +++ b/usr/fileio/common.c @@ -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; diff --git a/usr/fileio/common.h b/usr/fileio/common.h index b1b6792f6..2ab754408 100644 --- a/usr/fileio/common.h +++ b/usr/fileio/common.h @@ -17,6 +17,7 @@ */ #include +#include #include