1、首先看一下blk-mq的处理流程图(不同内核版本之间会有一些差异,但整体结构基本一样)
从整个流程图可以看到,主要是分为三个部分:(1)初始化硬件设备的相关参数(2)初始化请求队列request_queue(3)bio请求的处理过程。前面两个过程主要是完成底层存储设备向文件系统的注册,同时完成软硬队列映射关系等初始化,后一个部分是bio在MQ机制最后生成对应子请求并挂载在硬件队列上的过程。
2、接下来我们来分析具体的函数
(1)int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)——为一个或者多个request queue分配tag
/*
* Alloc a tag set to be associated with one or more request queues.
* May fail with EINVAL for various error conditions. May adjust the
* requested depth down, if it's too large. In that case, the set
* value will be stored in set->queue_depth.
*/
//为一个或者多个请求队列分配tag(tag set可以是多个request queue共享的)
int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
{
int i, ret;
BUILD_BUG_ON(BLK_MQ_MAX_DEPTH > 1 << BLK_MQ_UNIQUE_TAG_BITS);
if (!set->nr_hw_queues) //硬件队列身量
return -EINVAL;
if (!set->queue_depth) //软件队列深度
return -EINVAL;
if (set->queue_depth < set->reserved_tags + BLK_MQ_TAG_MIN) //块设备保留的tag数
return -EINVAL;
if (!set->ops->queue_rq) //ops表示块设备驱动的抽象集合
return -EINVAL;
if (!set->ops->get_budget ^ !set->ops->put_budget)
return -EINVAL;
if (set->queue_depth > BLK_MQ_MAX_DEPTH) {
pr_info("blk-mq: reduced tag depth to %u\n",
BLK_MQ_MAX_DEPTH);
set->queue_depth = BLK_MQ_MAX_DEPTH;
}
if (!set->nr_maps) //映射表数量
set->nr_maps = 1;
else if (set->nr_maps > HCTX_MAX_TYPES)
return -EINVAL;
/*
* If a crashdump is active, then we are potentially in a very
* memory constrained environment. Limit us to 1 queue and
* 64 tags to prevent using too much memory.
*/
if (is_kdump_kernel()) {
set->nr_hw_queues = 1;
set->nr_maps = 1;
set->queue_dept