我如何被动检查 ZFS 发送流的内容?

我如何被动检查 ZFS 发送流的内容?

我有一些存储的 ZFS“发送流”(即,它们是通过将输出重定向zfs send到文件而创建的)。我想检查这些流的内容,而无需接收它们并将其写入文件系统 — 例如,我想查看流内的文件名列表。有什么办法吗?

我读了一些资料并搜索了一番,但没找到任何与我所说的类似的内容。我同时使用了FreeBSDLinux 上的 ZFSZFS 的实现。

答案1

您可以通过将它们导入管道来获取一些信息zstreamdump -d,但这不会直接提供有关文件名的任何信息,因为流中没有文件。流是块中描述的两棵树之间的巨大差异。但是代码是公开的,因此如果您设法添加 ZFS 结构检测和解析,您可以从中获得更多。

ZFS内部结构内部是一棵树,所有操作都在该树上完成。文件、目录、文件名、属性和其他所有内容都只是该树中的数据。快照、卷和 FS 是树根,当您拍摄另一个快照时,您只是将当前根存储在某个地方。实时系统会为每个事务生成新的根,这些新根不断远离旧根,同时保持上一棵树的大量数据“叶子”完好无损。流表示应在树 A 上执行的操作列表,以成为 B。

我只是想说,您可能无法在流中看到您要查找的数据,因为它们不需要在那里。当文件被删除时,相应的块就会被释放,因此您无法分辨文件名或内容是什么。当文件被更改时,它会被对象 ID 引用,因此即使文件从头开始重写但目录条目尚未更新,您也不会从流中获得任何内容。

如果流不是差异流,或者您有一些数据超过其先前的状态,那么您会很幸运。但那只是因为完整流将空根转换为目标树,从而包含所有必需的数据。因此,您可以将块解析代码添加到zstreamdump检测和处理 ZFS 内部数据。

答案2

简短回答:

我不相信有任何方法可以有效地对发送流的内容进行分类,这种方法比将其通过管道传输到 zfs 接收以将其重新创建为数据集更轻。

更长的答案:

发送流是数据的存储块级别集合,不是文件系统级别的数据集合。发送流不知道也不关心单个文件;它旨在复制本质上是原始块设备的内容。虽然一个用户可能专门用zfs send它来复制直接存储文件的 ZFS 数据集,但另一个用户可能用它来复制使用 ext4、ntfs 甚至 LUKS 等加密系统格式化的 ZVOL - 在这些情况下,ZFS 完全不知道卷的内容是什么,它只是为它们存储原始块。

zfs send无论您复制的是数据集还是原始 zvol,其工作方式都完全相同,因为它根本不关心原始块存储级别以下的任何内容。它不知道文件名、文件大小、路径或其他任何内容 - 它知道哪些块属于 zvol 或快照的给定快照,但它确实不是知道这些块彼此之间如何关联。

因此,没有轻量级的方法来对流的文件内容进行分类zfs send,因为没有文件的内部目录。即使您确切地知道这个特定的流恰好是未加密的 ZFS 数据集的完整(而非增量)复制,您也必须逐行解析它的每个块,以尝试找出其中哪些块包含文件名。

本质上,为了从发送流中提取文件名,您zfs receive首先需要完成将该流应用于数据集的所有相同的工作。

相关内容