mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-20 06:06:23 +00:00
Merged revisions 5933,5940 via svnmerge from
svn+ssh://vlnb@svn.code.sf.net/p/scst/svn/trunk ........ r5933 | vlnb | 2014-12-10 20:38:04 -0800 (Wed, 10 Dec 2014) | 11 lines vdisk_blockio: Report invalid scatterlists It is possible for a target driver to pass a scatterlist via scst_cmd_set_tgt_sg() that is valid for the vdisk_fileio handler but not for the vdisk_blockio handler. Complain loudly if an invalid scatterlist is passed to vdisk_blockio because such scatterlists cause silent data corruption with most Linux block drivers. Signed-off-by: Bart Van Assche <bvanassche@acm.org> ........ r5940 | vlnb | 2014-12-18 19:55:14 -0800 (Thu, 18 Dec 2014) | 7 lines Replace in cases, where sporadic failures are possible, HARDWARE ERROR by INTERNAL TARGET FAILURE, which is retriable (some OS'es don't retry HARDWARE ERROR) Reported and suggested by Shahar Salzman <shahar.salzman@kaminario.com> ........ git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.0.x@6109 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -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)",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user