#10318·borg

check --repair: 共享一个对象头解析器,停止对未变更的包重新验证

作者: mr-raj12创建于 2026年9月3日更新于 2026年9月16日
  1. 对象头解析存在五个副本检查"此缓冲是否以有效的对象头开始"(OBJ_MAGIC, SUPPORTED_OBJ_VERSIONS中的一个版本,大小是否合适)被写出五次: - RepoObj.extract_crypted_data, repoobj.py:94 - RepoObj.parse_meta, repoobj.py:168 - RepoObj.parse, repoobj.py:197 - PackReader._parse_header, repository.py:381 - superseded_gap_ranges中的间隙遍历, repository.py:556, 它内联解压对象头 gap walk 不仅是一个副本,它更弱: 它检查魔法值和对象是否位于间隙内,除此之外没有其他检查。没有版本检查,也没有 MAX_DATA_SIZE 检查。因此,它接受了 _parse_header 拒绝的对象头。 语言已经偏离了: repoobj.py 中错误的魔法值是"无效对象魔法",而 _parse_header 中是"没有对象头"。第六个副本距离新的调用者仅有一步。建议: 一个 RepoObj.parse_header(buf) 类方法,它返回 ObjHeader 或它发现的问题的名称。 RepoObj 方法从该名称中抛出 IntegrityError, _parse_header 仅添加了特定于包的内容(对象是否适合此包,是否在 MAX_DATA_SIZE 内),而间隙遍历则调用它而不是手动解压。 仅仅重构。可见的唯一变化是错误字符串不再相互矛盾。 2. finish() 以第二次方式验证每个包 在 --repair 使用 chunks_modified 设置的情况下, ArchiveChecker.finish() (archive.py:2747) 使用同一个验证器 check() 重新构建块索引。每个对象都需要读取最多 1 KiB 的元数据槽加上一次解密,其中第二次遍历之前只读取 49 字节的头部和其他任何内容。它遍历了每个包,尽管唯一的包内容发生变化的是那些在修复过程中删除缺陷块时重写的包。 建议: 记住哪些包在第一次遍历中验证为清洁,或者哪些包在修复过程中重写(重定向的索引项将它们命名),并仅对那些包进行 validate 遍历。对于未受影响的包,使用 self.chunks 中已存在的条目而不是再次从存储中读取它们。 这个建议值得在具有许多包的存储库上进行测量,在之前和之后,以便改进是一个数字而不是一个猜测。

内容来源: borgbackup/borg