Files
minio/docs/investigations/r7/research.md
T
Feng Ruohang 4fcdf37ce6 fix(replication): preserve normalized replica metadata
Restore only the six replication-specific metadata fields after trust
validation, so streaming uploads retain their actual content encoding and
Snowball entries do not inherit ordinary metadata from the outer archive.

Include helper, authenticated PUT/COPY/multipart and Snowball regressions,
plus the R7 investigation, actual Opus 5 consensus and local verification.
The production change is based on PR #187 by Mikhail Khadarenka.

Co-authored-by: Mikhail Khadarenka <chodorenko@gmail.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
2026-09-16 00:00:17 +08:00

3.8 KiB
Raw Blame History

R7 调查与复现

结论

基线 9ebe81c1b3611f9cc73e676b5b741c2be62c467a 中,可信复制恢复过程把已规范化的普通元数据从原始请求中重新提取。aws-chunked 是传输编码,重新落盘后会被 GET/HEAD 返回。SILO 在 2026-04-15 的 56fa63bfd155154157cd7e1fb6dc295a3b3104ed 中引入此回归;该提交修复的复制头信任边界仍需保留。

实时核对 PR #187OPEN、未合并,head b8f2fdde41dff3dc3b8db669c1d42d30ca5c1d3d;只恢复复制专用字段的方向与根因吻合。没有将 PR 自报测试当成本轮验证。

当前调用链

五处调用:PUT、COPY REPLACE、NewMultipartUpload、Snowball 外层请求、Snowball PAX 条目。

  • PUT/COPY/multipart 使用规范化普通元数据;可信分支不应再覆盖它。
  • Snowball 外层只有 storage class/条目转换信息,没有通用提取;归档外层 Content-Type/Content-Encoding 不是条目元数据。
  • PAX 元数据经过普通提取;无 Content-Encoding 的 PAX 映射也不能留下先前泄漏的外层编码。
  • multipart 的 Part/CopyPart/Complete 不调用该恢复函数;完成后必须检验初始化元数据确实被保留。
  • 所有可信恢复均需通过认证、精确复制标记、ReplicateObject 权限和 REPLICA 状态的组合判断;Snowball 对每个条目分别鉴权。

erasure-metadata.go 将落盘 content-encoding 读入 ObjectInfoapi-headers.go 在 GET/HEAD 返回该值。对象字节并非因此一定受损。

AWS SigV4 streaming 规范 要求保存对象时去掉 aws-chunked,只保留实际的内容编码;只有 aws-chunked 时读取响应不应有 Content-Encoding。

实测记录

原始证据根目录:/Users/vonng/tmp/silo-r7-20260915-ad51/

记录 结果与边界
baseline_test.go / baseline-overlay.json / baseline.log 原始产品代码,临时 Go 测试覆盖:ordinary bare/mixed 正常,trusted bare/mixed 重新污染,纯 gzip 正常
http-baseline-unadapted.log 未调整夹具的本机单盘 HTTP 上传被 507 / XMinioStorageFull 拒绝;不是 R7 结果
http-baseline.log 首个容量适配 HTTP 运行;PUT/COPY/Snowball 可复现;multipart 夹具错误用 Header.Get 读取了仓库直接写入的 ETag 键,完成时 InvalidPart,不能用于 multipart 结论
http_test.go / http-capacity-overlay.json / http-baseline-v2.log 修正 ETag 读取后:PUT、COPY REPLACE、multipart 的普通和 untrusted-marker 对照通过;trusted bare/mixed 在落盘和 GET/HEAD 中失败;trusted gzip 通过;无权 replica 返回 403 且不建对象
同一最终 HTTP 基线日志的 Snowball 部分 no-PAX、PAX 无编码、PAX 裸编码、PAX 混合编码均复现 GET/HEAD 污染

最终 HTTP 基线总计 64 个叶子用例:44 个控制通过,20 个预期缺陷失败。每个用例均使用认证 HTTP handler + 实际对象磁盘。PUT 传输案例和 Snowball 使用真实流式分块签名,gzip 案例使用实际 gzip 字节;读取比较原始字节并检查 Content-Encoding。

容量适配的准确含义

宿主 APFS 报告约 100% 使用率,触发 SILO 的相对空闲阈值。临时 capacity-test-utils_test.go 使用仓库既有 tagTestCapacityDisk 包装 API 测试夹具,将总量/已用量报告为当前空闲量/0;实际对象写入、读取和元数据持久化仍落在测试磁盘。该 overlay 不进入产品 diff,也不调整生产容量策略。结果属于明确容量适配后的本地验证,不是未改夹具的通过。

方案与存量

冻结方案见 plan-v1.md。存量对象处理见 stored-metadata-remediation.md,只提供设计,本任务不执行现网对象改写。