From 7a38dc0bfb4cc39ed57e120e2224673f3d4d200f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 6 Apr 2017 15:36:29 +0200 Subject: scsi: scsi_error: count medium access timeout only once per EH run The current medium access timeout counter will be increased for each command, so if there are enough failed commands we'll hit the medium access timeout for even a single device failure and the following kernel message is displayed: sd H:C:T:L: [sdXY] Medium access timeout failure. Offlining disk! Fix this by making the timeout per EH run, ie the counter will only be increased once per device and EH run. Fixes: 18a4d0a ("[SCSI] Handle disk devices which can not process medium access commands") Cc: Ewan Milne Cc: Lawrence Obermann Cc: Benjamin Block Cc: Steffen Maier Signed-off-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_error.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index f2cafae150bc..370f6c045b60 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -220,6 +220,23 @@ scsi_abort_command(struct scsi_cmnd *scmd) return SUCCESS; } +/** + * scsi_eh_reset - call into ->eh_action to reset internal counters + * @scmd: scmd to run eh on. + * + * The scsi driver might be carrying internal state about the + * devices, so we need to call into the driver to reset the + * internal state once the error handler is started. + */ +static void scsi_eh_reset(struct scsi_cmnd *scmd) +{ + if (!blk_rq_is_passthrough(scmd->request)) { + struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd); + if (sdrv->eh_reset) + sdrv->eh_reset(scmd); + } +} + /** * scsi_eh_scmd_add - add scsi cmd to error handling. * @scmd: scmd to run eh on. @@ -249,6 +266,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) eh_flag &= ~SCSI_EH_CANCEL_CMD; scmd->eh_eflags |= eh_flag; + scsi_eh_reset(scmd); list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); shost->host_failed++; scsi_eh_wakeup(shost); -- cgit 1.4.1 From 1bcb93047e1b22b68cb8a30b48f999884fa827a8 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 6 Apr 2017 15:36:31 +0200 Subject: scsi: always send command aborts When a command has timed out we always should be sending an abort; with the previous code a failed abort might signal SCSI EH to start, and all other timed out commands will never be aborted, even though they might belong to a different ITL nexus. Cc: Benjamin Block Signed-off-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_error.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 370f6c045b60..cff7d9de79f2 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -196,19 +196,7 @@ scsi_abort_command(struct scsi_cmnd *scmd) return FAILED; } - /* - * Do not try a command abort if - * SCSI EH has already started. - */ spin_lock_irqsave(shost->host_lock, flags); - if (scsi_host_in_recovery(shost)) { - spin_unlock_irqrestore(shost->host_lock, flags); - SCSI_LOG_ERROR_RECOVERY(3, - scmd_printk(KERN_INFO, scmd, - "not aborting, host in recovery\n")); - return FAILED; - } - if (shost->eh_deadline != -1 && !shost->last_reset) shost->last_reset = jiffies; spin_unlock_irqrestore(shost->host_lock, flags); -- cgit 1.4.1 From 8e8c9d01c5ea33e0d21f13264a9caeed255526d1 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 6 Apr 2017 15:36:33 +0200 Subject: scsi: make eh_eflags persistent If a failed command is retried and fails again we need to enter SCSI EH, otherwise we will never be able to recover the command. To detect this situation we must not clear scmd->eh_eflags when EH finishes but rather make it persistent throughout the lifetime of the command. Signed-off-by: Hannes Reinecke Reviewed-by: Benjamin Block Reviewed-by: Bart Van Assche Reviewed-by: Johannes Thumshirn Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi_eh.txt | 14 +++++++------- drivers/scsi/libsas/sas_scsi_host.c | 2 -- drivers/scsi/scsi_error.c | 4 ++-- include/scsi/scsi_eh.h | 1 + 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt index 37eca00796ee..4edb9c1cbef5 100644 --- a/Documentation/scsi/scsi_eh.txt +++ b/Documentation/scsi/scsi_eh.txt @@ -105,11 +105,14 @@ function 2. If the host supports asynchronous completion (as indicated by the no_async_abort setting in the host template) scsi_abort_command() - is invoked to schedule an asynchrous abort. If that fails - Step #3 is taken. + is invoked to schedule an asynchrous abort. + Asynchronous abort are not invoked for commands which the + SCSI_EH_ABORT_SCHEDULED flag is set (this indicates that the command + already had been aborted once, and this is a retry which failed), + or when the EH deadline is expired. In these case Step #3 is taken. - 2. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the - command. See [1-3] for more information. + 3. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the + command. See [1-4] for more information. [1-3] Asynchronous command aborts @@ -263,7 +266,6 @@ scmd->allowed. 3. scmd recovered ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd - - clear scmd->eh_eflags - scsi_setup_cmd_retry() - move from local eh_work_q to local eh_done_q LOCKING: none @@ -456,8 +458,6 @@ except for #1 must be implemented by eh_strategy_handler(). - shost->host_failed is zero. - - Each scmd's eh_eflags field is cleared. - - Each scmd is in such a state that scsi_setup_cmd_retry() on the scmd doesn't make any difference. diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index ee6b39a1db69..87e5079d816b 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -613,8 +613,6 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * SAS_DPRINTK("trying to find task 0x%p\n", task); res = sas_scsi_find_task(task); - cmd->eh_eflags = 0; - switch (res) { case TASK_IS_DONE: SAS_DPRINTK("%s: task 0x%p is done\n", __func__, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index cff7d9de79f2..4d26ff215c74 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -188,7 +188,6 @@ scsi_abort_command(struct scsi_cmnd *scmd) /* * Retry after abort failed, escalate to next level. */ - scmd->eh_eflags &= ~SCSI_EH_ABORT_SCHEDULED; SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "previous abort failed\n")); @@ -937,6 +936,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, ses->result = scmd->result; ses->underflow = scmd->underflow; ses->prot_op = scmd->prot_op; + ses->eh_eflags = scmd->eh_eflags; scmd->prot_op = SCSI_PROT_NORMAL; scmd->eh_eflags = 0; @@ -1000,6 +1000,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) scmd->result = ses->result; scmd->underflow = ses->underflow; scmd->prot_op = ses->prot_op; + scmd->eh_eflags = ses->eh_eflags; } EXPORT_SYMBOL(scsi_eh_restore_cmnd); @@ -1132,7 +1133,6 @@ static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn) */ void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q) { - scmd->eh_eflags = 0; list_move_tail(&scmd->eh_entry, done_q); } EXPORT_SYMBOL(scsi_eh_finish_cmd); diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 98d366b55770..a25b3285dd6f 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -31,6 +31,7 @@ extern int scsi_ioctl_reset(struct scsi_device *, int __user *); struct scsi_eh_save { /* saved state */ int result; + int eh_eflags; enum dma_data_direction data_direction; unsigned underflow; unsigned char cmd_len; -- cgit 1.4.1 From 2171b6d08bf8c2b826922b94e24ba36b00cb78b3 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 6 Apr 2017 15:36:34 +0200 Subject: scsi: make scsi_eh_scmd_add() always succeed scsi_eh_scmd_add() currently only will fail if no error handler thread is started (which will never be the case) or if the state machine encounters an illegal transition. But if we're encountering an invalid state transition chances is we cannot fixup things with the error handler. So better add a WARN_ON for illegal host states and make scsi_dh_scmd_add() a void function. Signed-off-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Reviewed-by: Bart Van Assche Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_error.c | 41 +++++++++++++---------------------------- drivers/scsi/scsi_lib.c | 4 ++-- drivers/scsi/scsi_priv.h | 2 +- 3 files changed, 16 insertions(+), 31 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4d26ff215c74..bbc431897606 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -162,13 +162,7 @@ scmd_eh_abort_handler(struct work_struct *work) } } - if (!scsi_eh_scmd_add(scmd, 0)) { - SCSI_LOG_ERROR_RECOVERY(3, - scmd_printk(KERN_WARNING, scmd, - "terminate aborted command\n")); - set_host_byte(scmd, DID_TIME_OUT); - scsi_finish_command(scmd); - } + scsi_eh_scmd_add(scmd, 0); } /** @@ -228,28 +222,23 @@ static void scsi_eh_reset(struct scsi_cmnd *scmd) * scsi_eh_scmd_add - add scsi cmd to error handling. * @scmd: scmd to run eh on. * @eh_flag: optional SCSI_EH flag. - * - * Return value: - * 0 on failure. */ -int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) +void scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) { struct Scsi_Host *shost = scmd->device->host; unsigned long flags; - int ret = 0; + int ret; - if (!shost->ehandler) - return 0; + WARN_ON_ONCE(!shost->ehandler); spin_lock_irqsave(shost->host_lock, flags); - if (scsi_host_set_state(shost, SHOST_RECOVERY)) - if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) - goto out_unlock; - + if (scsi_host_set_state(shost, SHOST_RECOVERY)) { + ret = scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY); + WARN_ON_ONCE(ret); + } if (shost->eh_deadline != -1 && !shost->last_reset) shost->last_reset = jiffies; - ret = 1; if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) eh_flag &= ~SCSI_EH_CANCEL_CMD; scmd->eh_eflags |= eh_flag; @@ -257,9 +246,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); shost->host_failed++; scsi_eh_wakeup(shost); - out_unlock: spin_unlock_irqrestore(shost->host_lock, flags); - return ret; } /** @@ -288,13 +275,11 @@ enum blk_eh_timer_return scsi_times_out(struct request *req) rtn = host->hostt->eh_timed_out(scmd); if (rtn == BLK_EH_NOT_HANDLED) { - if (!host->hostt->no_async_abort && - scsi_abort_command(scmd) == SUCCESS) - return BLK_EH_NOT_HANDLED; - - set_host_byte(scmd, DID_TIME_OUT); - if (!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) - rtn = BLK_EH_HANDLED; + if (host->hostt->no_async_abort || + scsi_abort_command(scmd) != SUCCESS) { + set_host_byte(scmd, DID_TIME_OUT); + scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD); + } } return rtn; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ba2286652ff6..ba8da904e774 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1593,8 +1593,8 @@ static void scsi_softirq_done(struct request *rq) scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); break; default: - if (!scsi_eh_scmd_add(cmd, 0)) - scsi_finish_command(cmd); + scsi_eh_scmd_add(cmd, 0); + break; } } diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 99bfc985e190..5be6cbf69df6 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -72,7 +72,7 @@ extern enum blk_eh_timer_return scsi_times_out(struct request *req); extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); extern void scsi_eh_wakeup(struct Scsi_Host *shost); -extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); +extern void scsi_eh_scmd_add(struct scsi_cmnd *, int); void scsi_eh_ready_devs(struct Scsi_Host *shost, struct list_head *work_q, struct list_head *done_q); -- cgit 1.4.1 From a06586325f371c0f0f6095454b5beca0602eaab4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 6 Apr 2017 15:36:35 +0200 Subject: scsi: make asynchronous aborts mandatory There hasn't been any reports for HBAs where asynchronous abort would not work, so we should make it mandatory and remove the fallback. Signed-off-by: Hannes Reinecke Reviewed-by: Johannes Thumshirn Reviewed-by: Bart Van Assche Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi_eh.txt | 18 ++++------ drivers/scsi/scsi_error.c | 81 ++++-------------------------------------- drivers/scsi/scsi_lib.c | 2 +- drivers/scsi/scsi_priv.h | 3 +- include/scsi/scsi_host.h | 5 --- 5 files changed, 15 insertions(+), 94 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt index 4edb9c1cbef5..11e447bdb3a5 100644 --- a/Documentation/scsi/scsi_eh.txt +++ b/Documentation/scsi/scsi_eh.txt @@ -70,7 +70,7 @@ with the command. scmd is requeued to blk queue. - otherwise - scsi_eh_scmd_add(scmd, 0) is invoked for the command. See + scsi_eh_scmd_add(scmd) is invoked for the command. See [1-3] for details of this function. @@ -103,9 +103,7 @@ function eh_timed_out() callback did not handle the command. Step #2 is taken. - 2. If the host supports asynchronous completion (as indicated by the - no_async_abort setting in the host template) scsi_abort_command() - is invoked to schedule an asynchrous abort. + 2. scsi_abort_command() is invoked to schedule an asynchrous abort. Asynchronous abort are not invoked for commands which the SCSI_EH_ABORT_SCHEDULED flag is set (this indicates that the command already had been aborted once, and this is a retry which failed), @@ -127,16 +125,13 @@ function scmds enter EH via scsi_eh_scmd_add(), which does the following. - 1. Turns on scmd->eh_eflags as requested. It's 0 for error - completions and SCSI_EH_CANCEL_CMD for timeouts. + 1. Links scmd->eh_entry to shost->eh_cmd_q - 2. Links scmd->eh_entry to shost->eh_cmd_q + 2. Sets SHOST_RECOVERY bit in shost->shost_state - 3. Sets SHOST_RECOVERY bit in shost->shost_state + 3. Increments shost->host_failed - 4. Increments shost->host_failed - - 5. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed + 4. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed As can be seen above, once any scmd is added to shost->eh_cmd_q, SHOST_RECOVERY shost_state bit is turned on. This prevents any new @@ -252,7 +247,6 @@ scmd->allowed. 1. Error completion / time out ACTION: scsi_eh_scmd_add() is invoked for scmd - - set scmd->eh_eflags - add scmd to shost->eh_cmd_q - set SHOST_RECOVERY - shost->host_failed++ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index bbc431897606..53e334356f31 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -162,7 +162,7 @@ scmd_eh_abort_handler(struct work_struct *work) } } - scsi_eh_scmd_add(scmd, 0); + scsi_eh_scmd_add(scmd); } /** @@ -221,9 +221,8 @@ static void scsi_eh_reset(struct scsi_cmnd *scmd) /** * scsi_eh_scmd_add - add scsi cmd to error handling. * @scmd: scmd to run eh on. - * @eh_flag: optional SCSI_EH flag. */ -void scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) +void scsi_eh_scmd_add(struct scsi_cmnd *scmd) { struct Scsi_Host *shost = scmd->device->host; unsigned long flags; @@ -239,9 +238,6 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) if (shost->eh_deadline != -1 && !shost->last_reset) shost->last_reset = jiffies; - if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) - eh_flag &= ~SCSI_EH_CANCEL_CMD; - scmd->eh_eflags |= eh_flag; scsi_eh_reset(scmd); list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); shost->host_failed++; @@ -275,10 +271,9 @@ enum blk_eh_timer_return scsi_times_out(struct request *req) rtn = host->hostt->eh_timed_out(scmd); if (rtn == BLK_EH_NOT_HANDLED) { - if (host->hostt->no_async_abort || - scsi_abort_command(scmd) != SUCCESS) { + if (scsi_abort_command(scmd) != SUCCESS) { set_host_byte(scmd, DID_TIME_OUT); - scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD); + scsi_eh_scmd_add(scmd); } } @@ -331,7 +326,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, list_for_each_entry(scmd, work_q, eh_entry) { if (scmd->device == sdev) { ++total_failures; - if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) + if (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) ++cmd_cancel; else ++cmd_failed; @@ -1154,8 +1149,7 @@ int scsi_eh_get_sense(struct list_head *work_q, * should not get sense. */ list_for_each_entry_safe(scmd, next, work_q, eh_entry) { - if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) || - (scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) || + if ((scmd->eh_eflags & SCSI_EH_ABORT_SCHEDULED) || SCSI_SENSE_VALID(scmd)) continue; @@ -1295,61 +1289,6 @@ static int scsi_eh_test_devices(struct list_head *cmd_list, return list_empty(work_q); } - -/** - * scsi_eh_abort_cmds - abort pending commands. - * @work_q: &list_head for pending commands. - * @done_q: &list_head for processed commands. - * - * Decription: - * Try and see whether or not it makes sense to try and abort the - * running command. This only works out to be the case if we have one - * command that has timed out. If the command simply failed, it makes - * no sense to try and abort the command, since as far as the shost - * adapter is concerned, it isn't running. - */ -static int scsi_eh_abort_cmds(struct list_head *work_q, - struct list_head *done_q) -{ - struct scsi_cmnd *scmd, *next; - LIST_HEAD(check_list); - int rtn; - struct Scsi_Host *shost; - - list_for_each_entry_safe(scmd, next, work_q, eh_entry) { - if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD)) - continue; - shost = scmd->device->host; - if (scsi_host_eh_past_deadline(shost)) { - list_splice_init(&check_list, work_q); - SCSI_LOG_ERROR_RECOVERY(3, - scmd_printk(KERN_INFO, scmd, - "%s: skip aborting cmd, past eh deadline\n", - current->comm)); - return list_empty(work_q); - } - SCSI_LOG_ERROR_RECOVERY(3, - scmd_printk(KERN_INFO, scmd, - "%s: aborting cmd\n", current->comm)); - rtn = scsi_try_to_abort_cmd(shost->hostt, scmd); - if (rtn == FAILED) { - SCSI_LOG_ERROR_RECOVERY(3, - scmd_printk(KERN_INFO, scmd, - "%s: aborting cmd failed\n", - current->comm)); - list_splice_init(&check_list, work_q); - return list_empty(work_q); - } - scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; - if (rtn == FAST_IO_FAIL) - scsi_eh_finish_cmd(scmd, done_q); - else - list_move_tail(&scmd->eh_entry, &check_list); - } - - return scsi_eh_test_devices(&check_list, work_q, done_q, 0); -} - /** * scsi_eh_try_stu - Send START_UNIT to device. * @scmd: &scsi_cmnd to send START_UNIT @@ -1692,11 +1631,6 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q, sdev_printk(KERN_INFO, scmd->device, "Device offlined - " "not ready after error recovery\n"); scsi_device_set_state(scmd->device, SDEV_OFFLINE); - if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) { - /* - * FIXME: Handle lost cmds. - */ - } scsi_eh_finish_cmd(scmd, done_q); } return; @@ -2140,8 +2074,7 @@ static void scsi_unjam_host(struct Scsi_Host *shost) SCSI_LOG_ERROR_RECOVERY(1, scsi_eh_prt_fail_stats(shost, &eh_work_q)); if (!scsi_eh_get_sense(&eh_work_q, &eh_done_q)) - if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q)) - scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q); + scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q); spin_lock_irqsave(shost->host_lock, flags); if (shost->eh_deadline != -1) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ba8da904e774..9822fdeed0ce 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1593,7 +1593,7 @@ static void scsi_softirq_done(struct request *rq) scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); break; default: - scsi_eh_scmd_add(cmd, 0); + scsi_eh_scmd_add(cmd); break; } } diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 5be6cbf69df6..e20ab10623fb 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -18,7 +18,6 @@ struct scsi_nl_hdr; /* * Scsi Error Handler Flags */ -#define SCSI_EH_CANCEL_CMD 0x0001 /* Cancel this cmd */ #define SCSI_EH_ABORT_SCHEDULED 0x0002 /* Abort has been scheduled */ #define SCSI_SENSE_VALID(scmd) \ @@ -72,7 +71,7 @@ extern enum blk_eh_timer_return scsi_times_out(struct request *req); extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); extern void scsi_eh_wakeup(struct Scsi_Host *shost); -extern void scsi_eh_scmd_add(struct scsi_cmnd *, int); +extern void scsi_eh_scmd_add(struct scsi_cmnd *); void scsi_eh_ready_devs(struct Scsi_Host *shost, struct list_head *work_q, struct list_head *done_q); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 3cd8c3bec638..afb04811b7b9 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -451,11 +451,6 @@ struct scsi_host_template { /* True if the controller does not support WRITE SAME */ unsigned no_write_same:1; - /* - * True if asynchronous aborts are not supported - */ - unsigned no_async_abort:1; - /* * Countdown for host blocking with no commands outstanding. */ -- cgit 1.4.1 From 2908769c35fbd3de7b874b60b95ba81546e3c920 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 24 Apr 2017 16:51:12 +0900 Subject: scsi: Improve scsi_get_sense_info_fld Use get_unaligned_be32 and get_unaligned_be64 to obtain values from the sense buffer instead of open coding the operations. Also change the function return value to a bool and fix the function signature declaration to remove spaces triggering checkpatch warnings. No functional change is introduced by this patch. Signed-off-by: Damien Le Moal Reviewed-by: Bart Van Assche Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_error.c | 38 +++++++++++++++----------------------- include/scsi/scsi_eh.h | 4 ++-- 2 files changed, 17 insertions(+), 25 deletions(-) (limited to 'drivers/scsi/scsi_error.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 53e334356f31..d70c67cf46ef 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -46,6 +46,8 @@ #include +#include + static void scsi_eh_done(struct scsi_cmnd *scmd); /* @@ -2361,44 +2363,34 @@ EXPORT_SYMBOL(scsi_command_normalize_sense); * field will be placed if found. * * Return value: - * 1 if information field found, 0 if not found. + * true if information field found, false if not found. */ -int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, - u64 * info_out) +bool scsi_get_sense_info_fld(const u8 *sense_buffer, int sb_len, + u64 *info_out) { - int j; const u8 * ucp; - u64 ull; if (sb_len < 7) - return 0; + return false; switch (sense_buffer[0] & 0x7f) { case 0x70: case 0x71: if (sense_buffer[0] & 0x80) { - *info_out = (sense_buffer[3] << 24) + - (sense_buffer[4] << 16) + - (sense_buffer[5] << 8) + sense_buffer[6]; - return 1; - } else - return 0; + *info_out = get_unaligned_be32(&sense_buffer[3]); + return true; + } + return false; case 0x72: case 0x73: ucp = scsi_sense_desc_find(sense_buffer, sb_len, 0 /* info desc */); if (ucp && (0xa == ucp[1])) { - ull = 0; - for (j = 0; j < 8; ++j) { - if (j > 0) - ull <<= 8; - ull |= ucp[4 + j]; - } - *info_out = ull; - return 1; - } else - return 0; + *info_out = get_unaligned_be64(&ucp[4]); + return true; + } + return false; default: - return 0; + return false; } } EXPORT_SYMBOL(scsi_get_sense_info_fld); diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index a25b3285dd6f..64d30d80dadb 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -23,8 +23,8 @@ static inline bool scsi_sense_is_deferred(const struct scsi_sense_hdr *sshdr) return ((sshdr->response_code >= 0x70) && (sshdr->response_code & 1)); } -extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, - u64 * info_out); +extern bool scsi_get_sense_info_fld(const u8 *sense_buffer, int sb_len, + u64 *info_out); extern int scsi_ioctl_reset(struct scsi_device *, int __user *); -- cgit 1.4.1