Linux ext4 rm 数据恢复原理(二)-大文件Extent结构解析及数据恢复实例-rm误删恢复
目录
本文仅理论探讨,真实数据恢复,敬请先参考:
《Linux ext4 rm 误删,用extundelete恢复失败/报错,无数血泪教训!!!附:ext4误删后的正确处理步骤》
https://blog.****.net/weixin_42745590/article/details/86418144
多级索引的缺陷
在《Linux ext4文件系统原理-文件系统结构及文件解析》中,我们解析了ext4基础文件系统结构,并用实例解析恢复了一个基于多级索引的小文件。
但是多级索引机制对于超大文件的存储是有缺陷的,因为映射表对每一个数据块进行记录,而一个超大文件将占有很多的数据块,因此造成映射表巨大,文件系统效率低下。
Extent机制
Ext4引入 “Extents”概念。一个Extents是连续地址数据块的集合,而超大型文件会被分解在多个extents里。
在inode中,当Extents标志为1,表示这个inode采用Extent标记数据块。Extend区域内有3种结构体,分别为ext4_extent_header、
ext4_extent_idx、ext4_extent,其磁盘布局如下图所 示:
|
|
|
|
|
|
|
entry |
entry |
entry |
entry |
ext4_extent_tail |
ext4_extent_header
结构体ext4_extent_header的大小为12bytes,定义了此extent的条目数量、深度,定义如下:
Offset |
Size |
Name |
Description |
0x0 |
__le16 |
eh_magic |
Magic number, 0xF30A. |
0x2 |
__le16 |
eh_entries |
Number of valid entries following the header. |
0x4 |
__le16 |
eh_max |
Maximum number of entries that could follow the header. |
0x6 |
__le16 |
eh_depth |
Depth of this extent node in the extent tree. 0 = this extent node points to data blocks; otherwise, this extent node points to other extent nodes. The extent tree can be at most 5 levels deep: a logical block number can be at most 2^32, and the smallest n that satisfies 4*(((blocksize - 12)/12)^n) >= 2^32 is 5. |
0x8 |
__le32 |
eh_generation |
Generation of the tree. (Used by Lustre, but not standard ext4). |
ext4_extent_idx
结构体ext4_extent_idx的大小为12bytes,属于索引extent,用于寻找到下一级extent节点,定义如下:
Offset |
Size |
Name |
Description |
0x0 |
__le32 |
ei_block |
This index node covers file blocks from 'block' onward. |
0x4 |
__le32 |
ei_leaf_lo |
Lower 32-bits of the block number of the extent node that is the next level lower in the tree. The tree node pointed to can be either another internal node or a leaf node, described below. |
0x8 |
__le16 |
ei_leaf_hi |
Upper 16-bits of the previous field. |
0xA |
__u16 |
ei_unused |
ext4_extent
结构体ext4_extent的大小为12bytes,它直接指向datablock,定义如下:
Offset |
Size |
Name |
Description |
0x0 |
__le32 |
ee_block |
First file block number that this extent covers. |
0x4 |
__le16 |
ee_len |
Number of blocks covered by extent. If the value of this field is <= 32768, the extent is initialized. If the value of the field is > 32768, the extent is uninitialized and the actual extent length is ee_len - 32768. Therefore, the maximum length of a initialized extent is 32768 blocks, and the maximum length of an uninitialized extent is 32767. |
0x6 |
__le16 |
ee_start_hi |
Upper 16-bits of the block number to which this extent points. |
0x8 |
__le32 |
ee_start_lo |
Lower 32-bits of the block number to which this extent points. |
磁盘解析与数据恢复
我们在一个ext4文件系统中,直接恢复一个以extent记录数据块的文件。
已知用户一个名为PG_11_201809051的目录下某些文件需要恢复,但用专业数据恢复软件无法扫描到有效的目录结构,因此我们需要人工恢复。
首先用winhex全盘搜索PG_11_20180905,发现此目录在50404904 扇区:
目录回退8字节为其inode,定位到此目录的inode,并套用ext4 inode模板:
定位到ee_start_lo= 6300614 block:
定位到6300614选块,找到下级关键目录16385,重复上述步骤
目录16385有两个extent,起始于6300615 block长度3,起始于6300619 block长度2:
分别定位到6300615 block和6300619 block,查看目录下的文件列表:
文件3258是需要恢复的目标文件,找到其inode为1590197:
定位到此inode后,套用ext4 inode模板,定位到文件datablock起始于6584714 block,长度为9:
定位到6584714选块,查看文件数据块内容:
选择6584714-6584722 block区域,右键“复制选块”,选择“到新文件”:
按原文件名保存为3258:
至此,数据恢复完成。
特别注意
ext4文件系统引入extent后,让大文件连续分配空间。因此在 rm 误删除后,像tar类大压缩包文件,在人工介入分析后,可大概率完整恢复。对复杂的破坏场景,需要结合文件特征,灵活正向/反向推荐,以提高恢复效率和成功率,本文不再展开。
对于超大文件,或大目录,人工恢复耗时长,容易出错,需要编写对应的数据抽取程序,自动恢复数据。
本案例中,难点是ext4 inode解析,和目录追溯。
技术支持
温馨提示:如重要数据丢失,还请在行动前咨询专业工程师建议,以免数据遭到二次破坏。