数据恢复(九)-从XFS_undelete源码分析XFS文件系统恢复原理
工具源码链接
https://github.com/ianka/xfs_undelete
XFS文件系统删除原理
当文件在XFS文件系统中被删除时,虽然iNode被标记为空闲(使用特定的”IN\0\0″签名),但数据块和inode结构本身并不会立即被覆盖,核心在于iNode中存储的extent并没有被删除,即指向文件实际数据块block的指针。
这一点和EXT文件系统有着本质区别,EXT文件系统在删除文件时,是把iNode中对应的extent信息给填0,一旦被删除就找不到iNode和block的映射关系。
XFS_undelete恢复原理
XFS_undelete的核心原理基于XFS文件系统的以下特性:
- 当文件被删除时,inode标记为删除状态(使用特定的”IN\0\0″签名)但实际内容仍保留在磁盘上
- inode中存储了extent信息,即指向文件实际数据块的指针
- 通过读取这些extent信息并复制对应的数据块,可以重建被删除的文件
所以XFS_undelete通过搜索所有被标记为删除的iNode即可找到被删除的文件。
XFS_undelete数据恢复流程
文件系统准备
程序首先确保文件系统以只读方式挂载,这样可以防止新数据写入覆盖被删除的文件。如果检测到文件系统以读写方式挂载,它会尝试重新挂载为只读模式。这一步非常关键,因为继续写入可能会覆盖待恢复的数据。
读取超级块
程序读取XFS超级块,获取文件系统参数,包括:
- 块大小(blocksize)
- 数据块总数(dblocks)
- 分配组块数(agblocks)
- 分配组数量(agcount)
- 版本号(versionnum)
- 扇区大小(sectsize)
- inode大小(inodesize)
- 每块inode数(inopblock)
这些参数对于理解文件系统结构和正确解析inode信息至关重要。
遍历inode B+树
程序遍历每个分配组(AG)的inode B+树结构,识别所有inode。这个过程通过递归遍历树节点实现,区分节点(node)和叶子(leaf):
- 对于节点:继续递归遍历子节点
- 对于叶子:检查包含的inode记录
识别已删除inode
程序在遍历inode时,寻找特定签名。具体而言:
- 检查”IN”魔术字符串确认inode记录存在
- 检查”IN\0\0″签名识别已删除但未覆盖的inode
时间筛选
恢复过程可以基于以下时间条件进行筛选:
- 删除时间(ctime):文件被删除的时间
- 修改时间(mtime):文件最后修改的时间
这允许用户恢复特定时间段内删除的文件。
extent信息提取
对于每个符合条件的已删除inode,程序提取extent信息。每个extent包含:
- 逻辑偏移量(loffset):文件内的位置
- 分配组号(aag):物理位置(分配组)
- 分配块号(ablock):物理位置(块号)
- 块数(count):连续的块数量
这些信息指示了文件数据在磁盘上的位置。
文件恢复
使用dd
命令从源文件系统复制特定数据块到输出文件:
- 首先恢复第一个数据块以确定文件类型
- 使用
file
命令识别文件类型和MIME类型 - 根据文件类型添加适当的扩展名
- 恢复所有extent对应的数据块
XFS_undelete限制与局限性
基于代码分析,该工具存在一些固有限制:
- 无法恢复目录结构或文件名
- 无法保证文件完整性(特别是对于碎片化文件)
- 可能无法恢复具有非标准存储模式的文件
XFS_undelete最大的局限性在于无法恢复大文件。
当文件被删除时,该工具仅依赖保留在inode中的区段信息进行恢复。由于物理空间限制,一个典型的512字节inode最多只能直接存储21个区段信息。超过这个数量的文件会使用B+树结构存储其区段信息,而现有的恢复工具(如xfs_undelete)并没有去解析这种复杂的树结构,因此无法恢复具有超过21个区段的文件。
赞赏微信赞赏
支付宝赞赏
发表评论