BLOCK层代码分析(9)IO下发之IO下发

        看着题目是不是很奇怪,想不出好的名字,就这样将就吧。

        前面bio bounce过程,bio的切分和合并,request的获取是为IO请求下发做准备工作。当这些准备工作完成后,才进入到真正的IO下发过程。之前在前面章节中介绍过,IO下发基本上有三条路径(可参考BLOCK层代码分析(3)IO下发概述):经过plug->mq_list往调度器或ctx->rq_lists下发、不经过plug->mq_list往调度器或ctx->rq_lists下发、直接往驱动下发。是否经过plug->mq_list即为是否支持PLUG/UNPLUG机制。

1. IO同步和异步下发方式

        IO同步下发为直接调用queue_rq()下发,待上一个IO下发后再进行下一个IO下发;IO异步下发为通过hctx的workqueue执行run_work,可以将多个work分别下发到不同的cpu上(异步work执行的CPU为hctx->cpumask中的一个,轮询机制,每个cpu执行的WORK数目为BLK_MQ_CPU_WORK_BATCH(8)),分别执行run_work,每个run_work最终会执行queue_rq()。

2. 直接下发路径

        对于一些SSD盘或NVME盘,不希望进行PLUG/UNPLUG,且不需要调度层的合并和排序,因此直接下发驱动。

        直接下发会通过q->mq_ops->queue_rq()下发IO,但若由于资源不足(比如tag不够),会将当前IO请求放入hctx->dispatch链中。然后通过函数blk_mq_run_hw_queue()以同步方式执行hcxt上IO请求。

3. IO调度器下发路径

        对于需要通过IO调度器中排序和合并的情况时,通过函数blk_mq_sched_insert_request(rq, false, true, true)将IO请求插入到IO调度器中(若没有定义IO调度器(调度器类型为none),将IO请求插入到ctx->rq_lists即每CPU的请求链表)。最终也通过函数blk_mq_run_hw_queue()以异步方式执行hctx中IO请求。

4. 函数blk_mq_run_hw_queue()

        无论是直接下发IO还是通过IO调度器下发,最终通过函数blk_mq_run_hw_queue()下发IO。

函数blk_mq_run_hw_queue()简单流程如下所示:

  1. 检查参数,若是异步,执行workqueue的run_work;
  2. 若是同步,先检查hctx->dispatch上(当资源不足时放入hctx->dispatch)是否存在未完成的IO,若存在执行未完成的IO;
  3. 执行步骤(2)后仍有IO待完成,检查是否定义调度器类型,若定义,从调度器中取IO下发,若没有定义,从ctx->rq_lists中取IO下发;
  4. 若hctx->dispatch上没有未完成的IO,执行步骤(3)

5. 小结

        准备好request后,可以直接往驱动下发IO,不经过调度层,但若遇到资源不足时,会将未完成的IO放入hctx->dispatch中,然后同步执行blk_mq_run_hw_queue();也可以根据调度层是否定义调度器,决定从调度器中或从ctx->rq_lists中取IO下发,以异步执行blk_mq_run_hw_queue()。若异步执行,通过workqueue执行run_work下发IO,若同步执行,先从hctx->dispatch中取IO执行,再根据是否定义调度器类型,决定是从调度器中取IO还是从ctx->rq_lists中取IO下发。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值