block层:3. plug机制

news/2024/11/28 23:48:21/

Kernel源码笔记目录

block层:1. 提交io
block层:2. mq提交io
block层:3. plug机制
block层:4. 运行队列
block层:5. 请求分配
block层:6. tag机制
block层:7. 请求下发
block层:8. deadline调度器

plug 机制

源码基于5.10

blk_start_plug

void blk_start_plug(struct blk_plug *plug)
{struct task_struct *tsk = current;// 该进程已经有了plugif (tsk->plug)return;// 一些基本的初始化INIT_LIST_HEAD(&plug->mq_list);INIT_LIST_HEAD(&plug->cb_list);plug->rq_count = 0;plug->multiple_queues = false;plug->nowait = false;// 设置值tsk->plug = plug;
}

blk_finish_plug

void blk_finish_plug(struct blk_plug *plug)
{// 当前进程没有plugif (plug != current->plug)return;// 刷出plugblk_flush_plug_list(plug, false);// 当前进程plug置空current->plug = NULL;
}

blk_mq_plug

static inline struct blk_plug *blk_mq_plug(struct request_queue *q,struct bio *bio)
{/** 对于普通块设备和读请求使用current->plug,如果blk_start_plug()还没执* 行时它是NULL*/if (!blk_queue_is_zoned(q) || !op_is_write(bio_op(bio)))return current->plug;/* Zoned block device write operation case: do not plug the BIO */return NULL;
}

blk_add_rq_to_plug

static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq)
{// 把请求加到末尾list_add_tail(&rq->queuelist, &plug->mq_list);// 请求数量增加plug->rq_count++;// 当前plug没有多个队列的请求 && 有多个请求if (!plug->multiple_queues && !list_is_singular(&plug->mq_list)) {struct request *tmp;// 第一个请求tmp = list_first_entry(&plug->mq_list, struct request,queuelist);// 如果rq的队列和第1个请求不是一个队列,则标记plug里的请求有多个队列if (tmp->q != rq->q)plug->multiple_queues = true;}
}

blk_flush_plug_list

void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
{// 先调用回调列表flush_plug_callbacks(plug, from_schedule);// 请求列表不为空,则刷出请求if (!list_empty(&plug->mq_list))blk_mq_flush_plug_list(plug, from_schedule);
}static void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule)
{LIST_HEAD(callbacks);// 遍历plug的回调函数列表,这个循环主要是怕在调用回调期间再往回调链表上加回调while (!list_empty(&plug->cb_list)) {// 把plug的回调列表链到callbacks上,然后初始化cb_list// 这样做主要是为了在调用回调期间再往上加新的回调?list_splice_init(&plug->cb_list, &callbacks);// 遍历每个回调while (!list_empty(&callbacks)) {// 取出回调struct blk_plug_cb *cb = list_first_entry(&callbacks,struct blk_plug_cb,list);// 从callbacks列表上删除回调list_del(&cb->list);// 调用回调cb->callback(cb, from_schedule);}}
}void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
{LIST_HEAD(list);// 请求列表为空if (list_empty(&plug->mq_list))return;// 把请求放到临时列表上,并初始化mq_listlist_splice_init(&plug->mq_list, &list);// 请求数大于2 && plug里的请求有多个队列if (plug->rq_count > 2 && plug->multiple_queues)// 给链表排序,plug_rq_cmp是按照请求的ctx, hctx来排序// 这样能优化效率list_sort(NULL, &list, plug_rq_cmp);// 请求数量置0plug->rq_count = 0;do {struct list_head rq_list;// head_rq:请求头struct request *rq, *head_rq = list_entry_rq(list.next);struct list_head *pos = &head_rq->queuelist; /* skip first */// 硬上下文struct blk_mq_hw_ctx *this_hctx = head_rq->mq_hctx;// 软上下文struct blk_mq_ctx *this_ctx = head_rq->mq_ctx;// depth是给一个队列里插入请求的数量unsigned int depth = 1;// 遍历plug里的请求队列,算出同一个队列里要插入请求的数量// 因为depth刚开始是1,所以从第2个开始遍历list_for_each_continue(pos, &list) {// 获取请求rq = list_entry_rq(pos);// 请求的队列为空,什么情况?BUG_ON(!rq->q);// 上下文不一致,退出if (rq->mq_hctx != this_hctx || rq->mq_ctx != this_ctx)break;// 请求数量加1depth++;}// 这个函数会把[list, pos)的元素放到rq_list里,然后把list指向poslist_cut_before(&rq_list, &list, pos);trace_block_unplug(head_rq->q, depth, !from_schedule);// 给队列里插入list里的请求blk_mq_sched_insert_requests(this_hctx, this_ctx, &rq_list,from_schedule);} while(!list_empty(&list));
}static int plug_rq_cmp(void *priv, const struct list_head *a,const struct list_head *b)
{struct request *rqa = container_of(a, struct request, queuelist);struct request *rqb = container_of(b, struct request, queuelist);// 先比软队列if (rqa->mq_ctx != rqb->mq_ctx)return rqa->mq_ctx > rqb->mq_ctx;// 再比硬队列if (rqa->mq_hctx != rqb->mq_hctx)return rqa->mq_hctx > rqb->mq_hctx;// 软硬都相同,再比qosreturn blk_rq_pos(rqa) > blk_rq_pos(rqb);
}

