透视BlueStore存储结构:如何根据文件名从裸盘提取文件内容
在FileStore下,用户文件经过切分对象块后最终存放在了单机文件系统(xfs 、ext4等)中,我们可以较容易地找到这些对象块对应的文件,然后提取这些对象块文件后组装成用户文件。然而,BlueStore是构建在裸盘上的,没有文件之说,我们提取用户文件时就需要知道用户文件的坐落在裸盘的哪些空间(位置+大小:offset + length)上。下面笔者就介绍下笔者是怎么提取BlueStore中的文件的~
一、需要了解的一些概念
如果笔者理解有误,请留言指正~
概念 | 解释 |
---|---|
onode | 每个对象有个onode |
lextent | 逻辑extent |
extent_map | 存放 lextent 的map |
extent_map shard | extent map较大时切分shard |
blob | lextent占据blob的一段或这全部 ,blob内可以有多个lextent |
pextent | 物理extent,blob由一个或多个 pextent 组成 pextent 含字段 offset+length,代表裸盘的一段空间 |
几个概念的关系如图:
此图源于网络(http://www.sysnote.org/2016/08/19/ceph-bluestore/),如有冒犯,请联系笔者删除~
二、使用 ceph-kvstore-tool 工具获得用户文件位置
集群中有名为ceph-osd.0.log的文件:
[root@s131 /data]# ls -i /cephfs
1099511627776 ceph-osd.0.log 1099511627777 test
获取该文件的十六进制inode号:
[root@s131 /data]# printf %llx 1099511627776
10000000000
使用 ceph osd map fs_d 10000000000.00000000 命令可以取得该对象所在的osd ${OSDID},通过 ceph-kvstore-tool 工具查看其 onode 和 onode的extent_map的shard:
[root@s131 /data]# ceph-kvstore-tool bluestore-kv /data/lib/ceph/osd/ceph-${OSDID} list O 2>/dev/null |grep 10000000000.00000000
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo%00%00%00%00x
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo%00%08%00%00x
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo%00%10%00%00x
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo%00%18%00%00x
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo%00%20%00%00x
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo%00%28%00%00x
O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo%00%2a%10%00x
第一个kv对象是onode,后面每一个kv对象是onode的extent_map的一个shard
使用 ceph-kvstore-tool 的get命令可以将kv对象保存成文件:
ceph-kvstore-tool bluestore-kv /data/lib/ceph/osd/ceph-0 get O %7f%80%00%00%00%00%00%00%02%0c%f6%ad%0f%2110000000000.00000000%21%3d%ff%ff%ff%ff%ff%ff%ff%fe%ff%ff%ff%ff%ff%ff%ff%ffo out onode_out_file
要获取用户的存储位置,就需要获得onode最终存储在哪些pextent上,而这个信息是存储在onode的extent_map中的,我们需要将这些信息加载到内存,然后dump出来
笔者对 ceph-kvstore-tool 进行修改,在get onode时,将onode及其extent_map都加载到内存中,然后dump出来:
_dump_onode 0x7f67c86bf440 #2:0cf6ad0f:::10000000000.00000000:head# nid 151669 size 0x2a1a47 (2759239) expected_object_size 0 expected_write_size 0 in 7 shards, 1 spanning blobs
_dump_onode attr _ len 275
_dump_onode attr snapset len 35
_dump_extent_map shard 0x0(0x211 bytes) (loaded)
_dump_extent_map shard 0x80000(0x213 bytes) (loaded)
_dump_extent_map shard 0x100000(0x213 bytes) (loaded)
_dump_extent_map shard 0x180000(0x213 bytes) (loaded)
_dump_extent_map shard 0x200000(0x213 bytes) (loaded)
_dump_extent_map shard 0x280000(0x97 bytes) (loaded)
_dump_extent_map shard 0x2a1000(0x9 bytes) (loaded)
_dump_extent_map 0x0~80000: 0x0~80000 Blob(0x7f67c87004c0 blob([0x86d626d000~80000] csum crc32c/0x1000) use_tracker(0x80*0x1000 0x[1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000]) SharedBlob(0x7f67c8700140 sbid 0x0))
_dump_extent_map csum: [a9c1d499,82e5a14b,13d41153,5d2c92ac,bd486ca7,69b734b3,bbd4506b,5c78934,23a7ec86,71cd4025,da049035,3b335b95,3aaad68e,c108d427,64464011,4e852c8b,f105f7cf,97c530a5,990131c3,53abee5f,eb2a752e,f46c6204,a02cd25e,a0edcf8f,806f4051,6edf9661,3a6a9b6e,46839e5d,47a8fe0,e1fbbc93,2881e5c,ff0c1c78,120aeef4,b871a43b,311a829a,a086216e,690f7afc,2c4fcfc8,5ca3103d,1b26aedc,75e29d22,c6ef70c2,b554bde1,ad70d878,55acfc75,1adb3a0a,8ac031ab,5392bb48,6548b760,7b8223e,9bf5dd1b,8935c0b,d5ba7870,4bb04662,b37a21fc,ab36345c,2277149a,fbb73550,2dc74707,bfafd22b,28981f79,950972b1,d6bbde66,74b66358,81c50f84,716677d5,2b6ef5d2,996752fd,b99bf360,24715cce,d62dfb8,b11bd85c,3136a56a,882e8c4,ecf2eb0c,16926e73,d339b6de,d17d8613,337ca950,cad27fa6,f2efd4e7,bb0b23ce,6c8b014b,209144b7,86da06c3,8e6fa11e,463ec5a,c1b83c22,187d0b9c,15931b79,5dda6148,a89ab9ae,563f9db5,33902e1,cde965c4,859ac4e3,3a2d5134,9a824e29,6e9626a8,f9c58152,647d262a,955ca05d,baaa6a85,58e3133b,a19af4f0,57cdb970,fa0c6a09,551ac600,8400f2b5,2885abc7,9ce677f1,4d3d5310,b8f464a,2693ec2b,bfedcacc,6a302160,2e312a4f,362e6430,9c0d1984,cba58e72,9fe69d47,5ae2db10,f5ebd276,9dbbbc83,a4df126a,f4b63496,4e0034cb,1df47ea7]
提取出关键的pextent的信息:
[root@s131 /data]# cat onode_dump |grep "blob(" |awk '{print $5" "$6" "$7}'
blob([0x86d626d000~80000] csum crc32c/0x1000)
blob([0x86d62ed000~80000] csum crc32c/0x1000)
blob([0x86d636d000~80000] csum crc32c/0x1000)
blob([0x86d63ed000~80000] csum crc32c/0x1000)
blob([0x86d646d000~80000] csum crc32c/0x1000)
blob([0x86d64ed000~21000] csum crc32c/0x1000)
spanning 0 blob([!~21000,0x86d650e000~1000]
[0x86d626d000~80000]表示的是blob中的pextent的数组,0x86d626d000是pextent在裸盘上的offset,80000为其长度
由于笔者的环境比较干净,这些blob的pextent在裸盘上是连续的,用户文件的长度是已知的,为2759239,我们可以通过如下方式提取出用户文件
[root@s131 /data]# printf %lld 0x86d626d000
579118485504
[root@s131 /data]# dd if=/dev/sdb2 of=test_onode_dump bs=1 count=2759239 skip=579118485504
[root@s131 /data]# md5sum /cephfs/ceph-osd.0.log
e07a2ab39136190a9550a3b07ca9efd9 /cephfs/ceph-osd.0.log
[root@s131 /data]# md5sum test_onode_dump
e07a2ab39136190a9550a3b07ca9efd9 test_onode_dump
提取出的文件的md5跟直接通过/cephfs访问得到的mds5一致,提前用户文件数据完毕: )