前言

之前有个想法,是不是有办法找到rbd中的文件与对象的关系,想了很久但是一直觉得文件系统比较复杂,在fs 层的东西对ceph来说是透明的,并且对象大小是4M,而文件很小,可能在fs层进行了合并,应该很难找到对应关系,最近看到小胖有提出这个问题,那么就再次尝试了,现在就是把这个实现方法记录下来

这个提取的作用个人觉得最大的好处就是一个rbd设备,在文件系统层被破坏以后,还能够从rbd提取出文件,我们知道很多情况下设备的文件系统一旦破坏,无法挂载,数据也就无法读取,而如果能从rbd中提取出文件,这就是保证了即使文件系统损坏的情况下,数据至少不丢失

本篇是基于xfs文件系统情况下的提取,其他文件系统有时间再看看,因为目前使用的比较多的就是xfs文件系统

本篇也回答了一个可能会经常被问起的问题,能告诉我虚拟机里面的文件在后台存储在哪里么,看完本篇就知道存储在哪里了

XFS文件系统介绍

[root@lab8106 ~]# mkfs.xfs -f /dev/rbd0p1
warning: device is not properly aligned /dev/rbd0p1
meta-data=/dev/rbd0p1 isize=256 agcount=9, agsize=162816 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=4096 blocks=1310475, imaxpct=25
= sunit=1024 swidth=1024 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=8 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0

XFS文件系统采取是AG管理的,每个AG维护自己的inode和数据,所以XFS文件系统是一种很容易扩展的文件系统,本篇里面主要用到的命令是xfs_bmap这个命令

[root@lab8106 ~]# xfs_bmap -lvp /etc/fstab
/etc/fstab:
EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL FLAGS
0: [0..7]: 26645424..26645431 1 (431024..431031) 8 00000

一个文件最小就是8个block(512b),也就是4k,这个因为上面默认的xfs的格式化就是data bsize=4K,这个值可以自行调整的,本篇尽量用默认常规的参数来讲例子

查看man xfs_bmap这个命令可以看到:

Holes are marked by replacing the startblock..endblock with hole. All the file offsets and disk blocks are in units of 512-byte blocks, no matter what the filesystem's block size is.

意思是这个查询到的里面的计数单位都是512-byte,不管上层设置的block大小是多少,我们知道文件系统底层的sector就是512-byte,所以这个查询到的结果就可以跟当前的文件系统的sector的偏移量联系起来,这里强调一下,这个偏移量的起始位子为当前文件系统所在分区的偏移量,如果是多分区的情况,在计算整个偏移量的时候就要考虑分区的偏移量了,这个会在后面用实例进行讲解的

rbd的对象是不清楚内部分区的偏移量,所以在rbd层进行提取的时候是需要得到的是分区当中的文件相对整个磁盘的一个sector的偏移量

rbd的对象结构

[root@lab8106 ~]# rados -p rbd ls|grep data
rbd_data.25a636b8b4567.00000000000009ff
rbd_data.25a636b8b4567.00000000000001dd
rbd_data.25a636b8b4567.0000000000000000
rbd_data.25a636b8b4567.000000000000009f
rbd_data.25a636b8b4567.0000000000000459
rbd_data.25a636b8b4567.000000000000027e
rbd_data.25a636b8b4567.00000000000004ff
rbd_data.25a636b8b4567.000000000000027c
rbd_data.25a636b8b4567.000000000000027d
rbd_data.25a636b8b4567.0000000000000001
rbd_data.25a636b8b4567.000000000000013e
rbd_data.25a636b8b4567.00000000000003ba
rbd_data.25a636b8b4567.000000000000031b
rbd_data.25a636b8b4567.00000000000004f8

rbd被xfs格式化以后会产生一些对象,这些对象是以16进制名称的方式存储在后台的,也就是rbd大小一定的情况下对象数目是一定的,也就是名称也是一定的

[root@lab8106 ~]# parted -s /dev/rbd0 unit s print
Model: Unknown (unknown)
Disk /dev/rbd0: 20971520s
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: Number Start End Size File system Name Flags
1 1953s 10485759s 10483807s xfs primari
2 10485760s 20963327s 10477568s primari

上面可以看到rbd0的sector个数为20971520s

20971520s*512byte=10737418240byte=10485760KB=10240MB

sector的大小一定,总rbd大小一定的情况下sector的数目也是一定的,本篇实例的rbd大小

[root@lab8106 ~]# rbd info zp
rbd image 'zp':
size 10000 MB in 2500 objects
order 22 (4096 kB objects)
block_name_prefix: rbd_data.25a776b8b4567
format: 2
features: layering
flags:
create_timestamp: Sat Jul 22 18:04:12 2017

sector和ceph object的对应关系的查询

这个就像个map一样,需要把这个关系给找到,一个sector的区间对应到object的map,这里我用python写个简单的方法来做查询,也可以自己用其他语言来实现

首先查询到rbd的对象数目

