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

rbd块设备数据IO流程(client端)

一、rbd内核驱动写入流程

1)初始化

首先是rbd驱动的初始化工作:包括验证libceph的兼容性,分配内存,在sysfs中创建块设备控制文件、创建工作队列rbd_wq并调用INIT_WORK初始化它

module_init(rbd_init);
static int __init rbd_init(void)
{
if (!libceph_compatible(NULL)) { //兼容性
rbd_warn(NULL, "libceph incompatibility (quitting)");
return -EINVAL;
}
rbd_wq = alloc_workqueue(RBD_DRV_NAME, WQ_MEM_RECLAIM, 0);  //创建工作队列
if (!rbd_wq)
{rc = -ENOMEM;goto err_out_slab;
}
rc = rbd_slab_init(); //初始化内存分配器
if (rc)
return rc;
.......
rc = rbd_sysfs_init(); //创建/sys/bus/rbd/
if (rc)
goto err_out_blkdev;
...}static int rbd_init_request(void *data, struct request *rq,unsigned int hctx_idx, unsigned int request_idx,unsigned int numa_node)
{struct work_struct *work = blk_mq_rq_to_pdu(rq);INIT_WORK(work, rbd_queue_workfn);  //初始化一个work,work通过rbd_queue_workfn进行处理return 0;
}

2)块设备创建、工作队列中启动work

添加块设备,首先创建一个rbd client用来通信,然后选择一个pool存储池去创建rbd设备,创建完成后调用rbd_dev_device_setup初始化rbd设备,在初始化块设备的时候会启动工作队列rbd_wq,并将通用块设备层的请求转化为一个work添加到rbd_wq工作队列中,然后由cpu调度执行工作队列rbd_wq中的work,work对应的处理函数为rbd_queue_workfn,该work用于处理通用块设备层的IO请求。

启动work的调用关系: rbd_dev_device_setup → rbd_init_disk  → rbd_mq_ops → rbd_init_request → rbd_queue_workfn处理函数

static BUS_ATTR(add, S_IWUSR, NULL, rbd_add);
static BUS_ATTR(remove, S_IWUSR, NULL, rbd_remove);
static BUS_ATTR(add_single_major, S_IWUSR, NULL, rbd_add_single_major);
static BUS_ATTR(remove_single_major, S_IWUSR, NULL, rbd_remove_single_major);static int rbd_queue_rq(struct blk_mq_hw_ctx *hctx,const struct blk_mq_queue_data *bd)
{struct request *rq = bd->rq;struct work_struct *work = blk_mq_rq_to_pdu(rq);  //通用块设备层请求转为workqueue_work(rbd_wq, work);  //将work加入到工作队列,工作队列中的work由cpu调度处理return BLK_MQ_RQ_QUEUE_OK;
}static ssize_t rbd_add(struct bus_type *bus,const char *buf,size_t count)
{if (single_major)return -EINVAL;return do_rbd_add(bus, buf, count);
}static ssize_t do_rbd_add(struct bus_type *bus,const char *buf,size_t count)
{.....rbdc = rbd_get_client(ceph_opts);  //获取或创建rbd_clientif (IS_ERR(rbdc)) {rc = PTR_ERR(rbdc);goto err_out_args;}/* pick the pool */rc = rbd_add_get_pool_id(rbdc, spec->pool_name);  //选择存储池if (rc < 0) {if (rc == -ENOENT)pr_info("pool %s does not exist\n", spec->pool_name);goto err_out_client;}spec->pool_id = (u64)rc;rbd_dev = rbd_dev_create(rbdc, spec, rbd_opts);  //创建rbd设备down_write(&rbd_dev->header_rwsem);
......rc = rbd_dev_image_probe(rbd_dev, 0);  //探针更多的是检查rbd image是否被mapif (rc < 0) {up_write(&rbd_dev->header_rwsem);goto err_out_rbd_dev;}
......rc = rbd_dev_device_setup(rbd_dev);  //包括obj->pg映射等static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
{int ret;
....../* Set up the blkdev mapping. */ret = rbd_init_disk(rbd_dev); ......
}static int rbd_init_disk(struct rbd_device *rbd_dev)
{struct gendisk *disk;struct request_queue *q;u64 segment_size;int err;
.....memset(&rbd_dev->tag_set, 0, sizeof(rbd_dev->tag_set));rbd_dev->tag_set.ops = &rbd_mq_ops;                        //rbd_dev初始化rbd_dev->tag_set.queue_depth = rbd_dev->opts->queue_depth;rbd_dev->tag_set.numa_node = NUMA_NO_NODE;
.....
}static struct blk_mq_ops rbd_mq_ops = {.queue_rq   = rbd_queue_rq,.init_request   = rbd_init_request,   //调用rbd_init_request
};static int rbd_init_request(void *data, struct request *rq,unsigned int hctx_idx, unsigned int request_idx,unsigned int numa_node)
{struct work_struct *work = blk_mq_rq_to_pdu(rq);INIT_WORK(work, rbd_queue_workfn);  //通过work_struct启动线程return 0;
}

3)work处理函数rbd_queue_workfn内流程分析

