Ceph的FileStore代码阅读问题整理

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最广泛的场景:
  1. 快速encode/decode:messege层收到osd传递的消息(为一个bufferlist),需要加上消息头和消息尾等操作,这些消息头和尾本身都encode为bufferlist,就很容易与消息本身合并(prepend和append操作),而且这些encode、preprend、append操作都是指针操作,不涉及内存拷贝,提示效率。
  2. 减少内存分配次数和碎片:利用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 -
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值