Ceph的FileStore代码阅读问题整理
liebian365 2024-10-26 13:02 22 浏览 0 评论
1.bufferlist中的_memcopy_count作用是什么?
bufferlist提供了一个rebuild函数,用来将整个buffterptr链表的所有bufferraw都copy到一个新建的bufferptr中,然后清空链表并将新建的这个bufferptr插入到链表中。_memcopy_count成员记录了在进行拷贝过程中每个bufferraw的长度之和。这个值用来在进行内存对齐时需要重新计算,然后比较两者的值,如果不相同就判断内存对齐成功,否则失败。
2.bufferlist是不是类似io buffer?
bufferlist是ceph中进行所有内存操作的管理类:
- bufferraw(buffer::raw):对应一段真实内存,派生了十多种不同分配内存的子类,如raw_malloc,raw_static,raw_mmap_pages,raw_posix_aligned,raw_char,raw_pipe等
- bufferptr(buffer::ptr):对应ceph实际使用的一段内存,可能多个bufferptr对应于同一个底层bufferraw,其成员off和len标识具体使用的一段内存
- bufferlist(buffer::list):多个正在使用的bufferptr构成的一个链表,对应成员std::list<bufferptr> _buffers,其成员off表示整个链表构成的内存相对于起始位置的偏移,p_off表示当前使用的bufferptr的偏移
对于bufferlist来说,通过内部实现的bufferlist::iterator来访问多个bufferptr,能够逐个字节的访问整个内存的内容,不需要关心到底有多少个bufferptr存在,也不用关心bufferptr和底层bufferraw到底是怎么关联的,这种设计就是为了上层使用上的方便,与io buffer的缓存作用并没有太大关系。
上层用户可以直接使用write_file,write_fd等方法,将bufferlist的内容写入文件,可以完全忽略内存的来源、释放等问题,这些问题统一由bufferraw的派生子类和引用计数进行解决。ceph中有两个使用bufferlist最广泛的场景:
- 快速encode/decode:messege层收到osd传递的消息(为一个bufferlist),需要加上消息头和消息尾等操作,这些消息头和尾本身都encode为bufferlist,就很容易与消息本身合并(prepend和append操作),而且这些encode、preprend、append操作都是指针操作,不涉及内存拷贝,提示效率。
- 减少内存分配次数和碎片:利用bufferptr这个中间层进行内存的多次使用,多个bufferptr可以引用同一段bufferraw的不同区域,这个bufferraw可以预先一次性申请较大一段连续内存,从而避免了多次申请内存以及内存碎片的产生。
3.io 优先级?best effort和 real time区别?
I/O优先级是linux系统为read和同步write操作提供的一种系统调用,对于异步write不支持,同时glibc没有提供封装,需要使用<sys/linux.h>头文件,使用ioprio_set函数进行设置。共有三个参数
- which:表明第二个参数的解释方式,IOPRIO_WHO_PROCESS代表who参数为一个进行或线程ID;IOPRIO_WHO_PGRP表明who为同一进程组的所有进程;IOPRIO_WHO_USER为同一用户的所有进程
- who:优先级的指定方式,分为IOPRIO_PRIO_VALUE/CLASS/DATA三种方式指定优先级
- ioprio:为优先级的掩码值,用来生成最终的优先级,优先级数值越低优先级越高
I/O优先级是通过I/O调度器实现,对于每个设备有一个特殊文件可以查看:/sys/block/<device>/queue/scheduler
目前绝大部分实现都是CFQ I/O调度器(Completely Fair Queuing I/O Scheduler),支持三种类型的I/O调度类别:
- IOPRIO_CLASS_RT:real time,被CFQ给予最高优先级进行调度,每次都会给予最优先的机会去放问磁盘,这种调度策略可能会将整个磁盘的IO打满,对应的优先级值可以从最高的0到最低的7进行设置
- IOPRIO_CLASS_BE:best effort,每个进程默认的优先级,优先级值从最高的0到最低的7进行设置
- IOPRIO_CLASS_IDLE:idle调度类别最低,只有没有其他进程使用磁盘时才会调度这类优先级类别的I/O操作
4.pre_pad作用是什么?
FileJournal的每一个entry没有offset字段,利用pre_pad找到data部分的起始位置,然后利用len确定数据部分的长度,接着的post_pad用来找到footer部分,具体结构如下图:
代码中的实现部分如下,可以看出footer和header部分都是写入了一个entry_header:
int FileJournal::prepare_entry(vector<ObjectStore::Transaction>& tls, bufferlist* tbl) {
...
entry_header_t h;
unsigned head_size = sizeof(entry_header_t);
off64_t base_size = 2*head_size + bl.length();
memset(&h, 0, sizeof(h));
if (data_align >= 0)
h.pre_pad = ((unsigned int)data_align - (unsigned int)head_size) & ~CEPH_PAGE_MASK;
off64_t size = ROUND_UP_TO(base_size + h.pre_pad, header.alignment);
unsigned post_pad = size - base_size - h.pre_pad;
h.len = bl.length();
h.post_pad = post_pad;
h.crc32c = bl.crc32c(0);
...
bufferlist ebl;
// header
ebl.append((const char*)&h, sizeof(h));
if (h.pre_pad) {
ebl.push_back(buffer::create_static(h.pre_pad, zero_buf));
}
// payload
ebl.claim_append(bl, buffer::list::CLAIM_ALLOW_NONSHAREABLE); // potential zero-copy
if (h.post_pad) {
ebl.push_back(buffer::create_static(h.post_pad, zero_buf));
}
// footer
ebl.append((const char*)&h, sizeof(h));
...
}
5.magic number作用是什么?
从第4个问题的图示中可以看出magic number是进行数据校验的,magic1是记录的当前entry写入的相对于整个journal文件开头的绝对位置,也就是最终调用文件系统的lseek操作的位置;magic2就是fsid、seq、len三者的异或值,用于进一步校验。
6.aio是否落盘还是cache就返回?
FileJournal打开fd进行写入的时候设置的flag为O_RDWR,如果使用了directio(通过配置项设置journal dio = true),则会为flag增加O_DIRECT | O_DSYNC,因此配置dio为true时就会直接写入磁盘。
7.读数据多个线程?
读取数据的操作都会解析为lfn_open打开文件,调用safe_pread进行读取,最后lfn_close关闭文件,而safe_pread是封装了pread的一个公共函数:
ssize_t safe_pread(int fd, void *buf, size_t count, off_t offset)
{
size_t cnt = 0;
char *b = (char*)buf;
while (cnt < count) {
ssize_t r = pread(fd, b + cnt, count - cnt, offset + cnt);
if (r <= 0) {
if (r == 0) {
// EOF
return cnt;
}
if (errno == EINTR)
continue;
return -errno;
}
cnt += r;
}
return cnt;
}
因此使用方并发调用读取操作是支持的。
8.配journal限制的目的是什么?
Journal Throttle一方面为了控制写入速度过快导致所有journal可写空间都占满,造成大量修改操作并没有commit到底层存储中,另一方面是可以控制底层存储的队列中的长度,可以为实时性要求高的业务场景提供可配。
9.split和merge后怎么维持hash关系?
每个object都有一个对其hash值进行nibble reverse之后的字段:nibblewise_key_cache,每次进行split的时候会基于这个对象重新创建一个新的匹配的路径,见下面的get_path_component函数,这个函数最终会获取这个对象的nibblewise_key_cache字段的值,然后每次都会按照半字节翻转一次,得到的新路径会重新创建或者直接移动到相应目录(已存在的话),然后删除现有object,最终设置新目录的xattr,里面包含了这个目录下有多少个object和子目录等信息。当进行merge的时候与这个过程类似。
int HashIndex::complete_split(const vector<string> &path, subdir_info_s info) {
int level = info.hash_level;
map<string, ghobject_t> objects;
vector<string> dst = path;
int r;
dst.push_back("");
r = list_objects(path, 0, 0, &objects);
...
map<string, map<string, ghobject_t> > mapped;
...
for (map<string, ghobject_t>::iterator i = objects.begin();
i != objects.end();
++i) {
vector<string> new_path;
get_path_components(i->second, &new_path);
mapped[new_path[level]][i->first] = i->second;
}
...
r = remove_objects(path, moved, &objects);
...
set_info(path, info);
...
}
void HashIndex::get_path_components(const ghobject_t &oid, vector<string> *path) {
char buf[MAX_HASH_LEVEL + 1];
snprintf(buf, sizeof(buf), "%.*X", MAX_HASH_LEVEL, (uint32_t)oid.hobj.get_nibblewise_key());
// Path components are the hex characters of oid.hobj.hash, least
// significant first
for (int i = 0; i < MAX_HASH_LEVEL; ++i) {
path->push_back(string(&buf[i], 1));
}
}
10.多级目录的目的是什么?
多级目录是为了防止同一个目录下保存的文件数目过多导致查询时效率过低,通过多级目录的切分,能够增加读取目录项和文件的效率。
相关推荐
- 4万多吨豪华游轮遇险 竟是因为这个原因……
-
(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...
- “菜鸟黑客”必用兵器之“渗透测试篇二”
-
"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...
- 科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白
-
作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...
- 麦子陪你做作业(二):KEGG通路数据库的正确打开姿势
-
作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...
- 知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势
-
智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...
- 每日新闻播报(September 14)_每日新闻播报英文
-
AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...
- 香港新巴城巴开放实时到站数据 供科技界研发使用
-
中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...
- 5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper
-
本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...
- Qt动画效果展示_qt显示图片
-
今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...
- 如何从0到1设计实现一门自己的脚本语言
-
作者:dong...
- 三年级语文上册 仿写句子 需要的直接下载打印吧
-
描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...
- C++|那些一看就很简洁、优雅、经典的小代码段
-
目录0等概率随机洗牌:1大小写转换2字符串复制...
- 二年级上册语文必考句子仿写,家长打印,孩子照着练
-
二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)