Linux Block layer-Multi Queue

发布于:2023-01-09 ⋅ 阅读:(532) ⋅ 点赞:(0)

1.Block layer- Multi queue overview

Proposed two level Linux block layer design:

 


2. Multi queue Process flow overview-kernel

以当前内核提供的Multi queue的API为例,展示Multi queue的初始化,下发和处理流程:


3. Multi queue Process flow overview-framework

Multi queue在内核中下发的整体框架图:

 


4. Basic data structure:

bio和request在内核中链接结构:

bio和request在内核中的定义:

        request是block层下发给scsi层的最小的IO单元(IO调度的最小单元),描述一段block设备地址连续的IO请求,包含一个或者多个连续的bio,还包含了调度器及软硬件队列(mq_ctx和mq_hctx)管理request时需要使用的链表节点结构。其中request结构体中__sector记录当前request请求的IO在磁盘上的起始扇区以及数据长度;__data_len记录当前request需要对block设备进行操作的数据大小;bio指向request第一个bio;bio_tail指最后一个bio。

        bio是block层的IO最小单元,负责在block层以及其上下层之间传递数据。 bio数据结构中除了包含IO的一些基础信息,操作类型(读/写/discard...),作用的磁盘/分区(反应在bi_disk指针上),IO优先级,状态等等。 bio最重要的信息是描述了磁盘上一段连续数据与内存页的映射关系,主要由bi_vcnt,bi_io_vec,bi_iter 描述。

 

 

        bio_vec是描述磁盘数据与内存页映射的最小单元,每个bio_vec以offset & size形式描述一个内存页中的一段数据。 每个bio 通常有多个bio_vec,bio_vec以数组的形式存储,*bi_io_vec 指向数组头,bi_vcnt记录了其个数。 bi_inline_vecs是为每个bio预分配的bio_vec数组,包括4个bio_vec,若bio需要分配的bio_vec小于4可直接使用bi_inline_vecs,不需要再额外申请内存,此时bi_io_vec会指向bi_inline_vecs

        bver_iter用于遍历bi_io_vec数组,可由bio_for_each_segment等宏来使用。bvec_iter记录了当前IO请求在磁盘上的起始扇区(bi_sector)以及bi_size表示数据长度,bi_idx用以记录当前所在的bio_vec索引号。

         blk_mq_tag_set和blk_mq_tags很容易被混淆。实际上blk_mq_tag_set作为一种公共属性的结构,scsi层通过上报来的参数填充blk_mq_tag_set(比如硬件队列数;映射表数量;队列深度;命令区大小-非CDB,远比CDB复杂;标志),起到更新软硬件队列映射关系,根据硬件队列数分配blk_mq_tags,根据队列深度预分配request池并初始化的作用。

        blk_mq_tags是由blk_mq_tag_set分配而来,内核通过bitmap方式的方式进行管理。

 硬件队列(blk_mq_hw_ctx)和软件队列(blk_mq_ctx):

 


 5. Multi queue set up functions:

scsi_mq_setup_tag:

 需要值得注意的是cmd_size不仅有从底层驱动程序上报来的cmd_size,还包含了scsi_cmnd和sgl的大小;同时将scsi层与block层交互的函数挂载到tag_set->ops上。scsi_mq_setup_tag执行完毕后blk_mq_tags和对应的request池会链接起来,为后续硬件队列的链入打下基础。

blk_mq_alloc_tag_set:

scsi_mq_ops包含的是scsi层与block层交互的函数:

 scsi_alloc_sdev,重点是blk_mq_init_queue函数:

         blk_mq_init_queue实现对每一个scsi设备分配request_queue,软硬件队列之间,硬件队列和tags之间的相互链接,设置该scsi设备的请求超时时间。

 


网站公告

今日签到

点亮在社区的每一天
去签到