http://www.ppmy.cn/news/1078715.html

相关文章

视频云存储/安防监控/AI视频智能分析网关V3:工服检测功能详解

在一些工地、后厨、化工、电力等特定的场景中,工服的穿戴是必不可少的。这不仅是安全制度的要求,更能降低工作风险、提高工作效率。TSINGSEE青犀AI 边缘计算网关硬件 —— 智能分析网关可以通过实时监测和识别工人的工装穿戴情况,确保他们符合…

数字化新零售平台系统提供商,门店商品信息智慧管理-亿发进销存

传统的批发零售业务模式正面临着市场需求变化的冲击。用户日益注重个性化、便捷性和体验感,新兴的新零售模式迅速崛起,改变了传统的零售格局。如何在保持传统业务的基础上,变革发展,成为了业界亟需解决的问题。 在这一背景下&…

Windows安装FFmpeg说明

下载地址 官网 Download FFmpeg Csdn ffmpeg安装包,ffmpeg-2023-08-28-git-b5273c619d-full-build.7z资源-CSDN文库 解压安装,添加环境变量 命令行输入ffmpeg 安装成功

Leetcode54螺旋矩阵

思路:用set记录走过的地方,记下走的方向,根据方向碰壁变换 class Solution:def spiralOrder(self, matrix: list[list[int]]) -> list[int]:max_rows len(matrix)max_cols len(matrix[0])block_nums max_cols * max_rowscount 1i 0j…

Vue2 集成 CodeMirror 实现公式编辑、块状文本编辑,TAG标签功能

效果图 安装codemirror依赖 本示例为Vue2项目&#xff0c;安装低版本的依赖 npm i codemirror5.65.12 npm i vue-codemirror4.0.6 实现 实现代码如下&#xff0c;里边涉及到的变量和函数自行替换即可&#xff0c;没有其他复杂逻辑。 <template><div class"p…

【日积月累】后端刷题日志

刷题日志 说说对Java的理解JAVA中抽象类和接口之间的区别Java中的泛型 和equals()的区别八种基本数据类型与他们的包装类在一个静态方法内调用一个非静态成员为什么是非法的静态方法与实例方法有何不同重载与重写深拷贝浅拷贝面向过程与面向对象成员变量与局部变量Spring框架Sp…

git文件夹内容详解

.git文件夹是Git版本控制系统在项目根目录下创建的隐藏文件夹&#xff0c;包含了Git仓库的所有相关信息。如下是.git文件夹中常见的一些内容及其作用&#xff1a; HEAD&#xff1a;指向当前所在的分支&#xff08;或者是一个特定的提交&#xff09;。 branches&#xff1a;存储…

计算机视觉-YOYO-

目录 计算机视觉-YOYO 目标检测发展历程 区域卷积神经网络(R-CNN) Fast R-CNN Mask R-CNN模型 比如SSD、YOLO(1, 2, 3)、R-FCN 目标检测基础概念 边界框、锚框和交并比 边界框&#xff08;bounding box&#xff09; 锚框&#xff08;Anchor box&#xff09; 交并比 …