目录
0.前言
内核版本:4.19
文档目的: 主要以null_dev为例来研究多队列的工作机制, 为了能够凸显多队列的工作流程,只对block层做重点分析说明,对其它代码只做注释性说明。
本文主要通过分析null blk块设备的初始化流程,来理解多队列的初始化,流程。
1. null_init
static int __init null_init(void)
|--struct nullb *nullb;
| struct nullb_device *dev;
|--config_group_init(&nullb_subsys.su_group)
|--configfs_register_subsystem(&nullb_subsys)
|--register_blkdev(0, "nullb")
\--for (i = 0; i < nr_devices; i++)
dev = null_alloc_dev();
null_add_dev(dev);
null_init为null dev创建gendisk并注册进系统,创建软硬件队列及其映射关系,期间也会为null设备创建派发队列并初始化
1. config_group_init 初始化cofigfs group以供使用
2. configfs_register_subsystem: 将config group注册进configfs
3. null_alloc_dev 分配nullb_device,并初始化nullb_device的成员
4. register_blkdev完成了nullb块设备的注册,实际是添加到全局major_names数组中
5. null_add_dev为null设备创建gendisk并注册进系统
static int null_add_dev(struct nullb_device *dev)
|--struct nullb *nullb;
|--null_validate_conf(dev)
|--nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, dev->home_node);
| nullb->dev = dev;
| dev->nullb = nullb
|
|--setup_queues(nullb)
|--if (dev->queue_mode == NULL_Q_MQ)
| null_init_tag_set(nullb, nullb->tag_set)
| nullb->q = blk_mq_init_queue_data(nullb->tag_set, nullb);
| else if (dev->queue_mode == NULL_Q_BIO)
| nullb->q = blk_alloc_queue(dev->home_node);
| rv = init_driver_queues(nullb);
|--nullb->q->queuedata = nullb;
|--blk_queue_logical_block_size(nullb->q, dev->blocksize)
|--blk_queue_physical_block_size(nullb->q, dev->blocksize)
|--null_config_discard(nullb);
\--null_gendisk_register(nullb)
|--struct gendisk *disk;
|--disk = nullb->disk = alloc_disk_node(1, nullb->dev->home_node);
|--set_capacity(disk, size);
|--if (queue_is_mq(nullb->q))
| disk->fops = &null_rq_ops;
| else
| disk->fops = &null_bio_ops;
\--add_disk(disk)
null_add_dev创建tag set并初始化,创建软硬件队列及其映射关系,为null设备创建request_queue并初始化,为null设备创建gendisk并注册进系统
1. setup_queues主要为nullb_queue分配空间,队列个数由nullb->dev->submit_queues来定义
同时也设置了队列深度
2,n

本文以nullblk块设备为例,详细分析了Linux内核4.19版本中多队列的工作机制。从nullblk的初始化流程入手,深入探讨了多队列的创建、软硬件队列的映射及调度器的初始化过程。
最低0.47元/天 解锁文章
6212

被折叠的 条评论
为什么被折叠?



