FAQ 空洞创建时间 (hole_birth)
简短说明
hole_birth 功能存在(或曾经存在)一些错误,导致的结果是,如果你从一个受影响的数据集执行 zfs send -i`(或 `-R,因为它使用了 -i),接收方不会看到任何校验和或其他错误,但生成的目标快照将与源快照不匹配。
ZoL 版本 0.6.5.8 和 0.7.0-rc1(及以上版本)默认忽略导致此问题的错误元数据 在发送方。
FAQ
我有一个启用了 hole_birth 的池,如何知道我是否受到影响?
从技术上讲,可以计算你是否受到任何影响,但这需要为每个数据集中的每个快照中的每个文件抓取 zdb 输出,这是一个组合噩梦。(如果你真的想要,这里有一个概念验证 这里。
如果我们已经接收到一个受影响的快照,是否有不那么痛苦的方式来修复这个问题?
不幸的是,没有。你所需的数据根本没有出现在发送流中,并且无法在目标位置进行重写。
详细说明
hole_birth 是一个用于加速 zfs send -i 的功能——特别是,ZFS 过去不存储文件中的“空洞”(稀疏区域)创建时间的元数据,因此每次 zfs send -i 都需要包含每个空洞。
hole_birth,顾名思义,添加了对空洞创建时的 txg`(事务组)的跟踪,以便 `zfs send -i 可以只发送在(起始快照的 txg)和(结束快照的 txg)之间创建的空洞,生活变得美好。
不幸的是,hole_birth 在某些情况下可能会“忘记”设置空洞的 birth_time,导致它记录 birth_time 为 0(在 hole_birth 之前使用的值,基本上等同于“自文件创建以来”)。
这意味着,当你执行 zfs send -i 时,由于 zfs send 在发送给定快照时没有任何关于周围快照的知识,它会看到创建 txg 为 0,得出结论“哦,它是 0,我肯定之前已经发送过这个了”,然后不包含它。
这意味着,在接收方,它不知道这些空洞应该存在,因此不会创建它们。这导致源和目标之间的差异。
ZoL 版本 0.6.5.8 和 0.7.0-rc1(及以上版本)默认忽略此元数据,并始终发送 birth_time 为 0 的空洞,可通过调优参数 ignore_hole_birth 或 send_holes_without_birth_time 进行配置。后者是 OpenZFS 标准化的名称。ZoL 版本 0.6.5.8 只有前者,但对于任何具有 send_holes_without_birth_time 的 ZoL 版本,它们指向相同的值,因此更改其中任何一个都会生效。