从上层取出通用块设备层请求后,转换为image对象,再从image对象批量转为object对象,再计算出object到pg,pg到osd的映射关系。

3.1 获取通用块设备层信息

在rbd_queue_workfn中,通过blk_mq_rq_from_pdu获取到通用块设备层IO请求rq、通过blk_rq_bytes(rq)获取到请求中需要写入的数据长度length(length表示的是客户端需要写到磁盘总的数据长度),通过blk_rq_pos(rq)获取块设备写入偏移量offset。

static void rbd_queue_workfn(struct work_struct *work)
{struct request *rq = blk_mq_rq_from_pdu(work);  //通用块设备层请求struct rbd_device *rbd_dev = rq->q->queuedata;struct rbd_img_request *img_request;struct ceph_snap_context *snapc = NULL;u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;  //块设备的偏移量u64 length = blk_rq_bytes(rq);  //enum obj_operation_type op_type;
.....
}

3.2 通用块设备层信息转换image请求,image请求批量转换为object

在rbd_queue_workfn中从通用块设备层请求中获取到块设备偏移offset和长度length后,再使用这些指标来创建img_request并将img_request→offset进行填充中,然后调用rbd_img_request_fill函数,在该函数中,基于rados object的大小(4M)与rados对象在rbd中的segment排列,对请求进行拆分,最终将rbd_img_request拆分成多个rbd_obj_request对象,通过这样的过程实现从linux内核的通用块请求到ceph rados object的转换。

