scst_lib: Fix SCSI pass-through error handling

Some but not all SCSI LLD drivers set req->errors. Some SCSI
LLD drivers set req->errors to a negative Unix error code and
others assign the result of make_status_bytes() to req->errors.
The SCSI core finishes failed pass-through requests by calling
blk_finish_request(). That function calls req->end_io() without
setting req->errors. Hence check both the error argument and
req->errors before calling sioc->done().



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7861 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2019-01-05 21:55:26 +00:00
parent 457d6fceed
commit 656931dfce
3 changed files with 14 additions and 3 deletions

View File

@@ -377,11 +377,13 @@ static void disk_cmd_done(void *data, char *sense, int result, int resid)
TRACE_DBG("work %p, cmd %p, left %d, result %d, sense %p, resid %d",
work, work->cmd, work->left, result, sense, resid);
work->result = result;
WARN_ON_ONCE(IS_ERR_VALUE((long)result));
if (result == SAM_STAT_GOOD)
if (status_byte(result) == GOOD)
goto out_complete;
work->result = result;
disk_restore_sg(work);
scst_pass_through_cmd_done(work->cmd, sense, result, resid + work->left);

View File

@@ -8411,13 +8411,20 @@ static void scsi_end_async(struct request *req, blk_status_t error)
#endif
if (sioc->done) {
int result, resid_len;
int resid_len;
long result;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
result = scsi_req(req)->result;
#else
result = req->errors;
#endif
TRACE_DBG("error %d / %ld", error, result);
result = result && !IS_ERR_VALUE(result) ? result :
IS_ERR_VALUE(result) || error ?
SAM_STAT_CHECK_CONDITION : 0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
resid_len = scsi_req(req)->resid_len;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)

View File

@@ -2132,6 +2132,8 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
{
TRACE_ENTRY();
WARN_ON_ONCE(IS_ERR_VALUE((long)result));
cmd->status = result & 0xff;
cmd->msg_status = msg_byte(result);
cmd->host_status = host_byte(result);