当前位置: 首页 > news >正文

blk_mq_init_queue函数学习记录

blk-mq编程,主要要调用两个函数进行初始化工作,blk_mq_init_queue这是第二个。该函数先是申请了struct request_queue结构,这个请求队列后面用于赋值给磁盘那个结构体的相应成员。

struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
{struct request_queue *uninit_q, *q;//分配struct request_queue并初始化uninit_q = blk_alloc_queue_node(GFP_KERNEL, set->numa_node, NULL);if (!uninit_q)return ERR_PTR(-ENOMEM);/*1:分配每个cpu专属的软件队列并初始化2:分配硬件队列,并初始化3:建立软件队列和硬件队列的联系*/q = blk_mq_init_allocated_queue(set, uninit_q);if (IS_ERR(q))blk_cleanup_queue(uninit_q);return q;
}
EXPORT_SYMBOL(blk_mq_init_queue);

blk_mq_init_allocated_queue函数分析

一眼望过去,确实有点复杂,不过,多看几遍就好了,
这里面,主要就是给struct request_queue *q结构体里面的成员变量赋值的,简单的变量赋值就不分析了,看看它调用的函数进行分析。

struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, struct request_queue *q)
{/* mark the queue as mq asap */q->mq_ops = set->ops;q->poll_cb = blk_stat_alloc_callback(blk_mq_poll_stats_fn, blk_mq_poll_stats_bkt, BLK_MQ_POLL_STATS_BKTS, q);if (!q->poll_cb)goto err_exit;q->queue_ctx = alloc_percpu(struct blk_mq_ctx);//percpu变量 软件队列if (!q->queue_ctx)goto err_exit;/* init q->mq_kobj and sw queues' kobjects */blk_mq_sysfs_init(q); //主要是初始化kobject变量//二级指针 硬件队列q->queue_hw_ctx = kcalloc_node(nr_cpu_ids, sizeof(*(q->queue_hw_ctx)), GFP_KERNEL, set->numa_node);if (!q->queue_hw_ctx)goto err_percpu;//赋值q->mq_map,这个数组保存了每个CPU对应的硬件队列编号q->mq_map = set->mq_map;blk_mq_realloc_hw_ctxs(set, q);if (!q->nr_hw_queues)goto err_hctxs;/*定时器初始化,设置超时时间*/INIT_WORK(&q->timeout_work, blk_mq_timeout_work);blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);q->nr_queues = nr_cpu_ids;q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;if (!(set->flags & BLK_MQ_F_SG_MERGE))queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);q->sg_reserved_size = INT_MAX;INIT_DELAYED_WORK(&q->requeue_work, blk_mq_requeue_work);INIT_LIST_HEAD(&q->requeue_list);spin_lock_init(&q->requeue_lock);blk_queue_make_request(q, blk_mq_make_request);if (q->mq_ops->poll)q->poll_fn = blk_mq_poll;/** Do this after blk_queue_make_request() overrides it...*/q->nr_requests = set->queue_depth; //防止被覆盖/** Default to classic polling*/q->poll_nsec = -1;if (set->ops->complete)blk_queue_softirq_done(q, set->ops->complete);blk_mq_init_cpu_queues(q, set->nr_hw_queues);blk_mq_add_queue_tag_set(set, q);blk_mq_map_swqueue(q);if (!(set->flags & BLK_MQ_F_NO_SCHED)) {int ret;ret = elevator_init_mq(q);if (ret)return ERR_PTR(ret);}return q;
err_hctxs:kfree(q->queue_hw_ctx);
err_percpu:free_percpu(q->queue_ctx);
err_exit:q->mq_ops = NULL;return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL(blk_mq_init_allocated_queue);

blk_stat_alloc_callback

这个函数一看也没什么分析的,主要也是给poll_cb进行赋值,采用了很多的默认函数进行赋值。

struct blk_stat_callback *
blk_stat_alloc_callback(void (*timer_fn)(struct blk_stat_callback *),int (*bucket_fn)(const struct request *), unsigned int buckets, void *data)
{struct blk_stat_callback *cb;cb = kmalloc(sizeof(*cb), GFP_KERNEL);if (!cb)return NULL;cb->stat = kmalloc_array(buckets, sizeof(struct blk_rq_stat), GFP_KERNEL);if (!cb->stat) {kfree(cb);return NULL;}cb->cpu_stat = __alloc_percpu(buckets * sizeof(struct blk_rq_stat), __alignof__(struct blk_rq_stat));if (!cb->cpu_stat) {kfree(cb->stat);kfree(cb);return NULL;}cb->timer_fn = timer_fn;cb->bucket_fn = bucket_fn;cb->data = data;cb->buckets = buckets;timer_setup(&cb->timer, blk_stat_timer_fn, 0);return cb;
}
EXPORT_SYMBOL_GPL(blk_stat_alloc_callback);

blk_mq_sysfs_init

接着到这个函数,也是变量的初始化工作,struct request_queue队列里面的kobject变量初始化,以及取出在每一个cpu上q->queue_ctx结构体,然后对齐成员kobject变量进行初始化。

void blk_mq_sysfs_init(struct request_queue *q)
{struct blk_mq_ctx *ctx;int cpu;kobject_init(&q->mq_kobj, &blk_mq_ktype);for_each_possible_cpu(cpu) {ctx = per_cpu_ptr(q->queue_ctx, cpu);//返回每个cpu上的q->queue_ctx变量的首地址kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);}
}

blk_mq_realloc_hw_ctxs

这个函数相对来说比较重要。后面再补充。

在这里插入代码片

blk_queue_make_request

这个函数也是给q的其成员赋值的,先大概熟悉一下,如果有实际的调试分析,需要了解某个参数的值,到时再回来看吧。

void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
{/** set defaults*/q->nr_requests = BLKDEV_MAX_RQ; //这个值后面会重新赋值进行覆盖q->make_request_fn = mfn;blk_queue_dma_alignment(q, 511);blk_queue_congestion_threshold(q);q->nr_batching = BLK_BATCH_REQ;blk_set_default_limits(&q->limits);
}
EXPORT_SYMBOL(blk_queue_make_request);

blk_queue_softirq_done

也是赋值,IO操作完成时,会调用这个回调函数。

void blk_queue_softirq_done(struct request_queue *q, softirq_done_fn *fn)
{q->softirq_done_fn = fn;
}
EXPORT_SYMBOL(blk_queue_softirq_done);

blk_mq_init_cpu_queues

static void blk_mq_init_cpu_queues(struct request_queue *q, unsigned int nr_hw_queues)
{unsigned int i;for_each_possible_cpu(i) { //硬件队列数/*返回这个变量在编号为i的cpu上的起始地址*/struct blk_mq_ctx *__ctx = per_cpu_ptr(q->queue_ctx, i);struct blk_mq_hw_ctx *hctx;//其成员做一些赋值操作__ctx->cpu = i;spin_lock_init(&__ctx->lock);INIT_LIST_HEAD(&__ctx->rq_list);__ctx->queue = q;/** Set local node, IFF we have more than one hw queue. If* not, we remain on the home node of the device*/hctx = blk_mq_map_queue(q, i); //取出每个cpu上的硬件队列if (nr_hw_queues > 1 && hctx->numa_node == NUMA_NO_NODE)hctx->numa_node = local_memory_node(cpu_to_node(i));}
}

blk_mq_add_queue_tag_set


blk_mq_map_swqueue


相关文章:

blk_mq_init_queue函数学习记录

blk-mq编程,主要要调用两个函数进行初始化工作,blk_mq_init_queue这是第二个。该函数先是申请了struct request_queue结构,这个请求队列后面用于赋值给磁盘那个结构体的相应成员。 struct request_queue *blk_mq_init_queue(struct blk_mq_t…...

高防服务器的工作原理

在当今互联网时代,网络安全问题日益突出,各种网络攻击层出不穷。为了保护企业的网络安全,高防服务器应运而生。那么,你是否了解高防服务器的工作原理呢?下面就让我们一起来探索一下。 高防服务器是一种能够有效抵御各种…...

2023.11.19使用flask制作一个文件夹生成器

2023.11.19使用flask制作一个文件夹生成器 实现功能: (1)在指定路径上建立文件夹 (2)返回文件夹的路径和建立成功与否的提示 main.py import os from flask import Flask, request, jsonify, render_templateapp F…...

【04】ES6:字符串的扩展

一、模板字符串 模板字符串是可以插入表达式的字符串字面量。模板字符串和传统字符串比较,存在以下特点: 1、使用反单引号 传统字符串字面量使用单引号 ‘’ 或者双引号 “”,模板字符串使用反单引号(backquote) …...

Docker可视化管理界面工具Portainer安装

Portainer是Docker容器管理界面工具,可以直观的管理Docker。 部署也很简单: 官方安装文档地址 1、创建数据卷 docker volume create portainer_data2、下载允许容器 docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restartalways -v /v…...

css实现水波纹效果

css实现水波纹效果 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><styl…...

一种全新且灵活的 Prompt 对齐优化技术

并非所有人都熟知如何与 LLM 进行高效交流。 一种方案是&#xff0c;人向模型对齐。 于是有了 「Prompt工程师」这一岗位&#xff0c;专门撰写适配 LLM 的 Prompt&#xff0c;从而让模型能够更好地生成内容。 而另一种更为有效的方案则是&#xff0c;让模型向人对齐。 这也是…...

8:kotlin 类型检查和转换(Type checks and casts)

在运行时可以执行类型检查以检查对象的类型。类型转换将对象强制转换为不同的类型 is 和 !is 可以使用is或者!is来判断实例是不是指定的类型 fun main() {var obj : Any "cast"if (obj is String) {println(obj.length) // 4}obj 123if (obj !is String) { pr…...

命令模式 (Command Pattern)

定义 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;它将一个请求封装为一个对象&#xff0c;从而允许用户使用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。主要目的是将命令的发送者和接收者解耦&#xff0c;引…...

蓝桥杯官网练习题(奇怪的数列)

题目描述 从 X 星截获一份电码&#xff0c;是一些数字&#xff0c;如下&#xff1a; 13 1113 3113132113 1113122113 ⋯ YY 博士经彻夜研究&#xff0c;发现了规律&#xff1a; 第一行的数字随便是什么&#xff0c;以后每一行都是对上一行"读出来" 比如第 2…...

flink的异常concurrent.TimeoutException: Heartbeat of TaskManager with id的解决

背景 在使用flink进行集成测试时&#xff0c;我们会使用MiniClusterWithClientResource类&#xff0c;但是当我们断点导致在某个方法执行的时间比较长时&#xff0c;会有错误发生&#xff0c;那么该如何解决这个错误呢&#xff1f; 处理concurrent.TimeoutException: Heartbe…...

火电安全事故vr模拟仿真培训强交互更真实

VR消防&#xff0c;利用VR虚拟现实技术&#xff0c;将VR和消防教育融合在一起达到寓教于乐的效果&#xff0c; VR消防教育是对于家中、校园内、大型商场、公司办公室等情景产品研发的消防安全培训类VR系统软件&#xff0c;根据互动体验、互动、视角实际操作、视听觉系统多度自然…...

ELK企业级日志分析平台

目录 一、elasticsearch 1、集群部署 2、cerebro部署 3、elasticsearch-head插件部署 4、elasticsearch集群角色分类 二、logstash 1、部署 2、elasticsearch输出插件 3、file输入插件 4、file输出插件 5、syslog 插件 6、多行过滤插件 7、grok过滤 三、kibana数…...

.NET面试题1

1.什么是C#&#xff1f; C#&#xff08;读作"C sharp"&#xff09;是一种通用的、面向对象的编程语言&#xff0c;由Microsoft开发。它是一种静态类型语言&#xff0c;支持强类型检查和面向对象编程&#xff08;OOP&#xff09;的概念。C#主要用于开发Windows应用程序…...

mongodb 日志详情

1 mongodb日志简介 MongoDB的日志包括两个主要部分&#xff1a;操作日志&#xff08;oplog&#xff09;和系统日志。 1.1 操作日志 操作日志&#xff08;oplog&#xff09;是一个特殊的集合&#xff0c;用于记录所有对数据库进行的操作&#xff08;如插入、更新和删除&#x…...

Oracle中文显示???????解决办法

项目场景&#xff1a; Oracleoracle中文显示???解决办法 问题描述 原因分析&#xff1a; Oracle中文显示???通常是由于字符集不匹配或者编码问题导致的。当数据库中的数据使用的是某种字符集&#xff0c;而客户端或者应用程序使用的是另一种字符集时&#xff0c;就会出…...

Java查询数据放入word模板中并在前端导出下载

需求&#xff1a;查询数据放入word模板中并在前端导出下载 解决方法&#xff1a;在模板的位置定义参数如 {{name}} {{age}}等等&#xff0c;使用 poi 处理 伪代码&#xff1a; PostMapping("/practiceAppr")public AjaxResult practiceAppr(OutputStream outputSt…...

HarmonyOS ArkTS 应用添加弹窗(八)

概述 在我们日常使用应用的时候&#xff0c;可能会进行一些敏感的操作&#xff0c;比如删除联系人&#xff0c;这时候我们给应用添加弹窗来提示用户是否需要执行该操作&#xff0c;如下图所示&#xff1a; 弹窗是一种模态窗口&#xff0c;通常用来展示用户当前需要的或用户必须…...

排序算法-----快速排序(非递归实现)

目录 前言 快速排序 基本思路 非递归代码实现 算法分析 空间复杂度 时间复杂度 稳定性 前言 很久没跟新数据结构与算法这一栏了&#xff0c;因为数据结构与算法基本上都发布完了&#xff0c;哈哈&#xff0c;那今天我就把前面排序算法那一块的快速排序完善一下&#xff0…...

el-input限制输入整数等分析

文章目录 前言1、在 Vue 中&#xff0c;可以使用以下几种方式来限制 el-input 只能输入整数1.1 设置input 的 type为number1.2 使用inputmode1.3 使用自定义指令1.4 使用计算属性1.5 使用 onafterpaste ,onkeyup1.6 el-input-number 的precision属性 总结 前言 input 限制输入…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...