Files
rustfs/crates/heal
Zhengchao An 3531abb34a feat(heal): disk-walk UNION enumeration to heal sub-quorum versions (backlog#920) (#4527)
B5 switched heal enumeration to list_object_versions, which only reflects the
read-quorum metadata view: a version present on fewer than read-quorum disks was
never enumerated, so it was never healed. Add a per-erasure-set disk-walk UNION
enumerator (mirrors MinIO global-heal.go objQuorum=1 listPathRaw +
mergeXLV2Versions) that surfaces every (object, version) present on ANY disk and
feeds each to the existing per-version heal_object.

- filemeta: MetaCacheEntries::resolve_union (dir_quorum=1/obj_quorum=1) yields the
  cross-disk version union at one tested seam.
- ecstore: SetDisks::heal_walk_versions_page (list_path_raw fan-out, min_disks=1,
  dual object/version page bound, inclusive-forward de-overlap) + ECStore delegator
  + HealWalkVersion.
- ecstore data-safety guard: before dangling-delete, try_regenerate_recoverable_meta
  physically probes part files via check_parts; when >= data_blocks data shards
  survive (meta lost but data recoverable) it regenerates xl.meta from a surviving
  FileInfo with the correct per-disk shard index instead of dangling-deleting.
  Genuine torn writes (< data_blocks) keep the current behavior — no resurrection.
- heal: dw1: forward-marker cursor codec (reuses ResumeState.resume_cursor,
  idempotent restart on foreign tokens); list_versions_for_heal_page_disk_walk
  trait method (default falls back to the B5 read-quorum path); heal_bucket_with_resume
  selects the disk-walk enumerator when scan_mode==Deep || source==AutoHeal, else
  the unchanged B5 path; anti-loop guard aborts on (empty && truncated).

Closes rustfs/backlog#920
2026-07-09 01:07:54 +08:00
..