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().

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
This commit is contained in:
Bart Van Assche
2015-04-16 09:36:09 +02:00
parent 5b57a0bcea
commit 8c6d767193
3 changed files with 14 additions and 4 deletions
+3 -1
View File
@@ -355,7 +355,9 @@ 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);
if (result == SAM_STAT_GOOD)
WARN_ON_ONCE(IS_ERR_VALUE(result));
if (status_byte(result) == GOOD)
goto out_complete;
work->result = result;
+9 -3
View File
@@ -6740,8 +6740,10 @@ out:
static void scsi_end_async(struct request *req, int error)
{
struct scsi_io_context *sioc = req->end_io_data;
int errors;
TRACE_DBG("sioc %p, cmd %p", sioc, sioc->data);
TRACE_DBG("sioc %p, cmd %p, error %d / %d", sioc, sioc->data, error,
req->errors);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
lockdep_assert_held(req->q->queue_lock);
@@ -6750,11 +6752,15 @@ static void scsi_end_async(struct request *req, int error)
lockdep_assert_held(req->q->queue_lock);
#endif
errors = req->errors && !IS_ERR_VALUE(req->errors) ? req->errors :
IS_ERR_VALUE(req->errors) || error ?
SAM_STAT_CHECK_CONDITION : 0;
if (sioc->done)
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 30)
sioc->done(sioc->data, sioc->sense, req->errors, req->data_len);
sioc->done(sioc->data, sioc->sense, errors, req->data_len);
#else
sioc->done(sioc->data, sioc->sense, req->errors, req->resid_len);
sioc->done(sioc->data, sioc->sense, errors, req->resid_len);
#endif
kmem_cache_free(scsi_io_context_cache, sioc);
+2
View File
@@ -1724,6 +1724,8 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
scst_set_exec_time(cmd);
WARN_ON_ONCE(IS_ERR_VALUE(result));
cmd->status = result & 0xff;
cmd->msg_status = msg_byte(result);
cmd->host_status = host_byte(result);