当前位置: 首页 > 工具软件 > UnPlug > 使用案例 >

BLOCK层代码分析(8)IO下发之plug/unplug机制

夏侯嘉荣
2023-12-01

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

        BLOCK层的plug/unplug机制为提升处理磁盘的性能:在开启机制后,IO请求会放置到请求池中(plug过程),当达到某个条件时会将IO请求统一下发(unplug过程)。这样有利于BLOCK请求的合并和排序操作。

1. PLUG的时机

        BLOCK PLUG的开启是由函数blk_start_plug()开启的。对于每个线程描述符task_struct,存在成员blk_plug,若为空表示没有使能PLUG,否则表示已使能PLUG。函数blk_start_plug()进行成员初始化,同时给task_struct->plug赋值。

        在开启BLOCK PLUG后,可以将通过函数blk_add_rq_to_plug()将IO请求加入到plug->mq_list中,且判断所包含的IO请求是否来自多个队列(通过成员multiple_queues)。

2. UNPLUG的时机

        目前UNPLUG的时机有三种:

  1. 所积攒的IO数目达到BLK_MAX_REQUEST_COUNT(16)或遇到的IO大小超过BLK_PLUG_FLUSH_SIZE (128K)时;
  2. 使用blk_finish_plug()主动冲刷;
  3. 在线程被调度前会执行函数sched_submit_work()检查线程plug->mq_list上是否存在IO请求,若存在进行异步冲刷;

        无论主动冲刷还是被动冲刷,最终调用函数blk_plug_flush_list()完成IO请求的下发。首先它会根据IO请求是否来自多个请求队列,若是会依次根据IO请求的mq_ctx(软件队列)/mq_hctx(硬件队列)/扇区位置做排序。待排序后依次将属于相同hctx且相同ctx的IO统一下发异步下发,下发具体函数为blk_mq_sched_insert_requests()(后面章节做介绍)。

        对于blk_plug_flush_list(),在调度前冲刷时会其异步线程(workqueue)做IO下发。其他情况目前都是同步做IO下发。

 类似资料: