目錄
本文僅理論探討,真實數據恢復,敬請先參考:
《Linux ext4 rm 誤刪,用extundelete恢復失敗/報錯,無數血淚教訓!!!附:ext4誤刪後的正確處理步驟》
https://blog.csdn.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解析,和目錄追溯。
技術支持
溫馨提示:如重要數據丟失,還請在行動前諮詢專業工程師建議,以免數據遭到二次破壞。