사례 연구: 손상된 12 TB 멀티‑디바이스 풀 복구
Source: Hacker News
One paragraph summary
3‑디스크 풀(데이터 싱글, 메타데이터 DUP, DM‑SMR 디스크)에서 강제 전원 차단이 발생하면서 익스텐트 트리와 자유 공간 트리가 원시 복구 경로로는 해결할 수 없는 상태가 되었습니다. 이후 실행한 btrfs check --repair는 순환 진행이 46 000 회 이상 반복되면서 실제 진행이 전혀 없었고, 4개의 backup_roots 슬롯이 사전 충돌 복구 지점을 모두 지나버렸습니다. 최종적으로 내부 btrfs-progs API를 이용해 만든 14개의 맞춤형 C 도구 세트를 사용해 복구했으며, 4.59 TB 중 약 7.2 MB(0.00016 %) 정도의 데이터 손실만 발생했습니다. 현재 풀은 완전히 정상 가동 중입니다.
Full analysis
사례를 환경, 타임라인, 근본 원인 분류, 실험적으로 도출한 탄탄한 안전 기준, 그리고 상향식 변경만으로 대부분의 맞춤형 도구가 필요 없었을 상황을 방지할 수 있었던 9가지 구체적인 영역으로 구조화했습니다.
운영자가 유사한 상황에 직면했을 때 기대되는 영향도 순서대로 정리한 9가지 개선 영역은 다음과 같습니다:
- A.
btrfs check --repair에서 진행 상황을 감지해 46 000번의 커밋 루프가 명확한 메시지와 함께 중단되도록 하고,backup_roots파괴를 방지합니다. - B.
reinit_extent_tree에서BTRFS_ADD_DELAYED_REF를 대칭적으로 처리해 기존BTRFS_DROP_DELAYED_REF예외와 일치시킵니다. - C.
btrfs_del_items재균형 시 형제 안전 사전 검사를 추가해LEAF_DATA_SIZE/4이하로 감소할 경우 오래된 공유 형제에 대해push_leaf_left가 트리거되지 않도록 합니다. - D.
alloc_reserved_tree_block에서EEXIST처리를 감독하도록 세 가지 명시적 모드(error,silent,update)를 도입합니다. - E. 사전 스캔된 ref 리스트를 기반으로 동작하는
btrfs rescue rebuild-extent-tree서브커맨드를 제공해 현재 교착 상태에 빠지는--init-extent-tree를 대체합니다. - F. 내장된 드라이런(dry‑run)과 탄탄한 5조건 검사를 적용하고 기계가 읽을 수 있는 계획을 출력하는
btrfs rescue clean-orphan-inodes서브커맨드를 추가합니다. - G. 대량 익스텐트‑트리 재구축 후
BLOCK_GROUP_ITEM.used를 정밀하게 수정하는btrfs rescue fix-bg-accounting을 제공합니다. - H.
backup_roots[0..3]이 네 번 커밋을 순환하는 슬라이딩 윈도우이며, 과거 백업이 아니라는 점을 명확히 문서화합니다(많이 오해되는 부분). - I. DIR
i_size = sum(namelen * 2)규칙을 문서화합니다. 이 규칙이 고아 디렉터리 엔트리 정리 중에 문제를 일으켰으며 현재 사용자 문서에 명시되어 있지 않습니다.
Reference implementation
14개의 맞춤형 도구와 alloc_reserved_tree_block에 대한 한 줄 패치는 모두 GPL‑2.0 라이선스로 다음 저장소에 공개되었습니다:
각 도구는 기본적으로 읽기 전용 스캔 모드를 제공하며, --write 모드는 선택적으로 활성화됩니다. README.md에 복구 과정에서 사용된 실행 순서가 설명되어 있습니다. 이 구현을 바로 상향 패치로 제안하는 것은 아니며, 위 제안 중 대부분은 단일 함수 변경이 아니라 시스템 전반에 걸친 설계 논의가 필요합니다. 별도의 풀 리퀘스트를 열기보다 참고 구현을 공유하는 것이 더 유용하다고 판단했습니다.
How I would like this to be received
이 내용을 요구가 아니라 의견으로 받아주셨으면 합니다. 하나의 관찰이나 제안이라도 가치가 있다면 분석을 추가로 확장하거나 세션 로그를 제공하고, 제안된 패치를 실제 손상 상황에 적용해 테스트하는 데 협조하겠습니다. 전혀 도움이 되지 않는다면 괜찮으며, 우리를 대부분 구해낸 도구 세트에 감사드립니다.
다시 한 번 감사합니다.