最近应组长的要求需要对ceph源码中关于cephfs模块的一组文件系统属性进行修改,在原来源码中写好的属性基础上再次添加一个属性,并且可以在命令行上进行getfattr 和setfattr操作。整个过程也称得上是身心俱疲,不过还好有每天晚上我家小可爱的亲切安慰才让躁动的内心平缓下来。
default的ceph.dir.layout如下:
-
输入命令:
getfattr -n ceph.dir.layout /nas/cephfs
可以得到如下输出命令的解释为
getfattr -n $cluster_name.dir.layout /nas/$cephfs_name
getfattr: Removing leading '/' from absolute path names # file: nas/cephfs/ ceph.dir.layout="stripe_unit=4194304 stripe_count=1 object_size=16777216 pool=data"
这些属性从左到右分别代表:stripe_unit(cephfs分片之后每个单元的大小MB),stripe_count(分片的数量),object_size(底层存储时每个对象的大小),pool(数据资源池的名称)
-
输入命令:
getfattr -n ceph.dir.layout.stripe_count /nas/cephfs
可以得到如下输出:getfattr: Removing leading '/' from absolute path names # file: nas/cephfs/ ceph.dir.layout.stripe_count="1"
-
输入命令:
setfattr -n ceph.dir.layout.stripe_count -v 12 /nas/cephfs
成功后没有输出,再次使用命令
getfattr -n ceph.dir.layout.stripe_count /nas/cephfs
可以得到如下输出:getfattr: Removing leading '/' from absolute path names # file: nas/cephfs/ ceph.dir.layout.stripe_count="12"
添加我自己的属性完成如上操作:protect和follow_protect
分析:关于cephfs的client可以getfattr到该属性,并且在设备重新启动之后该属性仍然需要被get到,那么除了正常的client端代码需要对属性设置这一块做定义初始化,然后获取值显示之外还需要将该属性的数据进行固化存储到存储设备上,即osd的数据库。这个时候便需要mds server在创建文件系统之前将该属性存储下来,保证在client 端发出获取属性的requese之后能够从数据库中读出来。这个过程是ceph源码为了保证属性不被随意更改,所以在属性数据传输过程中会有加解密的过程。(图形表达更直观一点)
首先显示一下结果:
[root@node ceph]# getfattr -n ceph.dir.layout /nas/cephfs/
getfattr: Removing leading '/' from absolute path names
# file: nas/cephfs/
ceph.dir.layout="stripe_unit=4194304 stripe_count=12 object_size=4194304 protect=67 follow_protect=32 pool=cephfs_pool"
[root@node ceph]# getfattr -n ceph.dir.layout.protect /nas/cephfs/
getfattr: Removing leading '/' from absolute path names
# file: nas/cephfs/
ceph.dir.layout.protect="67"
[root@node ceph]# setfattr -n ceph.dir.layout.protect -v 20 /nas/cephfs/
[root@node ceph]# getfattr -n ceph.dir.layout.protect /nas/cephfs/
getfattr: Removing leading '/' from absolute path names
# file: nas/cephfs/
ceph.dir.layout.protect="20"
[root@node ceph]#
更改代码ceph源码如下:
-
Getfattr:
- 定义:/ceph-12.2.1/src/common/fs_types.h(89):
uint32_t protect;
- 初始化:/ceph-12.2.1/src/common/fs_types.h(97):
protect(100)
- 设置默认值: /ceph-12.2.1/src/common/fs_types.h(103):
static file_layout_t get_default() {return file_layout_t(1<<22, 1, 1<<22,1<<4,1<<5); }
- 界面获取全部属性:
a) /ceph-12.2.1/src/common/client.cc(11246):protect=%lld
b) /ceph-12.2.1/src/common/client.cc(11250):(unsigned long long)in->layout.protect;
c) /ceph-12.2.1/src/common/client.cc(11374):XATTR_LAYOUT_FIELD(dir, layout, protect),
- 定义:/ceph-12.2.1/src/common/fs_types.h(89):
-
Setfattr
- 定义:
a) /ceph-12.2.1/src/include/cephfs.h(536):__le32 protect;
b) /ceph-12.2.1/src/include/cephfs.h(458):__le32 protect;
c) /ceph-12.2.1/src/include/cephfs.h(44):__le32 fl_protect;
- 创建固化文件结构体并写入:
a) /ceph-12.2.1/src/common/client.cc(8106): int Client::open()添加protect参数
b) /ceph-12.2.1/src/common/client.cc(8161): _create() 补充创建参数protect
c) /ceph-12.2.1/src/common/client.cc(11563):_create()添加创建函数的protect参数
d) /ceph-12.2.1/src/common/client.cc(11648):将protect赋值给传入server请求的结构体变量req->head.args.open.protect = protect;
细节的函数调用处理:
调用open,_create的参数赋值
client.cc(12512):
_create(parent, name, flags, mode, in, fhp, 0, 0, 0,0,0, NULL, &created,perms);
client.cc(8193):
open(relpath, flags, perms, mode, 0, 0, 0,0,0, NULL);
- mds接受属性之前的编码:
a) 字段赋值处理
/ceph-12.2.1/src/common/fs_types.cc(15):f->dump_unsigned("protect",l.fl_protect);
/ceph-12.2.1/src/common/fs_types.cc(141):f->dump_unsigned("protect",protect);
b) 传给固化结构体/ceph-12.2.1/src/common/fs_types.cc(69):fl->fl_protect = protect;
c) 编码存储(可以理解为加密存储) /ceph-12.2.1/src/common/fs_types.cc(110):::encode(protect, bl);
- MDS接受并处理:
a) 对client传入过来layout的参数进行解析,取出固化的值赋值给结构体中的属性 /ceph-12.2.1/src/mds/server.cc(4407):else if (name == "layout.protect") layout->protect = boost::lexical_cast<unsigned>(value);
b) 处理client的set layout /ceph-12.2.1/src/mds/server.cc(4228、4328):if (req->head.args.setlayout.layout.fl_protect > 0) layout.protect=req->head.args.setlayout.layout.fl_protect;
- client接受属性值并解码
a) /ceph-12.2.1/src/common/fs_types.cc(54):protect = fl.fl_protect;
b) /ceph-12.2.1/src/common/fs_types.cc(129):::decode(protect, p);
- 定义:
总结:
对于一些大型开源项目的源码的某一个模块的修改要建立在自己已经对该模块的功能有较为属性的了解(了解的程度是自己要能够看着源码将功能的实现流程从调用到功能操作结束顺一遍),过程最好用流程图表达出来,对于重要的函数也可以画一下函数流程图,数据调用流程图,这样在修改的时候才不会一头雾水,无从下手。
网友评论