From 21ddbb572ff7b8032b8aab5db6df2efaac0ed788 Mon Sep 17 00:00:00 2001 From: Zhenghua Jia Date: Tue, 29 Jan 2019 11:18:07 +0800 Subject: [PATCH] anolis: scsi: add a proc interface to cancel scsi eh reset ANBZ: #555 In case of multi-disk usecase, scsi layer would pause HBA if I/O error or timeout occurs, and the error handler is triggeerd to recover HBA with the following operations, Abort the command. Reset the device. Reset the bus. Reset the host. If all of the above fail, the device will be set to the offline state. The problem is that the process(30s * 5) maybe too long. Given that the disk error state is just around 2%, we decide to offer an knob to report errors immediately instead so that applications can deal with disk errors more gracefully. Signed-off-by: Zhenghua Jia Reviewed-by: Liu Bo Signed-off-by: Joseph Qi Reviewed-by: Xiaoguang Wang --- drivers/scsi/scsi_error.c | 9 ++++++++- drivers/scsi/scsi_sysctl.c | 12 +++++++++++- include/scsi/scsi_eh.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index f11f51e2465f..6389024869f5 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2074,6 +2074,8 @@ static void scsi_restart_operations(struct Scsi_Host *shost) spin_unlock_irqrestore(shost->host_lock, flags); } +int scsi_cancel_eh_reset; + /** * scsi_eh_ready_devs - check device ready state and recover if not. * @shost: host to be recovered. @@ -2084,13 +2086,18 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost, struct list_head *work_q, struct list_head *done_q) { - if (!scsi_eh_stu(shost, work_q, done_q)) + if (!scsi_eh_stu(shost, work_q, done_q)) { + if (scsi_cancel_eh_reset) { + scsi_eh_offline_sdevs(work_q, done_q); + return; + } if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) if (!scsi_eh_target_reset(shost, work_q, done_q)) if (!scsi_eh_bus_reset(shost, work_q, done_q)) if (!scsi_eh_host_reset(shost, work_q, done_q)) scsi_eh_offline_sdevs(work_q, done_q); + } } EXPORT_SYMBOL_GPL(scsi_eh_ready_devs); diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c index 7259704a7f52..c888cf8e65b1 100644 --- a/drivers/scsi/scsi_sysctl.c +++ b/drivers/scsi/scsi_sysctl.c @@ -8,16 +8,26 @@ #include #include +#include + #include "scsi_logging.h" #include "scsi_priv.h" - static struct ctl_table scsi_table[] = { { .procname = "logging_level", .data = &scsi_logging_level, .maxlen = sizeof(scsi_logging_level), .mode = 0644, .proc_handler = proc_dointvec }, + + { .procname = "scsi_cancel_eh_reset", + .data = &scsi_cancel_eh_reset, + .maxlen = sizeof(scsi_cancel_eh_reset), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, { } }; diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 6bd5ed695a5e..7662805c9a30 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -51,5 +51,6 @@ extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, extern void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses); +extern int scsi_cancel_eh_reset; #endif /* _SCSI_SCSI_EH_H */