在IO下发过程中,IO可能因为软件或硬件问题导致IO无法返回,这时如果没有超时机制,IO会一直阻塞。实际上存在超时机制,在达到一定时间IO仍未返回,会触发超时处理。
在分配request-queue时,会给每个请求队列分配一个定时器q->timeout,用于检测IO超时,默认30秒。当IO在指定时间没有返回时,会调用超时定时器的回调blk_rq_timed_out_timer(),它调用q->timeout_work。
q->tiemout_work会对未完成的IO做检查,如果该IO已经完成,就不需要进行超时处理,否则调用req->q->mq_ops->timeout()进行超时处理,对于SCSI层,对应处理函数为scsi_times_out()。
SCSI层超时处理首先会调用底层驱动的超时处理接口host->hostt->eh_timed_out()处理,若处理完!BLK_EH_NONE,直接返回,否则调用scsi_abort_command()尝试去abort掉该命令,若成功abort,直接返回,否则进入错误处理进行恢复。
Scsi_abort_command()会在shost->tmf_work_q工作队列上执行abort_work,对应的回调函数scmd_eh_abort_handler()执行流程如下:
函数scmd_eh_abort_handler()尝试调用底层接口hostt->eh_abort_handler()来处理,若失败或没有定义,则进入错误处理恢复,否则根据该IOS是否允许重试,进行重试或完成IO。
对于hisi_sas驱动,上述底层接口eh_timed_out()和eh_abort_handler()都没有填充,因此对于超时的IO,最终会进入错误处理进行恢复。