static void rbd_queue_workfn(struct work_struct *work)
{struct request *rq = blk_mq_rq_from_pdu(work);struct rbd_device *rbd_dev = rq->q->queuedata;struct rbd_img_request *img_request;u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;  //块设备偏移u64 length = blk_rq_bytes(rq);  //长度
......img_request = rbd_img_request_create(rbd_dev, offset, length, op_type,  //创建img_requestsnapc); img_request->offset = offset;  //填充img_request→offsetresult = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,  //将rbd_img_request划分为一个个rbd_obj_requestrq->bio);
.....
}static int rbd_img_request_fill(struct rbd_img_request *img_request,enum obj_request_type type,void *data_desc)
{struct rbd_obj_request *obj_request = NULL;u64 img_offset;img_offset = img_request->offset;  //块设备当前写入的偏移位置resid = img_request->length;  //待写入的长度while (resid) {
......object_name = rbd_segment_name(rbd_dev, img_offset);  //对象名length = rbd_segment_length(rbd_dev, img_offset, resid);  //长度obj_request = rbd_obj_request_create(object_name,  //创建obj_request对象offset, length, type);
......img_offset += length;  //偏移增加lengthresid -= length;
......
}

3.3 rbd块设备offset到rados object的映射

rbd块设备到rados对象的映射是根据rados对象的大小以及当前块设备的偏移量来决定的,并且rados对象的命名方式采用前缀rbd_data.$image_id.16位16进制的序号构成。

3.3.1 rados对象大小与命名方式

每个rbd块设备都定义了一个2为底的指数来表示每个rbd对象的大小,这个指数称为rbd的obj order。obj order默认值为22,因此每个rbd对象大小2^22Bytes,即每个rados对象大小为4MB。

相关文章:

rbd块设备数据IO流程(client端)

一、rbd内核驱动写入流程 1&#xff09;初始化 首先是rbd驱动的初始化工作&#xff1a;包括验证libceph的兼容性&#xff0c;分配内存&#xff0c;在sysfs中创建块设备控制文件、创建工作队列rbd_wq并调用INIT_WORK初始化它 module_init(rbd_init); static int __init rbd_i…...

数据仓库、数据中台、大数据平台之间的关系

数据行业经常会出现数据仓库、数据中台、大数据平台等概念&#xff0c;容易产生疑问&#xff0c;它们中间是相等&#xff0c;还是包含的关系&#xff1f; 数据中台和数据仓库概念的关系 数据中台概念是包含数据仓库的&#xff0c;数据仓库是数据中台中的一部分&#xff0c;包含…...

python写页面自动截图

from selenium import webdriver def take_screenshot(url, file_path):driver webdriver.Chrome()driver.get(url)driver.save_screenshot(file_path)driver.quit() if __name__ __main__:take_screenshot(http://baidu.com, D:\桌面\wang.png)要安装selenium还要安装google…...

【Qt 学习笔记】Qt常用控件 | 布局管理器 | 空白项Spacer

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 布局管理器 | 添加空白Spacer 文章编号&#xff1a;Qt 学…...

es问题汇总--待完善

1. 查询某个索引库中数据总量 方式一&#xff1a; CountRequest 鄙人喜欢这种方式 public long getTotalNum(String indexName) throws IOException {CountRequest countRequest new CountRequest(indexName);// 如果需要&#xff0c;你可以在这里添加查询条件// countReques…...

新一代高性价比LTE Cat.1通信模组ML307R

...

python 线性回归模型

教材链接-3.2. 线性回归的从零开始实现 c实现 该博客仅用于记录一下自己的代码&#xff0c;可与c实现作为对照 from d2l import torch as d2l import torch import random # nn是神经网络的缩写 from torch import nn from torch.utils import data# 加载训练数据 # 加载训…...

pcl::transformPointCloud()用法及注意事项

函数用法 #include <pcl/common/transforms.h> pcl::transformPointCloud(const pcl::PointCloud<PointT> &cloud_in, pcl::PointCloud<PointT> &cloud_out, const Eigen::Matrix4f &transform) 其中cloud_in, cloud_out的类型为pcl::PointClo…...

图像超分辨率重建相关概念、评价指标、数据集、模型

1、图像超分辨率概念 1.1 基本定义 超分辨率&#xff08;Super-Resolution&#xff09;&#xff0c;简称超分&#xff08;SR&#xff09;。是指利用光学及其相关光学知识&#xff0c;根据已知图像信息恢复图像细节和其他数据信息的过程&#xff0c;简单来说就是增大图像的分辨…...

中移物联OneMO Cat.1模组推动联网POS规模应用

在第三方支付蓬勃发展和消费模式不断革新的时代背景下&#xff0c;新型联网POS终端以其智能化、便捷化的特点丰富人们生活便利度。在这一变革浪潮中&#xff0c;中移物联OneMO Cat.1模组ML307R凭借其卓越的性能和成本效益&#xff0c;成为推动联网POS规模应用的重要力量。 性能…...

二.常见算法--贪心算法

&#xff08;1&#xff09;单源点最短路径问题 问题描述&#xff1a; 给定一个图&#xff0c;任取其中一个节点为固定的起点&#xff0c;求从起点到任意节点的最短路径距离。 例如&#xff1a; 思路与关键点&#xff1a; 以下代码中涉及到宏INT_MAX,存在于<limits.h>中…...

LabVIEW高温往复摩擦测试系统中PID控制

在LabVIEW开发高温往复摩擦测试系统中实现PID控制&#xff0c;需要注意以下几个方面&#xff1a; 1. 系统建模与参数确定 物理模型建立: 首先&#xff0c;需要了解被控对象的物理特性&#xff0c;包括热惯性、摩擦系数等。这些特性决定了系统的响应速度和稳定性。实验数据获取…...

配置yum源

以下是在 Linux 系统中配置新的 yum 源的一般步骤和命令示例&#xff08;以 CentOS 系统为例&#xff09;&#xff1a; 备份原有 yum 源配置文件&#xff1a;mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak 创建新的 yum 源配置文件&#xff08…...

深入理解数仓开发(二)数据技术篇之数据同步

1、数据同步 数据同步我们之前在数仓当中使用了多种工具&#xff0c;比如使用 Flume 将日志文件从服务器采集到 Kafka&#xff0c;再通过 Flume 将 Kafka 中的数据采集到 HDFS。使用 MaxWell 实时监听 MySQL 的 binlog 日志&#xff0c;并将采集到的变更日志&#xff08;json 格…...

C++语言学习(六)—— 类与对象(二)

目录 一、对象数组 二、对象指针 三、this 指针 四、类类型作为参数类型的三种形式 4.1 对象本身作为参数 4.2 对象指针作为参数 4.3 对象引用作为参数 五、静态成员 5.1 静态数据成员 5.2 静态成员函数 六、友元机制 6.1 友元函数 6.2 友元类 七、类的组合 八、…...

3d选择模型后不能旋转什么原因?怎么解决?---模大狮模型网

在3D建模和渲染的过程中&#xff0c;旋转模型是常见的操作。然而&#xff0c;有时在选择了模型后&#xff0c;却发现无法进行旋转&#xff0c;这可能会让许多用户感到困扰。本文将探讨3D选择模型后不能旋转的可能原因&#xff0c;并提供相应的解决方法。 一、3D选择模型后不能旋…...

从入门到精通:详解Linux环境基础开发工具的使用

前言 在这篇文章中&#xff0c;我将深入学习和理解Linux环境基础开发工具的使用。无论你是初学者还是有一定经验的开发者&#xff0c;相信这篇文章都会对你有所帮助。我们将详细讲解软件包管理器、编辑器、编译器、调试器、自动化构建工具以及版本控制工具的使用。 Linux软件…...

linux(centos 7)安装 node

linux&#xff08;centos 7&#xff09;安装 node 下载对应版本&安装解压配置环境变量使配置文件生效验证是否安装成功附加 目前node最新版本是 node-v22.0.0 官网下载地址&#xff1a;https://registry.npmmirror.com/binary.html?pathnode/latest-v22.x/node-v22.0.0-li…...

C++之第九课

课程列表 今天&#xff0c;我们要学习一种结构&#xff1a;循环结构。 循环的方法有3种。 今天先将第1种for学了&#xff1a; int a;//循环变量 int b; for(a1;a<10;a){//像if那样“打包”cout<<a<<" ";b; } 当然&#xff0c;也可以这样写&#…...

618精选编程书单推荐:优质知识提升你的代码力

前言 在这个快速发展的技术时代&#xff0c;不断学习和提升自己的编程技能是每位程序员的必修课。今天&#xff0c;我为大家精心挑选了一系列编程技术书籍&#xff0c;它们将是你技术成长道路上的宝贵财富。 文章目录 前言编程之路&#xff1a;为何阅读书籍是不可或缺的书籍的…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...