[root@lab8106 ~]# rbd info zp
rbd image 'zp':
size 10000 MB in 2500 objects
order 22 (4096 kB objects)
block_name_prefix: rbd_data.25a776b8b4567
format: 2
features: layering
flags:
create_timestamp: Sat Jul 22 18:04:12 2017

处理脚本如下:

vim getsecob.py

添加下面内容

#! /bin/python
# *-* conding=UTF-8 *-* import commands def main():
getmap(2500) def getmap(object):
sector=int(object)*4096*1024/512
print "object:"+str(object)
print "sector:"+str(sector)
incre=sector/object
for item in range(int(object)):
a=int(item*8192)
b=int((item+1)*8192-1)
print str([a,b])+" --> "+"%016x" %item if __name__ == '__main__':
main()

其中getmap后面为对象数目

输出是这个形式的:

[root@lab8106 ~]# python getsecob.py
object:2500
sector:20480000
[0, 8191] --> 0000000000000000
[8192, 16383] --> 0000000000000001
[16384, 24575] --> 0000000000000002
[24576, 32767] --> 0000000000000003
[32768, 40959] --> 0000000000000004
[40960, 49151] --> 0000000000000005
···

对rbd0进行分区,分区后的结果如下

[root@lab8106 ~]# parted -s /dev/rbd0 unit s print
Model: Unknown (unknown)
Disk /dev/rbd0: 20480000s
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: Number Start End Size File system Name Flags
1 1953s 10240000s 10238048s primari
2 10248192s 20471807s 10223616s primari

这个是个测试用的image,大小为10G分成两个5G的分区,现在我们在两个分区里面分别写入两个测试文件,然后经过计算后,从后台的对象中把文件读出

mount /dev/rbd0p1 /mnt1
mount /dev/rbd0p2 /mnt2
cp /etc/fstab /mnt1
cp /etc/hostname /mnt2

首先获取文件在分区上的sector的偏移量

[root@lab8106 ~]# xfs_bmap -lvp /mnt1/fstab
/mnt1/fstab:
EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL FLAGS
0: [0..7]: 8224..8231 0 (8224..8231) 8 01111

可以得到是(8224..8231)共8个sector

从上面的分区1的start的sector可以知道起始位置是1953,那么相对于磁盘的偏移量就变成了

(8224+1953..8231+1953) = (10177..10184)

这里说下,这个地方拿到偏移量后,直接通过对rbd设备进行dd读取也可以把这个文件读取出来,这个顺带讲下,本文主要是从对象提取:

dd if=/dev/rbd0 of=a bs=512 count=8 skip=10177

bs取512是因为sector的单位就是512b

这样就把刚刚的fstab文件读取出来了,skip就是文件的sector相对磁盘的起始位置,count就是文件所占的block数目

继续我们的对象提取方式,上面的(10177..10184)这个我们根据上面那个脚本输出的对象列表来找到对象

[8192, 16383] --> 0000000000000001

获取名称,这个因为我的是测试环境,就只有一个匹配,多个image的时候要过滤出对用的rbd的对象,用prifix过滤即可

[root@lab8106 ~]# rados -p rbd ls|grep 0000000000000001
rbd_data.25a776b8b4567.0000000000000001

下载对象

[root@lab8106 ~]# rados -p rbd get rbd_data.25a776b8b4567.0000000000000001 rbd_data.25a776b8b4567.0000000000000001

根据偏移量计算对象中的偏移量

(10177..10184)
[8192, 16383] --> 0000000000000001

得到

10177-8192=1985

dd if=rbd_data.25a776b8b4567.0000000000000001 of=a bs=512 count=8 skip=1985

得到的文件a的内容即为之前文件的内容

准备取第二个分区的文件

[root@lab8106 ~]# xfs_bmap -lvp /mnt2/hostname
/mnt2/hostname:
EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL FLAGS
0: [0..7]: 8224..8231 0 (8224..8231) 8 01111

8224+10248192..8231+10248192=10256416..10256423

从磁盘方式

[root@lab8106 ~]# dd if=/dev/rbd0 of=a bs=512 count=8 skip=10256416

从对象方式

10256416..10256423 对应

[10256384, 10264575] --> 00000000000004e4

对象偏移量

10256416-10256384=32
rados -p rbd get
[root@lab8106 ~]# rados -p rbd get rbd_data.25a776b8b4567.00000000000004e4 rbd_data.25a776b8b4567.00000000000004e4

获取文件

[root@lab8106 ~]# dd if=rbd_data.25a776b8b4567.00000000000004e4 of=a bs=512 count=8 skip=32

如果文件比较大的情况,可能出现就是文件是跨对象的,那么还是跟上面的提取方法一样,然后进行提取后的文件进行合并即可

总结

在存储系统上面存储的文件必然会对应到底层磁盘的sector,而sector也是会一一对应到后台的对象的,这个在本文当中得到了验证,所以整个逻辑就是,在文件系统层找到文件对应的sector位置,然后再在底层把sector和对象关系找好,就能从找到文件在对象当中的具体的位置,也就能定位并且能提取了,本篇是基于xfs的,其他文件系统只要能定位文件的sector,就可以在底层找到文件,这个以后会补充其他文件系统进来

