block多队列分析 - 1.概述

目录

  • 1. 前言
  • 2. block single queue的问题
  • 3. block multi-queue的引入
  • 4. tag管理
  • 5. 领域模型
  • 参考文档

1. 前言

本专题文章是对多队列部分学习的笔记。主要以null_dev为例来研究多队列的工作机制, 为了能够凸显多队列的工作流程,只对block层做重点分析说明,对其它代码只做注释性说明。本文是概述部分,说明多队列的基本原理,基本框架和工作流程。

kernel版本:5.10
平台:arm64

注:
为方便阅读,正文标题采用分级结构标识,每一级用一个"-“表示,如:两级为”|- -", 三级为”|- - -“

2. block single queue的问题

block多队列分析 - 1.概述_第1张图片
在进入block layer之后,由于对请求队列的访问、查询、完成等处理需要在加锁的情况下进行,因此造成了系统IO性能的瓶颈
block多队列分析 - 1.概述_第2张图片
通过上图可以看出由于block层的共享状态导致了系统IO性能的瓶颈

3. block multi-queue的引入

block mq引入的初衷就是要对block层,在各个应用之间、在request的submission和completion之间打破这种共享状态。
block多队列分析 - 1.概述_第3张图片
如上图,对每一个cpu core创建一个软队列,并在软队列与硬队列之间在初始化时创建映射关系,这样对于软队列的操作无需加锁。
block多队列分析 - 1.概述_第4张图片
应用访问软队列可以做到完全私有访问,submissions基本做到私有访问

4. tag管理

block多队列分析 - 1.概述_第5张图片
对于每一个request通过tag来标识,在将request分发给hardware之前会从tag pool中申请,request完成后会将tag归还到tag pool

5. 领域模型

block多队列分析 - 1.概述_第6张图片

  • nullb
    nullb为null dev的数据结构,它内嵌blk_mq_tag_set ,一般块设备都会内嵌此数据结构

  • blk_mq_tag_set
    内嵌在块设备结构体nullb中,是多队列的集大成者,是维护多队列各要素的数据结构,包含、tags、tag bitmap、软硬队列映射关系等。它内嵌blk_mq_queue数组map,每个数组成员代表一种类型的硬队列,每种类型的硬队列内部又维护着一个数组mq_map,用于保存软硬队列的映射关系。mq_map数组下标为cpu编号,数组元素为cpu编号所对应的硬队列号。
    每个硬队列一个blk_mq_tags结构体,保存在set->tags[hctx_idx]中, 每个blk_mq_tags是通过sbitmap_queue来描述,每个bit代表一个tag, 对应一个request;

  • blk_mq_queue_map
    为blk_mq_tag_set的内嵌结构体,用于描述软硬队列之间的映射关系。在blk_mq_tag_set中定义了一个blk_mq_queue_map数组,每个数组元素代表一种硬队列类型,主要的硬队列类型包括三种:HCTX_TYPE_DEFAULT,HCTX_TYPE_READ,HCTX_TYPE_POLL
    对于每种硬队列,blk_mq_queue_map中定义了一个mq_map数组,它保存了软队列与硬队列的映射关系,set->map[i]->mq_map数组下标为cpu编号,数组元素为硬队列号

  • blk_mq_tags
    用于tag空间管理。tags中包含了对request及payload的分配, page_list就是用于链接分配出的page; blk_mq_tags与硬队列blk_mq_hw_ctx一一对应,它管理了硬队列的tag bitmap和request,其中每一个tag bit代表了一个request

  • request_queue
    在blk_mq_init_queue_data的过程中会创建request_queue,它通过queue_ctx指向per cpu变量blk_mq_ctx软队列,通过queue_hw_ctx指向硬队列,它的queuedata一般为块设备数据结构nullb; 同时通过backing_dev_info指向了后备设备。
    request_queue可以共享blk_mq_tag_set,通过tag_set_list链接件连入tag_list.
    bio_split是队列的bio池描述符,用来分配bio和bio_vec;
    poll_cb为用于统计的回调函数;
    nr_requests表示软队列的个数;

  • blk_mq_ctx
    软队列,与cpu数目相同,在blk_mq_init_queue_data->blk_mq_init_allocated_queue会分配。它通过hctxs指向对应的硬队列

  • blk_mq_hw_ctx
    硬队列,数目为HCTX_MAX_TYPES, 在blk_mq_init_queue_data->blk_mq_init_allocated_queue->blk_mq_realloc_hw_ctxs时分配。硬队列中包含两种blk_mq_tags,分别为tags(block driver拥有)和sched_tags(io scheduler拥有),可参考blk_mq_hw_ctx中对两者的注释,每个blk_mq_hw_ctx与blk_mq_tags时一一对应的
    block多队列分析 - 1.概述_第7张图片
    tags用来保存硬队列本身所具有的blk_mq_tags
    sched_tags用来保存硬队列所对应的调度队列的blk_mq_tags

  • blk_stat_callback
    每个request_queue队列都有一个blk_stat_callback与之对应,会通过定时器回调函数来定时统计request状态

  • elevator_queue
    通用调度队列描述符,每个request_queue,都有一个struct elevator_queue与之对应。其中hash为哈希表,用于快速查找队列中的request。

  • elevator_type
    具体调度队列描述符,如mq-deadline调度器等

参考文档

Solving the Linux storage scalability bottlenecks, Jens Axboe,Vault 2016

你可能感兴趣的:(#,BLOCK)