Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: core: Change the return type of .eh_timed_out()

Commit 6600593cbd93 ("block: rename BLK_EH_NOT_HANDLED to BLK_EH_DONE")
made it impossible for .eh_timed_out() implementations to call
scsi_done() without causing a crash.

Restore support for SCSI timeout handlers to call scsi_done() as follows:

* Change all .eh_timed_out() handlers as follows:

- Change the return type into enum scsi_timeout_action.
- Change BLK_EH_RESET_TIMER into SCSI_EH_RESET_TIMER.
- Change BLK_EH_DONE into SCSI_EH_NOT_HANDLED.

* In scsi_timeout(), convert the SCSI_EH_* values into BLK_EH_* values.

Reviewed-by: Lee Duncan <lduncan@suse.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: John Garry <john.garry@huawei.com>
Cc: Mike Christie <michael.christie@oracle.com>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20221018202958.1902564-3-bvanassche@acm.org
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Bart Van Assche and committed by
Martin K. Petersen
dee7121e 978b7922

+77 -59
+5 -2
Documentation/scsi/scsi_eh.rst
··· 92 92 1. invokes optional hostt->eh_timed_out() callback. Return value can 93 93 be one of 94 94 95 - - BLK_EH_RESET_TIMER 95 + - SCSI_EH_RESET_TIMER 96 96 This indicates that more time is required to finish the 97 97 command. Timer is restarted. 98 98 99 - - BLK_EH_DONE 99 + - SCSI_EH_NOT_HANDLED 100 100 eh_timed_out() callback did not handle the command. 101 101 Step #2 is taken. 102 + 103 + - SCSI_EH_DONE 104 + eh_timed_out() completed the command. 102 105 103 106 2. scsi_abort_command() is invoked to schedule an asynchronous abort which may 104 107 issue a retry scmd->allowed + 1 times. Asynchronous aborts are not invoked
+4 -4
drivers/message/fusion/mptsas.c
··· 1952 1952 * @sc: scsi command that the midlayer is about to time out 1953 1953 * 1954 1954 **/ 1955 - static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc) 1955 + static enum scsi_timeout_action mptsas_eh_timed_out(struct scsi_cmnd *sc) 1956 1956 { 1957 1957 MPT_SCSI_HOST *hd; 1958 1958 MPT_ADAPTER *ioc; 1959 1959 VirtDevice *vdevice; 1960 - enum blk_eh_timer_return rc = BLK_EH_DONE; 1960 + enum scsi_timeout_action rc = SCSI_EH_NOT_HANDLED; 1961 1961 1962 1962 hd = shost_priv(sc->device->host); 1963 1963 if (hd == NULL) { ··· 1980 1980 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset," 1981 1981 "SML need to reset the timer (sc=%p)\n", 1982 1982 ioc->name, __func__, sc)); 1983 - rc = BLK_EH_RESET_TIMER; 1983 + rc = SCSI_EH_RESET_TIMER; 1984 1984 } 1985 1985 vdevice = sc->device->hostdata; 1986 1986 if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD ··· 1988 1988 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed " 1989 1989 "or in device removal delay (sc=%p)\n", 1990 1990 ioc->name, __func__, sc)); 1991 - rc = BLK_EH_RESET_TIMER; 1991 + rc = SCSI_EH_RESET_TIMER; 1992 1992 goto done; 1993 1993 } 1994 1994
+13 -13
drivers/scsi/libiscsi.c
··· 2071 2071 return 0; 2072 2072 } 2073 2073 2074 - enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) 2074 + enum scsi_timeout_action iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) 2075 2075 { 2076 - enum blk_eh_timer_return rc = BLK_EH_DONE; 2076 + enum scsi_timeout_action rc = SCSI_EH_NOT_HANDLED; 2077 2077 struct iscsi_task *task = NULL, *running_task; 2078 2078 struct iscsi_cls_session *cls_session; 2079 2079 struct iscsi_session *session; ··· 2093 2093 * Raced with completion. Blk layer has taken ownership 2094 2094 * so let timeout code complete it now. 2095 2095 */ 2096 - rc = BLK_EH_DONE; 2096 + rc = SCSI_EH_NOT_HANDLED; 2097 2097 spin_unlock(&session->back_lock); 2098 2098 goto done; 2099 2099 } ··· 2102 2102 * Racing with the completion path right now, so give it more 2103 2103 * time so that path can complete it like normal. 2104 2104 */ 2105 - rc = BLK_EH_RESET_TIMER; 2105 + rc = SCSI_EH_RESET_TIMER; 2106 2106 task = NULL; 2107 2107 spin_unlock(&session->back_lock); 2108 2108 goto done; ··· 2120 2120 if (unlikely(system_state != SYSTEM_RUNNING)) { 2121 2121 sc->result = DID_NO_CONNECT << 16; 2122 2122 ISCSI_DBG_EH(session, "sc on shutdown, handled\n"); 2123 - rc = BLK_EH_DONE; 2123 + rc = SCSI_EH_NOT_HANDLED; 2124 2124 goto done; 2125 2125 } 2126 2126 /* 2127 2127 * We are probably in the middle of iscsi recovery so let 2128 2128 * that complete and handle the error. 2129 2129 */ 2130 - rc = BLK_EH_RESET_TIMER; 2130 + rc = SCSI_EH_RESET_TIMER; 2131 2131 goto done; 2132 2132 } 2133 2133 2134 2134 conn = session->leadconn; 2135 2135 if (!conn) { 2136 2136 /* In the middle of shuting down */ 2137 - rc = BLK_EH_RESET_TIMER; 2137 + rc = SCSI_EH_RESET_TIMER; 2138 2138 goto done; 2139 2139 } 2140 2140 ··· 2151 2151 "Last data xfer at %lu. Last timeout was at " 2152 2152 "%lu\n.", task->last_xfer, task->last_timeout); 2153 2153 task->have_checked_conn = false; 2154 - rc = BLK_EH_RESET_TIMER; 2154 + rc = SCSI_EH_RESET_TIMER; 2155 2155 goto done; 2156 2156 } 2157 2157 ··· 2162 2162 * and can let the iscsi eh handle it 2163 2163 */ 2164 2164 if (iscsi_has_ping_timed_out(conn)) { 2165 - rc = BLK_EH_RESET_TIMER; 2165 + rc = SCSI_EH_RESET_TIMER; 2166 2166 goto done; 2167 2167 } 2168 2168 ··· 2200 2200 task->last_xfer, running_task->last_xfer, 2201 2201 task->last_timeout); 2202 2202 spin_unlock(&session->back_lock); 2203 - rc = BLK_EH_RESET_TIMER; 2203 + rc = SCSI_EH_RESET_TIMER; 2204 2204 goto done; 2205 2205 } 2206 2206 } ··· 2216 2216 */ 2217 2217 if (READ_ONCE(conn->ping_task)) { 2218 2218 task->have_checked_conn = true; 2219 - rc = BLK_EH_RESET_TIMER; 2219 + rc = SCSI_EH_RESET_TIMER; 2220 2220 goto done; 2221 2221 } 2222 2222 2223 2223 /* Make sure there is a transport check done */ 2224 2224 iscsi_send_nopout(conn, NULL); 2225 2225 task->have_checked_conn = true; 2226 - rc = BLK_EH_RESET_TIMER; 2226 + rc = SCSI_EH_RESET_TIMER; 2227 2227 2228 2228 done: 2229 2229 spin_unlock_bh(&session->frwd_lock); ··· 2232 2232 task->last_timeout = jiffies; 2233 2233 iscsi_put_task(task); 2234 2234 } 2235 - ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? 2235 + ISCSI_DBG_EH(session, "return %s\n", rc == SCSI_EH_RESET_TIMER ? 2236 2236 "timer reset" : "shutdown or nh"); 2237 2237 return rc; 2238 2238 }
+3 -4
drivers/scsi/megaraid/megaraid_sas_base.c
··· 2927 2927 * Sets the FW busy flag and reduces the host->can_queue if the 2928 2928 * cmd has not been completed within the timeout period. 2929 2929 */ 2930 - static enum 2931 - blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) 2930 + static enum scsi_timeout_action megasas_reset_timer(struct scsi_cmnd *scmd) 2932 2931 { 2933 2932 struct megasas_instance *instance; 2934 2933 unsigned long flags; 2935 2934 2936 2935 if (time_after(jiffies, scmd->jiffies_at_alloc + 2937 2936 (scmd_timeout * 2) * HZ)) { 2938 - return BLK_EH_DONE; 2937 + return SCSI_EH_NOT_HANDLED; 2939 2938 } 2940 2939 2941 2940 instance = (struct megasas_instance *)scmd->device->host->hostdata; ··· 2948 2949 2949 2950 spin_unlock_irqrestore(instance->host->host_lock, flags); 2950 2951 } 2951 - return BLK_EH_RESET_TIMER; 2952 + return SCSI_EH_RESET_TIMER; 2952 2953 } 2953 2954 2954 2955 /**
+2 -2
drivers/scsi/mvumi.c
··· 2109 2109 return 0; 2110 2110 } 2111 2111 2112 - static enum blk_eh_timer_return mvumi_timed_out(struct scsi_cmnd *scmd) 2112 + static enum scsi_timeout_action mvumi_timed_out(struct scsi_cmnd *scmd) 2113 2113 { 2114 2114 struct mvumi_cmd *cmd = mvumi_priv(scmd)->cmd_priv; 2115 2115 struct Scsi_Host *host = scmd->device->host; ··· 2137 2137 mvumi_return_cmd(mhba, cmd); 2138 2138 spin_unlock_irqrestore(mhba->shost->host_lock, flags); 2139 2139 2140 - return BLK_EH_DONE; 2140 + return SCSI_EH_NOT_HANDLED; 2141 2141 } 2142 2142 2143 2143 static int
+4 -4
drivers/scsi/qla4xxx/ql4_os.c
··· 116 116 static int qla4xxx_get_iface_param(struct iscsi_iface *iface, 117 117 enum iscsi_param_type param_type, 118 118 int param, char *buf); 119 - static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc); 119 + static enum scsi_timeout_action qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc); 120 120 static struct iscsi_endpoint *qla4xxx_ep_connect(struct Scsi_Host *shost, 121 121 struct sockaddr *dst_addr, 122 122 int non_blocking); ··· 1871 1871 return; 1872 1872 } 1873 1873 1874 - static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) 1874 + static enum scsi_timeout_action qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) 1875 1875 { 1876 1876 struct iscsi_cls_session *session; 1877 1877 unsigned long flags; 1878 - enum blk_eh_timer_return ret = BLK_EH_DONE; 1878 + enum scsi_timeout_action ret = SCSI_EH_NOT_HANDLED; 1879 1879 1880 1880 session = starget_to_session(scsi_target(sc->device)); 1881 1881 1882 1882 spin_lock_irqsave(&session->lock, flags); 1883 1883 if (session->state == ISCSI_SESSION_FAILED) 1884 - ret = BLK_EH_RESET_TIMER; 1884 + ret = SCSI_EH_RESET_TIMER; 1885 1885 spin_unlock_irqrestore(&session->lock, flags); 1886 1886 1887 1887 return ret;
+19 -14
drivers/scsi/scsi_error.c
··· 328 328 enum blk_eh_timer_return scsi_timeout(struct request *req) 329 329 { 330 330 struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); 331 - enum blk_eh_timer_return rtn = BLK_EH_DONE; 332 331 struct Scsi_Host *host = scmd->device->host; 333 332 334 333 trace_scsi_dispatch_cmd_timeout(scmd); ··· 337 338 if (host->eh_deadline != -1 && !host->last_reset) 338 339 host->last_reset = jiffies; 339 340 340 - if (host->hostt->eh_timed_out) 341 - rtn = host->hostt->eh_timed_out(scmd); 342 - 343 - if (rtn == BLK_EH_DONE) { 344 - /* 345 - * If scsi_done() has already set SCMD_STATE_COMPLETE, do not 346 - * modify *scmd. 347 - */ 348 - if (test_and_set_bit(SCMD_STATE_COMPLETE, &scmd->state)) 341 + if (host->hostt->eh_timed_out) { 342 + switch (host->hostt->eh_timed_out(scmd)) { 343 + case SCSI_EH_DONE: 349 344 return BLK_EH_DONE; 350 - if (scsi_abort_command(scmd) != SUCCESS) { 351 - set_host_byte(scmd, DID_TIME_OUT); 352 - scsi_eh_scmd_add(scmd); 345 + case SCSI_EH_RESET_TIMER: 346 + return BLK_EH_RESET_TIMER; 347 + case SCSI_EH_NOT_HANDLED: 348 + break; 353 349 } 354 350 } 355 351 356 - return rtn; 352 + /* 353 + * If scsi_done() has already set SCMD_STATE_COMPLETE, do not modify 354 + * *scmd. 355 + */ 356 + if (test_and_set_bit(SCMD_STATE_COMPLETE, &scmd->state)) 357 + return BLK_EH_DONE; 358 + if (scsi_abort_command(scmd) != SUCCESS) { 359 + set_host_byte(scmd, DID_TIME_OUT); 360 + scsi_eh_scmd_add(scmd); 361 + } 362 + 363 + return BLK_EH_DONE; 357 364 } 358 365 359 366 /**
+3 -4
drivers/scsi/scsi_transport_fc.c
··· 2530 2530 * Notes: 2531 2531 * This routine assumes no locks are held on entry. 2532 2532 */ 2533 - enum blk_eh_timer_return 2534 - fc_eh_timed_out(struct scsi_cmnd *scmd) 2533 + enum scsi_timeout_action fc_eh_timed_out(struct scsi_cmnd *scmd) 2535 2534 { 2536 2535 struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device)); 2537 2536 2538 2537 if (rport->port_state == FC_PORTSTATE_BLOCKED) 2539 - return BLK_EH_RESET_TIMER; 2538 + return SCSI_EH_RESET_TIMER; 2540 2539 2541 - return BLK_EH_DONE; 2540 + return SCSI_EH_NOT_HANDLED; 2542 2541 } 2543 2542 EXPORT_SYMBOL(fc_eh_timed_out); 2544 2543
+4 -4
drivers/scsi/scsi_transport_srp.c
··· 594 594 * @scmd: SCSI command. 595 595 * 596 596 * If a timeout occurs while an rport is in the blocked state, ask the SCSI 597 - * EH to continue waiting (BLK_EH_RESET_TIMER). Otherwise let the SCSI core 598 - * handle the timeout (BLK_EH_DONE). 597 + * EH to continue waiting (SCSI_EH_RESET_TIMER). Otherwise let the SCSI core 598 + * handle the timeout (SCSI_EH_NOT_HANDLED). 599 599 * 600 600 * Note: This function is called from soft-IRQ context and with the request 601 601 * queue lock held. 602 602 */ 603 - enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd) 603 + enum scsi_timeout_action srp_timed_out(struct scsi_cmnd *scmd) 604 604 { 605 605 struct scsi_device *sdev = scmd->device; 606 606 struct Scsi_Host *shost = sdev->host; ··· 611 611 return rport && rport->fast_io_fail_tmo < 0 && 612 612 rport->dev_loss_tmo < 0 && 613 613 i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ? 614 - BLK_EH_RESET_TIMER : BLK_EH_DONE; 614 + SCSI_EH_RESET_TIMER : SCSI_EH_NOT_HANDLED; 615 615 } 616 616 EXPORT_SYMBOL(srp_timed_out); 617 617
+2 -2
drivers/scsi/storvsc_drv.c
··· 1652 1652 * be unbounded on Azure. Reset the timer unconditionally to give the host a 1653 1653 * chance to perform EH. 1654 1654 */ 1655 - static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd) 1655 + static enum scsi_timeout_action storvsc_eh_timed_out(struct scsi_cmnd *scmnd) 1656 1656 { 1657 1657 #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) 1658 1658 if (scmnd->device->host->transportt == fc_transport_template) 1659 1659 return fc_eh_timed_out(scmnd); 1660 1660 #endif 1661 - return BLK_EH_RESET_TIMER; 1661 + return SCSI_EH_RESET_TIMER; 1662 1662 } 1663 1663 1664 1664 static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
+2 -2
drivers/scsi/virtio_scsi.c
··· 731 731 * latencies might be higher than on bare metal. Reset the timer 732 732 * unconditionally to give the host a chance to perform EH. 733 733 */ 734 - static enum blk_eh_timer_return virtscsi_eh_timed_out(struct scsi_cmnd *scmnd) 734 + static enum scsi_timeout_action virtscsi_eh_timed_out(struct scsi_cmnd *scmnd) 735 735 { 736 - return BLK_EH_RESET_TIMER; 736 + return SCSI_EH_RESET_TIMER; 737 737 } 738 738 739 739 static struct scsi_host_template virtscsi_host_template = {
+1 -1
include/scsi/libiscsi.h
··· 393 393 extern int iscsi_eh_session_reset(struct scsi_cmnd *sc); 394 394 extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); 395 395 extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc); 396 - extern enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc); 396 + extern enum scsi_timeout_action iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc); 397 397 398 398 /* 399 399 * iSCSI host helpers.
+13 -1
include/scsi/scsi_host.h
··· 27 27 #define MODE_INITIATOR 0x01 28 28 #define MODE_TARGET 0x02 29 29 30 + /** 31 + * enum scsi_timeout_action - How to handle a command that timed out. 32 + * @SCSI_EH_DONE: The command has already been completed. 33 + * @SCSI_EH_RESET_TIMER: Reset the timer and continue waiting for completion. 34 + * @SCSI_EH_NOT_HANDLED: The command has not yet finished. Abort the command. 35 + */ 36 + enum scsi_timeout_action { 37 + SCSI_EH_DONE, 38 + SCSI_EH_RESET_TIMER, 39 + SCSI_EH_NOT_HANDLED, 40 + }; 41 + 30 42 struct scsi_host_template { 31 43 /* 32 44 * Put fields referenced in IO submission path together in ··· 343 331 * 344 332 * Status: OPTIONAL 345 333 */ 346 - enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); 334 + enum scsi_timeout_action (*eh_timed_out)(struct scsi_cmnd *); 347 335 /* 348 336 * Optional routine that allows the transport to decide if a cmd 349 337 * is retryable. Return true if the transport is in a state the
+1 -1
include/scsi/scsi_transport_fc.h
··· 862 862 int fc_vport_terminate(struct fc_vport *vport); 863 863 int fc_block_rport(struct fc_rport *rport); 864 864 int fc_block_scsi_eh(struct scsi_cmnd *cmnd); 865 - enum blk_eh_timer_return fc_eh_timed_out(struct scsi_cmnd *scmd); 865 + enum scsi_timeout_action fc_eh_timed_out(struct scsi_cmnd *scmd); 866 866 bool fc_eh_should_retry_cmd(struct scsi_cmnd *scmd); 867 867 868 868 static inline struct Scsi_Host *fc_bsg_to_shost(struct bsg_job *job)
+1 -1
include/scsi/scsi_transport_srp.h
··· 118 118 extern void srp_start_tl_fail_timers(struct srp_rport *rport); 119 119 extern void srp_remove_host(struct Scsi_Host *); 120 120 extern void srp_stop_rport_timers(struct srp_rport *rport); 121 - enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd); 121 + enum scsi_timeout_action srp_timed_out(struct scsi_cmnd *scmd); 122 122 123 123 /** 124 124 * srp_chkready() - evaluate the transport layer state before I/O