对于IO request,目前使用blk_mq_complete_reuqest()依次完成每个IO。IO的完成有三条路径:直接在当前CPU上完成;通过软中断完成;发送IPI中断到其他CPU上完成。
对于路径1,尽量会让当前CPU来完成IO,这些情况包括:
- 请求队列没有设置QUEUE_FLAG_SAME_COMP(不需要在同一个CPU上发送和完成IO)且硬件是多队列;
- 强制中断线程化且硬件是多队列;
- 发送IO与完成IO的CPU相同且硬件是多队列;
- 没有设置QUEUE_FLAG_SAME_COMP但共享CACHE且硬件是多队列;
- POLL模式时;
对于路径2,通过软中断完成,是路径1中除了POLL模式外,其他情况在单队列时;
其他情况会通过IPI中断完成IO(路径3)。
上面最后都调用完成回调函数q->mq_ops->complete(),对于SCSI层,对应函数为scsi_softirq_done(),至于具体的调用参见后续的SCSI层代码分析。