1.对于硬件单队列的块设备,调用__blk_complete_request处理。如果发起IO请求的cpu就是当前cpu或者和当前cpu共享缓存,则发起当前cpu上的block软中断,在block软中断中继续request完成处理流程 2.对于硬件单队列的块设备,如果不满足case 1的条件,则通过IPI(inter-processor interrupt)发起其他cpu上的block软中断,在block软中断继续request完成处理流程 3.对于硬件多队列设备,如果当前cpu与发起IO请求的cpu不共享缓存(且不是高优先级的IO请求),则调用__blk_mq_complete_request_remote发起远端cpu上的request完成处理流程(IPI) 4.对于硬件多队列设备,非上述情况,直接在当前cpu上(硬件中断上下文)继续request完成处理流程
四、多队列IO调度器 事实上,在blk-mq框架一开始是不支持IO调度器的(Linux-3.13)。由于高速存储器件IO特征是高IOPS,低延迟,我们希望IO的软件开销尽可能低,而IO调度会增加软件开销,所以专门针对这类器件设计的blk-mq在一开始并没有加入IO调度的能力。 当时的Linux块设备层是SQ和MQ两套框架共存的(SQ用于HDD这样的慢速块设备驱动,MQ用于nvme这样的高速块设备驱动)。Linux Block Layer的发展趋势是希望能够使用一套框架同时满足慢速器件和高速器件的需求,所以blk-mq引入后,Linux上的块设备驱动程序开始往MQ框架迁移,在Linux-5.0上,所有基于SQ的块设备驱动都完成了向MQ框架的转化,Block Layer的SQ框架和相关IO调度器被完全移除。 我们知道对于慢速器件(特别是旋转磁盘,随机IO性能很差)来讲,IO调度是十分重要的,同时一些高速器件(特别是硬件单队列的器件,如emmc,ufs)也有IO调度的需求。 因此在Linux-4.11上,Jens Axboe在MQ框架上增加了IO调度的能力,同SQ框架一样,MQ中的IO调度器也是插件化的,框架提供一系列的接口,由具体的IO调度算法(如mq-deadline)实现这些接口: ![]() ![]() 目前基于blk-mq实现的IO调度器主要有下面几个:
五、结语 本文主要介绍了blk-mq框架,基于这个框架,我们能够实现下面几件事情:
参考资料 1.《Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems》 2.《High Performance Storage with blk-mq and scsi-mq》 3.https://www.thomas-krenn.com/en/wiki/Linux_Multi-Queue_Block_IO_Queueing_Mechanism_(blk-mq)#cite_note-blkmq-2 4.https://lwn.net/Articles/552904/ 5.https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/block 6.https://lwn.net/Articles/736534/ 7. https://lwn.net/Articles/738449/ 8.https://www.kernel.org/doc/html/latest/block/deadline-iosched.html 9.https://www.kernel.org/doc/html/latest/block/bfq-iosched.html 10.https://www.kernel.org/doc/html/latest/block/kyber-iosched.html |