变更记录

Why Who When
创建 武汉-运维-磨渣 2017-07-22

从ceph对象中提取RBD中的指定文件的更多相关文章

  1. SACD ISO镜像中提取DSDIFF(DFF)、DSF文件

                      听语音 | 浏览:5620 | 更新:2015-08-25 11:46 | 标签:硬件 1 2 3 4 5 分步阅读 现在有一种比较流行的无损音乐传输介质是SACD ...

  2. python学习笔记——爬虫中提取网页中的信息

    1 数据类型 网页中的数据类型可分为结构化数据.半结构化数据.非结构化数据三种 1.1 结构化数据 常见的是MySQL,表现为二维形式的数据 1.2 半结构化数据 是结构化数据的一种形式,并不符合关系 ...

  3. fortran中提取字符串中可见字符的索引

    fortran中常常需要提取字符串中可见字符的索引,下面是个小例子: !============================================================= su ...

  4. python中提取字典中的键值

    1 # 字典如下 2 movie = { 3 '妖猫传':['黄','染'], 4 '无问西东':['章','王'], 5 '超时空':['雷','佟'] 6 } 7 name = input('请输 ...

  5. C# 中提取表中的某一项数据

  6. sublime text3中sass编译后保存到指定文件夹

    第一步: tools->builde system->new build system 第二步: 粘贴如下代码到新建文档中: { "cmd": ["sass& ...

  7. 根据Excel文件中的内容,修改指定文件夹下的文件名称

    问题:根据Excel文件中内容,把文件名称由第2列,改为第1列.比如:把文件“123.jpg”修改为“1.jpg”.

  8. android中保存Bitmap图片到指定文件夹中的方法

    /** 保存方法 */  public void saveBitmap() {   Log.e(TAG, "保存图片");   File f = new File("/s ...

  9. Windows PE3.0制作方法(从Win7中提取制作)

    Windows PE3.0制作方法(从Win7中提取制作 在d:新建文件夹winpe,在winpe中新建sources.pe3和new文件夹,把附件中提供的工具imagex连文件夹一起放到winpe目 ...

随机推荐

  1. nginx安全: 配置http基本验证(Basic Auth)(nginx 1.18.0)

    一,http基本验证的作用: 1,http基本身份验证会从浏览器弹出登录窗口, 简单明了,容易理解, 对于面向终端用户的前台来说,不够友好, 但对于内部员工操作的后台还是很有用,通常作为一层安全措施应 ...

  2. Windows Server 2003 Enterprise Edition SP2

    SN: MPQ6X-3MCCF-47H9T-TKC2F-T69WM

  3. fish_redux使用详解---看完就会用!

    说句心里话,这篇文章,来来回回修改了很多次,如果认真看完这篇文章,还不会写fish_redux,请在评论里喷我. 前言 来学学难搞的fish_redux框架吧,这个框架,官方的文档真是一言难尽,比fl ...

  4. python定义函数后跟->的意义

    举例 def xxx(x)  后面跟着一个->数据类型 比如->int:(别忘了冒号) 作用很简单 挺流氓的 直接让函数返回值为这个类型 非常方(liu)便(mang)

  5. 深入理解Java注解类型(@Annotation)

    http://blog.csdn.net/javazejian/article/details/71860633  出自[zejian的博客] java注解是在JDK5时引入的新特性,鉴于目前大部分框 ...

  6. 浅谈SRT和NDI®在广电制作领域的技术优势和应用

    随着技术的不断发展,用户对音视频质量的要求不断提升,对视频内容观看的方式也日趋多元化.摄像设备的分辨率从高清到4K,甚至有些厂家推出了6K或8K的产品:用户不再局限于从有线电视的直播节目中收看内容,智 ...

  7. Luogu P4280 [AHOI2008]逆序对

    题目描述 甩个链接就走 题解 先预处理出每个位置上分别填上 1~k 的数的逆序对的数量的前缀和与后缀和 (不用管原来有值的,统计时不计入答案就行了) (有点绕,看代码应该能懂) 然后枚举每个 -1 的 ...

  8. 关于LoRa安全联盟的六大常见问题

    LoRaWAN的安全机制在哪里指定? 所有安全机制都在LULA联盟规范中指定,可以由公众下载. LoRa联盟规范如何保证LoRaWAN网络的安全操作? LoRaWAN支持来源认证.完整的媒体访问控制( ...

  9. OpenCascade拓扑对象之:TopoDS_Shape对象及其子对象

    @font-face { font-family: "Times New Roman" } @font-face { font-family: "宋体" } @ ...

  10. UVA12558 埃及分数 Egyptian Fractions

    题意描述 题目描述的翻译挺清楚的了. 和原题的区别是多了禁用的分母.(还有毒瘤输入输出) 算法分析 显然这道题没有什么很好的数学方法来解决,所以可以使用搜索. 由于不确定深度,深搜显然无穷无尽. 所以 ...