diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index 3741f88fa..85e81b59e 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -5823,8 +5823,10 @@ static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd) q2t_cleanup_hw_pending_cmd(ha, cmd); - scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR_FATAL, - SCST_CONTEXT_THREAD); + /* It might be sporadic, hence retriable */ + scst_set_cmd_error(scst_cmd, + SCST_LOAD_SENSE(scst_sense_internal_failure)); + scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR_SENSE_SET, SCST_CONTEXT_THREAD); goto out_unlock; } else if (cmd->state == Q2T_STATE_ABORTED) { TRACE_MGMT_DBG("Force finishing aborted cmd %p (tag %d)", diff --git a/scst/include/scst_const.h b/scst/include/scst_const.h index c18f874fa..c1b5f4440 100644 --- a/scst/include/scst_const.h +++ b/scst/include/scst_const.h @@ -298,7 +298,7 @@ static inline int scst_sense_response_code(const uint8_t *sense) #define scst_sense_read_error MEDIUM_ERROR, 0x11, 0 /* HARDWARE_ERROR is 4 */ -#define scst_sense_hardw_error HARDWARE_ERROR, 0x44, 0 +#define scst_sense_hardw_error HARDWARE_ERROR, 0x44, 0 /* non-retriable */ /* ILLEGAL_REQUEST is 5 */ #define scst_sense_invalid_opcode ILLEGAL_REQUEST, 0x20, 0 @@ -333,6 +333,7 @@ static inline int scst_sense_response_code(const uint8_t *sense) /* ABORTED_COMMAND is 0xb */ #define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0 +#define scst_sense_internal_failure ABORTED_COMMAND, 0x44, 0 /* retriable */ /* MISCOMPARE is 0xe */ #define scst_sense_miscompare_error MISCOMPARE, 0x1D, 0 diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c index 684aca4ff..555c8c093 100644 --- a/scst/src/dev_handlers/scst_disk.c +++ b/scst/src/dev_handlers/scst_disk.c @@ -536,7 +536,7 @@ out: return res; out_err_restore: - scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out_restore; out_error: diff --git a/scst/src/dev_handlers/scst_tape.c b/scst/src/dev_handlers/scst_tape.c index ec4e85bc8..4aeba2417 100644 --- a/scst/src/dev_handlers/scst_tape.c +++ b/scst/src/dev_handlers/scst_tape.c @@ -291,7 +291,7 @@ static int tape_done(struct scst_cmd *cmd) PRINT_ERROR("Sense format 0x%x is not supported", scst_sense_response_code(cmd->sense)); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out; } diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 0ba4f86bc..3b0ebc8bd 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1260,7 +1260,7 @@ out_unmap: ucmd->data_pages = NULL; res = -EFAULT; if (ucmd->cmd != NULL) - scst_set_cmd_error(ucmd->cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + scst_set_cmd_error(ucmd->cmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out_err; } @@ -1377,8 +1377,8 @@ out_inval: res = -EINVAL; goto out_abnormal; -out_hwerr_res_set: - scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); +out_intern_fail_res_set: + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); out_abnormal: scst_set_cmd_abnormal_done_state(cmd); @@ -1393,7 +1393,7 @@ out_status: res = scst_alloc_sense(cmd, 0); if (res != 0) - goto out_hwerr_res_set; + goto out_intern_fail_res_set; sense_len = min_t(int, cmd->sense_buflen, preply->sense_len); @@ -1403,7 +1403,7 @@ out_status: if (rc != 0) { PRINT_ERROR("Failed to copy %d sense's bytes", rc); res = -EFAULT; - goto out_hwerr_res_set; + goto out_intern_fail_res_set; } cmd->sense_valid_len = sense_len; } @@ -1495,7 +1495,7 @@ static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd, if (unlikely((ereply->pbuf & ~PAGE_MASK) != 0)) { PRINT_ERROR("Supplied pbuf %llx isn't " "page aligned", ereply->pbuf); - goto out_hwerr; + goto out_intern_fail; } pages = cmd->sg_cnt; } else @@ -1540,7 +1540,7 @@ static int dev_user_process_reply_exec(struct scst_user_cmd *ucmd, if (rc != 0) { PRINT_ERROR("Failed to copy %d sense's bytes", rc); res = -EFAULT; - goto out_hwerr_res_set; + goto out_intern_fail_res_set; } cmd->sense_valid_len = sense_len; } @@ -1560,16 +1560,16 @@ out_inval: (long long unsigned int)cmd->lun, scst_get_opcode_name(cmd), cmd); PRINT_BUFFER("Invalid exec_reply", reply, sizeof(*reply)); -out_hwerr: +out_intern_fail: res = -EINVAL; -out_hwerr_res_set: +out_intern_fail_res_set: if (ucmd->background_exec) { ucmd_put(ucmd); goto out; } else { scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out_compl; } @@ -2261,7 +2261,7 @@ static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy, scst_set_busy(ucmd->cmd); else scst_set_cmd_error(ucmd->cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); } scst_set_cmd_abnormal_done_state(ucmd->cmd); @@ -2292,7 +2292,7 @@ static void dev_user_unjam_cmd(struct scst_user_cmd *ucmd, int busy, scst_set_busy(ucmd->cmd); else scst_set_cmd_error(ucmd->cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); } ucmd->cmd->scst_cmd_done(ucmd->cmd, SCST_CMD_STATE_DEFAULT, diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 8aa6576dc..57ee0572e 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -4787,7 +4787,7 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) if (unlikely(length < 0)) { PRINT_ERROR("scst_get_buf_first() failed: %zd", length); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out; } @@ -4816,7 +4816,7 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) } else if (unlikely(length < 0)) { PRINT_ERROR("scst_get_buf_next() failed: %zd", length); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out_set_fs; } @@ -4910,7 +4910,7 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p) if (unlikely(length < 0)) { PRINT_ERROR("scst_get_buf_first() failed: %zd", length); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out; } @@ -4939,7 +4939,7 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p) } else if (unlikely(length < 0)) { PRINT_ERROR("scst_get_buf_next() failed: %zd", length); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out_set_fs; } @@ -5176,8 +5176,10 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua) /* Allocate and initialize blockio_work struct */ blockio_work = kmem_cache_alloc(blockio_work_cachep, gfp_mask); - if (blockio_work == NULL) - goto out_no_mem; + if (blockio_work == NULL) { + scst_set_busy(cmd); + goto finish_cmd; + } #if 0 { @@ -5199,6 +5201,18 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua) need_new_bio = 1; length = scst_get_sg_page_first(cmd, &page, &offset); + /* + * bv_len and bv_offset must be a multiple of 512 (SECTOR_SIZE), so + * check this here. + */ + if (WARN_ONCE((length & 511) != 0 || (offset & 511) != 0, + "Refused bio with invalid length %d and/or offset %d.\n", + length, offset)) { + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_hardw_error)); + goto free_bio; + } + while (length > 0) { int len, bytes, off, thislen; struct page *pg; @@ -5219,7 +5233,8 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua) PRINT_ERROR("Failed to create bio " "for data segment %d (cmd %p)", cmd->get_sg_buf_entry_num, cmd); - goto out_no_bio; + scst_set_busy(cmd); + goto free_bio; } bios++; @@ -5303,7 +5318,7 @@ out: TRACE_EXIT(); return; -out_no_bio: +free_bio: while (hbio) { bio = hbio; hbio = hbio->bi_next; @@ -5311,8 +5326,7 @@ out_no_bio: } kmem_cache_free(blockio_work_cachep, blockio_work); -out_no_mem: - scst_set_busy(cmd); +finish_cmd: cmd->completed = 1; cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME); goto out; @@ -5677,7 +5691,7 @@ static enum compl_status_e vdev_exec_verify(struct vdisk_cmd_params *p) if (length < 0) { PRINT_ERROR("scst_get_buf_() failed: %zd", length); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); } out_free: @@ -5735,7 +5749,7 @@ static enum compl_status_e vdisk_exec_caw(struct vdisk_cmd_params *p) scst_set_busy(cmd); else scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out; } diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 44132e9e8..62cd4197c 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4959,7 +4959,7 @@ static void scst_complete_request_sense(struct scst_cmd *req_cmd) PRINT_ERROR("%s", "Unable to get the sense via " "REQUEST SENSE, returning HARDWARE ERROR"); scst_set_cmd_error(orig_cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); } } @@ -6483,7 +6483,7 @@ int scst_get_buf_full_sense(struct scst_cmd *cmd, uint8_t **buf) scst_set_busy(cmd); else scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out; } @@ -10505,7 +10505,7 @@ void tm_dbg_release_cmd(struct scst_cmd *cmd) if (((scst_random() % 10) == 5)) { scst_set_cmd_error(cmd, SCST_LOAD_SENSE( - scst_sense_hardw_error)); + scst_sense_internal_failure)); /* It's completed now */ } } diff --git a/scst/src/scst_pres.c b/scst/src/scst_pres.c index cc06ac361..f17cd5e36 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -1032,7 +1032,7 @@ out: * the affected initiator. */ if (cmd != NULL) - scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); #endif } diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 175af61bf..7e43b6747 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -3516,7 +3516,7 @@ static bool scst_check_auto_sense(struct scst_cmd *cmd) "%s)", cmd->host_status, cmd, scst_get_opcode_name(cmd), cmd->tgt->tgt_name, cmd->dev->virt_name); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); } } @@ -3544,7 +3544,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd) PRINT_ERROR("%s", "Unable to issue REQUEST SENSE, " "returning HARDWARE ERROR"); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); } goto out; } @@ -3580,7 +3580,7 @@ next: "MODE_SENSE buffer"); scst_set_cmd_error(cmd, SCST_LOAD_SENSE( - scst_sense_hardw_error)); + scst_sense_internal_failure)); err = true; } else if (length > 2 && cmd->cdb[0] == MODE_SENSE) address[2] |= 0x80; /* Write Protect*/ @@ -3621,7 +3621,7 @@ next: PRINT_ERROR("%s", "Unable to get INQUIRY " "buffer"); scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_hardw_error)); + SCST_LOAD_SENSE(scst_sense_internal_failure)); err = true; } if (buflen > 0) diff --git a/usr/fileio/common.c b/usr/fileio/common.c index ac98120af..75d09a7d7 100644 --- a/usr/fileio/common.c +++ b/usr/fileio/common.c @@ -209,7 +209,7 @@ static int do_exec(struct vdisk_cmd *vcmd) #ifdef DEBUG_SENSE if ((random() % 100000) == 75) { - set_cmd_error(vcmd, SCST_LOAD_SENSE(scst_sense_hardw_error)); + set_cmd_error(vcmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); goto out; } #endif