Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
btrfs_fixes — 심각한 익스텐트 트리 손상용 사용자 정의 BTRFS 복구 도구 (btrfs check --repair가 세그폴트, 루프, 또는 데드락으로 실패하는 경우) | Kitploit
도구/GitHubGitHub/msedek/btrfs_fixes
Vulnerability AnalysisForensicsData RecoveryPapers & ResearchLearning & Education
GitHubmsedek/btrfs_fixes

btrfs_fixes

심각한 익스텐트 트리 손상용 사용자 정의 BTRFS 복구 도구 (btrfs check --repair가 세그폴트, 루프, 또는 데드락으로 실패하는 경우)

저장소 보기
94개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

btrfs_fixes: 사용자 정의 BTRFS 복구 도구

네이티브 명령어(btrfs check --repair, --init-extent-tree 등)로 복구할 수 없었던 심각한 익스텐트 트리 손상이 있는 12TB 멀티 디바이스 BTRFS 풀 복구 중에 작성된 사용자 정의 도구입니다.

복구의 구조화된 사례 연구, 근본 원인 분류, 그리고 이러한 도구의 대부분이 필요하지 않게 했을 상류 btrfs-progs 개선을 위한 건설적인 제안 모음을 보려면 **INCIDENT-ANALYSIS.md**를 참조하십시오.

이 도구를 사용해야 하는 경우

btrfs check --repair가 세그폴트를 일으키거나, 무한 루프에 빠지거나, 파일 시스템을 이전보다 더 나쁜 상태로 만드는 경우에만 이 도구를 사용하십시오.

도움이 되는 것으로 문서화된 사례:

  • btrfs check --repair가 [3/8] checking extents에서 세그폴트 (이슈 #525)
  • btrfs check --init-extent-tree 데드락
  • btrfs check --repair가 동일한 복구를 반복하며 무한 루프
  • 잘못된 owner/level/generation을 가진 수천 개의 METADATA_ITEM이 있는 익스텐트 트리
  • 다른 트리에서 재사용된 블록을 참조하는 오래된 자식 포인터가 있는 FS_TREE
  • rescue=all,ro로만 마운트되고 RW 마운트에 실패하는 풀

이 도구는 가벼운 손상용이 아닙니다. 일반적인 손상의 경우 먼저 btrfs check --repair를 시도하십시오.

경고

  • --write 옵션으로 도구를 실행하기 전에 메타데이터를 백업하세요:
    root@kitploit:~
    for DEV in sda1 sdb1 sdc1; do
      sudo dd if=/dev/$DEV of=sb_${DEV}.bin bs=4096 count=1 skip=16
    done
    
  • 이 도구들은 파일 시스템에 되돌릴 수 없는 변경을 가합니다.
  • 모든 도구는 기본적으로 스캔 전용 모드입니다(--write는 옵트인).
  • 이 도구를 실행할 때 파일 시스템은 마운트 해제되어 있어야 합니다.
  • btrfs-progs v6.19.1 이상이 필요하며, EEXIST 패치가 적용되어 있어야 합니다.

빌드

도구는 내부 btrfs-progs API를 사용하며, btrfs-progs 소스 트리 내에서 빌드해야 합니다.

root@kitploit:~
# 1. btrfs-progs 클론
git clone --depth 1 --branch v6.19.1 https://github.com/kdave/btrfs-progs.git
cd btrfs-progs

# 2. EEXIST 패치 적용 (배치 백레퍼 주입에 필요)
patch -p1 < path/to/btrfs_fixes/patches/alloc_reserved_tree_block_eexist.patch

# 3. 기본 btrfs-progs 구성 및 빌드
./autogen.sh
./configure
make -j$(nproc)

# 4. 이 저장소의 .c 파일을 btrfs-progs 디렉토리로 복사
cp path/to/btrfs_fixes/programs/*.c .

# 5. 각 프로그램에 대해 Makefile에 추가:
echo '
PROGNAME: PROGNAME.o $(objects) $(libs_shared)
	@echo "  [LD]    $@"
	$(Q)$(CC) -o $@ PROGNAME.o $(objects) $(libs_shared) $(LDFLAGS) $(LIBS)
' >> Makefile

# 6. 빌드
make PROGNAME

도구

권장 실행 순서:

1. scan_and_fix_all_backrefs.c (가장 중요)

가장 중요한 도구입니다. 파일 시스템의 모든 트리(ROOT, CHUNK, EXTENT, FS, DEV, CSUM, UUID, FREE_SPACE)를 재귀적으로 탐색하며 익스텐트 트리에서 METADATA_ITEM 백레퍼가 누락된 메타데이터 블록을 감지합니다. 단일 트랜잭션에서 누락된 모든 백레퍼를 주입하여 '루트 트리가 커밋 사이에 이동하는' 문제를 방지합니다.

사용법:

root@kitploit:~
sudo ./scan_and_fix_all_backrefs /dev/sdX          # 스캔 전용
sudo ./scan_and_fix_all_backrefs /dev/sdX --write  # 스캔 + 주입

2. fix_owner_refs.c

인라인 TREE_BLOCK_REF의 owner가 블록의 실제 btrfs_header_owner()와 일치하지 않을 때 수정합니다. 불일치는 실패한 복구 중에 블록이 트리 간에 재할당될 때 발생합니다.

root@kitploit:~
sudo ./fix_owner_refs /dev/sdX          # 스캔
sudo ./fix_owner_refs /dev/sdX --write  # 수정

3. fix_bad_levels.c

잘못된 레벨을 가진 METADATA_ITEM 및 EXTENT_ITEM 항목을 수정합니다. 손상된 레벨(예: 50, 55, 237)은 btrfs check --repair가 루프에 빠지면서 남긴 쓰레기입니다. 블록의 실제 btrfs_header_level()과 비교하여 확인합니다.

root@kitploit:~
sudo ./fix_bad_levels /dev/sdX          # 스캔
sudo ./fix_bad_levels /dev/sdX --write  # 수정

4. fix_duplicate_extents.c

중복 METADATA_ITEM(동일 bytenr, 키에서 다른 레벨)을 삭제합니다. 레벨이 btrfs_header_level과 일치하는 항목을 유지하고 나머지를 삭제합니다.

root@kitploit:~
sudo ./fix_duplicate_extents /dev/sdX          # 스캔
sudo ./fix_duplicate_extents /dev/sdX --write  # 중복 삭제

5. remove_stale_ptrs.c

FS_TREE의 모든 레벨-1 노드를 스캔합니다. 세 가지 검사(owner 불일치, first_key 불일치, 또는 FS_TREE에 유효하지 않은 유형(예: BLOCK_GROUP_ITEM)의 first key)를 사용하여 오래된 자식 포인터를 감지합니다. btrfs_del_ptr로 제거합니다.

root@kitploit:~
sudo ./remove_stale_ptrs /dev/sdX          # 스캔
sudo ./remove_stale_ptrs /dev/sdX --write  # 제거

6. fix_uuid_tree.c / fix_csum_tree.c

UUID 트리 / CSUM 트리에 대해 빈 리프를 생성합니다. ROOT_ITEM이 다른 트리에 재할당된 블록을 가리킬 때 유용합니다. 커널은 RW 마운트 시 UUID 트리를 자동으로 재생성합니다. 빈 CSUM 트리에서는 NODATASUM 플래그가 설정된 파일이 검증에 실패하지 않습니다.

root@kitploit:~
sudo ./fix_uuid_tree /dev/sdX
sudo ./fix_csum_tree /dev/sdX

7. set_nodatasum.c

일반 파일 inode에 BTRFS_INODE_NODATASUM 플래그를 설정합니다. csum 트리가 비어 있지만 파일에 여전히 예상 체크섬이 있어 읽기 오류가 발생하는 경우 사용합니다. NODATASUM이 설정되면 커널이 csum 조회를 건너뜁니다.

root@kitploit:~
sudo ./set_nodatasum /dev/sdX          # 스캔
sudo ./set_nodatasum /dev/sdX --write  # 적용

8. fix_fstree_node.c

오래된 블록의 하드코딩된 목록이 있는 버전입니다. 자동으로 감지하는 remove_stale_ptrs를 선호합니다. 특정 블록을 수동으로 제어해야 하는 경우에만 사용하십시오.

9. add_backrefs.c

누락된 백레퍼의 하드코딩된 목록이 있는 초기 버전입니다. 자동으로 감지하는 scan_and_fix_all_backrefs를 선호합니다.

세션 2 도구 세트 (2026-04-04/05): 대규모 손상을 위한 확장 복구

위의 기본 도구가 충분하지 않았을 때(여러 트리에 걸쳐 200K+ 오류가 있는 풀) 다음과 같은 추가 도구가 구축되었습니다:

scan_fstree_extents.c + scan_extent_tree.c

각각 FS_TREE와 익스텐트 트리를 탐색하여 모든 참조/익스텐트 매핑을 TSV 파일로 생성하는 패스 1 및 패스 2 스캐너입니다. 익스텐트 트리를 처음부터 다시 빌드해야 할 때 rebuild_extent_tree_apply의 입력을 구축하는 데 사용됩니다.

rebuild_extent_tree_apply.c (무거운 기록기)

주요 페이즈 3 기록기입니다. 사전 병합된 참조 목록(scan_fstree_extents + scan_extent_tree 비교 결과)을 가져와 트랜잭션당 5000개씩 묶어 3M+ EXTENT_DATA_REF를 익스텐트 트리에 주입합니다. DM-SMR 재-싱글 스톨을 피하기 위해 50K 항목마다 스로틀합니다. 3개의 WD40EFAX SMR 디스크에서 약 34분에 3,248,617개 삽입 성공 확인됨.

root@kitploit:~
sudo ./rebuild_extent_tree_apply /dev/sdX1 refs_folded.txt to_insert.txt watermark.txt --dryrun
sudo ./rebuild_extent_tree_apply /dev/sdX1 refs_folded.txt to_insert.txt watermark.txt --write

patch_block_group_used.c

페이즈 3 기록기가 기존 중복 file_extent_items로 인해 특정 bg에 초과 사용량을 남겼을 때 BLOCK_GROUP_ITEM.used를 외과적으로 단일 필드 패치하는 도구입니다. btrfs_update_block_group 공간 정보 계정(여기서는 원하지 않음)을 피하기 위해 btrfs_set_block_group_used 직접 세터를 사용합니다. flags & BTRFS_BLOCK_GROUP_DATA를 사전 검증합니다.

root@kitploit:~
sudo ./patch_block_group_used /dev/sdX1 <bg_bytenr> <bg_length> <new_used> --write

remove_extent_items_by_key.c

익스텐트 트리에서 (bytenr, num_bytes, expected_inode) EXTENT_ITEM의 하드코딩된 목록을 삭제합니다. 단일 리프에서 RO 마운트를 방해하는 중복된 오래된 익스텐트를 정리하는 데 사용됩니다. 삭제 전에 항목별 무결성 검사(inode 허용 목록 포함 7가지 불변 조건)를 수행합니다. rebuilding_extent_tree=1 + reinit_extent_tree=true로 실행하여 공간 계정을 건너뜁니다(호출자가 먼저 patch_block_group_used를 통해 used를 수동으로 패치함).

clean_orphan_dir_entries.c

FS_TREE에서 고아 DIR_ITEM + DIR_INDEX 항목을 정리합니다. 트랜잭션당 100개 항목씩 청크로 처리합니다. 상위 INODE_ITEM i_size를 업데이트합니다(namelen × 2만큼 감소: 중요한 버그 수정: v1은 namelen만 감소시켜 디렉토리를 잘못된 상태로 남겼습니다). 중요한 최상위 디렉토리 이름(e.g. pelis, series, music, backups, homestorage)에 대한 하드코딩된 제외 목록이 있습니다. 절대 i_size를 원시 namelen으로 감소시키지 마십시오: BTRFS는 namelen × 2 계정을 저장합니다.

clean_orphan_inode_refs.c

key.offset(상위 inode)이 고아 상위 목록에 있는 INODE_REF 항목을 위해 FS_TREE를 탐색합니다. 오탐을 피하기 위해 INODE_EXTREF는 건너뜁니다 (EXTREF의 key.offset은 해시이며 상위 ID가 아닙니다). 트랜잭션당 32개씩 청크로 처리합니다.

fix_dir_inode_counts.c

이전 고아 정리 버그로 인해 개수가 손상된 DIR inode에 대해 i_size = sum(name_len × 2) 및 nlink = 1을 다시 계산합니다. 안전에 매우 중요: DIR에 nlink = 2가 있으면 해당 경로에 대한 단일 rm -rf가 수천 개의 서브디렉토리를 조용히 삭제합니다(rmdir 폭탄). DIR_INDEX 항목을 탐색하고 DIR_ITEM과 교차 확인하여 해시 충돌을 감지합니다(경험적으로 0 충돌 확인).

remove_orphan_inode_subtrees.c

FS_TREE에서 고아 inode 서브트리(DIR 계열 + 독립 REG)를 제거합니다. 각 대상에 대해 EXTENT_DATA, INODE_REF, INODE_EXTREF, XATTR, 마지막으로 INODE_ITEM을 탐색 및 삭제합니다. DIR 계열당 트랜잭션(서브트리당 원자적), 독립 REG에 대해 50개씩 청크로 처리합니다. 하드코딩된 편집증적 제외 목록이 있습니다.

⚠️ 주요 안전 주의사항: 아래 "무적 부분 집합 기준"을 참조하십시오.

remove_stale_ptrs_v2.c

remove_stale_ptrs의 개선된 버전: parent expected_key가 있는 빈 리프를 감지합니다(v1은 이 경우를 건너뜀), 재귀적 2레벨 스캔(루트→레벨1 + 레벨1→리프), 동적 버퍼(512 제한 없음), read_tree_block 실패를 허용합니다.

insert_one_extent_poc.c

검증이 포함된 단일 익스텐트 삽입을 위한 개념 증명입니다. rebuild_extent_tree_apply를 실행하기 전에 API 경로를 검증하는 데 사용됩니다.

무적 부분 집합 기준 (매우 중요)

2026-04-05 세션에서 remove_orphan_inode_subtrees가 동일한 BUG_ON 어설션에서 서로 다른 두 가지 이유로 두 번 충돌했습니다:

충돌 벡터 1: 혼합 리프(세대 3601, 고아 및 활성 inode 모두 포함)에서 직접 btrfs_cow_block(leaf) → update_ref_for_cow가 자식 탐색 → 오래된 형제 자식에 대해 __btrfs_mod_ref(inc=1) → btrfs_free_extent(phantom)이 -ENOENT 반환 → BUG_ON → SIGABRT.

충돌 벡터 2 (나중에 발견, 필터링으로 회피): 정리 후 btrfs_del_items가 리프를 LEAF_DATA_SIZE/4 = 4096 바이트 아래로 배출 → push_leaf_left(sibling) 또는 push_leaf_right(sibling) 호출 → 형제의 gen ≤ last_snapshot = 3701이면 btrfs_block_can_be_shared가 1 반환 → update_ref_for_cow가 refs > 1 경로 진입 → btrfs_inc_ref(cow_sibling, 0) → __btrfs_mod_ref(cow, level=0, inc=1) → 오래된 형제의 모든 EXTENT_DATA 반복 → btrfs_inc_extent_ref(phantom_bytenr) → extent-tree.c:1302에서 BUG_ON(err) → SIGABRT.

플래그 fs_info->rebuilding_extent_tree = 1 및 trans->reinit_extent_tree = true는 INC 경로를 저장하지 않습니다: 이는 BTRFS_DROP_DELAYED_REF만 면제합니다(extent-tree.c:3885에서 확인). BTRFS_ADD_DELAYED_REF(btrfs_inc_ref에서 발생)는 치명적입니다.

삭제될 대상 inode에 대한 무적 기준:

  1. inode의 INODE_ITEM을 포함하는 리프의 gen > 3701 (충돌 후)
  2. 리프의 상위 레벨-1의 gen > 3701
  3. 정리 후 예상 used 바이트 > 4096 (재조정 트리거 없음)
  4. 상위 노드의 모든 직접 형제의 gen > 3701 (조건 3이 실패하더라도 충돌 후 형제로의 재조정은 안전)
  5. 모든 백레퍼 대상(EXTENT_DATA disk_bytenr)이 현재 익스텐트 트리에서 확인됨(백레퍼 조회 시 -ENOENT 없음)

조건 3+4 중 하나라도 위반하면 충돌 벡터 2가 발생합니다. 조건 5는 DROP에 대해 reinit_extent_tree에 의해 면제되지만 INC( push_leaf_left가 호출하는 것)에 대해서는 면제되지 않습니다.

경험적 검증 패턴

후보 고아 inode 세트에 대해 FS_TREE 덤프를 탐색하고 각 대상 리프를 5가지 무적 조건으로 분류합니다. 예시 패턴(익명화):

항목의 90% 이상이 고아인 리프가 위험 구역입니다. 이들은 확실히 재조정 임계값(LEAF_DATA_SIZE/4 = 4096바이트) 아래로 배출되어 push_leaf_left/right를 강제합니다. 상위 노드에서 직접 형제 중 하나라도 gen ≤ last_snapshot이면 push가 해당 형제에서 CoW를 트리거하고, 이는 btrfs_block_can_be_shared → refs > 1 → btrfs_inc_ref → __btrfs_mod_ref(inc=1) 경로에 진입하여 btrfs_inc_extent_ref의 BUG_ON(err)으로 충돌합니다.

완화: 입력 파일에서 문제가 있는 inode를 제외합니다. 도구는 사전 비행 검증을 통과하는 모든 것을 처리합니다. 안전/위험 대상이 섞인 리프는 안전한 부분 집합만 나열하여 부분적으로 처리할 수 있습니다. 가족별 트랜잭션 의미론은 다른 가족이 제외되더라도 각 안전 가족이 원자적으로 커밋됨을 의미합니다.

한 세션의 경험적 결과: N개의 후보 고아에서 시작하여 모든 5가지 조건을 적용한 후 최종 안전 부분 집합은 입력의 약 14%였지만, 해당 부분 집합은 단 한 번의 BUG_ON 없이 커밋되었으며, 쓰기 전에 캡처된 라이브 파일의 기준 sha256에 대해 0바이트 차이가 있었습니다.

패치: alloc_reserved_tree_block의 EEXIST

patches/alloc_reserved_tree_block_eexist.patch는 btrfs-progs를 수정하여 alloc_reserved_tree_block이 METADATA_ITEM이 이미 존재함을 발견하면 EEXIST를 전파하는 대신 0을 반환하도록 합니다. 이는 배치 백레퍼 주입이 작동하는 데 필요합니다. 많은 백레퍼를 주입할 때 지연된 참조 시스템도 COW를 통해 새로 할당된 블록에 대해 METADATA_ITEM을 생성하려고 시도하고 이미 삽입한 것과 충돌하기 때문입니다.

심각한 복구를 위한 전체 워크플로

root@kitploit:~
# 1. 백업
mkdir -p backup
for DEV in /dev/sdX1 /dev/sdY1; do
  sudo dd if=$DEV of=backup/$(basename $DEV).sb bs=4096 count=1 skip=16
done

# 2. 파일 시스템이 마운트 해제되었는지 확인
sudo umount /mnt/pool 2>/dev/null

# 3. 로그 트리 제로 (해당하는 경우)
sudo btrfs rescue zero-log /dev/sdX1

# 4. 모든 것 스캔 + 수정 (순서대로)
sudo ./scan_and_fix_all_backrefs /dev/sdX1 --write
sudo ./fix_bad_levels /dev/sdX1 --write
sudo ./fix_owner_refs /dev/sdX1 --write
sudo ./fix_duplicate_extents /dev/sdX1 --write
sudo ./remove_stale_ptrs /dev/sdX1 --write

# 5. 재스캔하여 수렴 확인
sudo ./scan_and_fix_all_backrefs /dev/sdX1
sudo ./remove_stale_ptrs /dev/sdX1

# 6. csum 트리가 손상된 경우:
sudo ./fix_csum_tree /dev/sdX1
sudo ./set_nodatasum /dev/sdX1 --write

# 7. RW 마운트 시도
sudo mount -o rw /dev/sdX1 /mnt/pool

# 8. 마운트되면 btrfs check readonly로 확인
sudo btrfs check --force /dev/sdX1

알려진 제한 사항

  1. 각 복구는 COW를 통해 새로운 문제를 만들 수 있습니다: 도구가 익스텐트 트리를 수정하면 btrfs가 영향을 받은 노드를 COW합니다. 새 노드는 이전 노드의 포인터를 복사하여 오래된 포인터를 전파할 수 있습니다. 여러 번의 패스가 필요할 수 있습니다.

  2. 데이터 익스텐트 참조 불일치는 수정되지 않습니다: 이 도구는 메타데이터 백레퍼만 다룹니다. 데이터 익스텐트의 잘못된 참조 카운트(실패한 btrfs check --repair 실행 후 흔함)는 정리되지 않습니다.

  3. 고아 inode는 정리되지 않습니다: FS_TREE의 고아 디렉토리 항목(더 이상 존재하지 않는 inode에 대한 참조)은 제거되지 않습니다.

  4. btrfs check --repair를 대체하지 않습니다: 이 도구는 특정 시나리오를 대상으로 합니다. 경미하거나 중간 정도의 손상에는 btrfs check --repair가 더 좋습니다.

배운 점

  1. 멀티 디바이스 BTRFS 파일 시스템을 절대 강제 전원 차단하지 마십시오: 결합된 여유 공간 트리 + 익스텐트 트리 손상은 복구하기가 매우 어렵습니다.

  2. 첫 번째 실행이 모든 것을 해결하지 못했다면 btrfs check --repair를 연속으로 여러 번 실행하지 마십시오: 이는 무한 루프에 빠져 파일 시스템을 극적으로 더 악화시킬 수 있습니다.

  3. 모든 쓰기 작업 전에 항상 슈퍼블록을 백업하십시오.

  4. **trans->reinit_extent_tree = true**는 백레퍼가 없는 블록에 대한 지연된 참조에서 DROP 실패를 무시하는 열쇠입니다.

  5. **fs_info->rebuilding_extent_tree = 1**은 복구 중 공간 검사를 비활성화합니다.

  6. 많은 삽입이 있는 하나의 큰 커밋이 여러 개의 작은 커밋보다 낫습니다. 중간 커밋이 루트 트리를 이동시키기 때문입니다.

  7. SB의 backup_slots는 기록 백업이 아닙니다: 이는 가장 최근 4개의 커밋만 포함하는 슬라이딩 윈도우입니다. 46,000+ 커밋의 btrfs check --repair 루프는 몇 분 만에 모든 슬롯을 약 11,000번 회전시켜 커널에서 복구할 수 있는 충돌 전 상태를 파괴합니다. 실제 보존을 위해서는 명시적인 btrfs subvolume snapshot 또는 다른 장치로의 btrfs send 스트림이 필요합니다.

  8. reinit_extent_tree는 비대칭입니다: BTRFS_DROP_DELAYED_REF만 면제하고 BTRFS_ADD_DELAYED_REF는 면제하지 않습니다. 오래된 리프에서 를 호출하는 모든 코드 경로(재조정 중 포함)는 여전히 → 을 통해 충돌합니다.

면책 조항

이 도구는 네이티브 도구가 실패한 특정 복구 사례를 위해 작성되었습니다. 일반적인 사용 사례에 대해 테스트되지 않았습니다. 코드를 이해하고 데이터 손실 위험을 수용하는 경우에만 사용하십시오.

가능하다면 복구를 시도하기 전에 항상 데이터를 복사하십시오.

라이선스

GPL-2.0 (이 도구가 내부 API를 사용하는 btrfs-progs와 호환됨)

도구 다운로드
리프세대고아 항목 / 전체제거 후 사용량(추정)재조정?직접 형제판정
$LEAF_A충돌 후대부분 고아, 대량 제거임계값 미만예모두 충돌 후✓ 안전
$LEAF_B충돌 후대부분 활성, 소량 제거임계값 이상아니요깨끗한 상위✓ 안전
$LEAF_C충돌 후거의 100% 고아4096보다 훨씬 낮음예 강제충돌 전 오래된❌ 충돌
btrfs_inc_ref
push_leaf_left/right
btrfs_inc_extent_ref
BUG_ON(err)
  • 손상된 FS_TREE에서 inode를 처리하기 위한 안전 기준에는 대상 리프 자체뿐만 아니라 형제도 포함되어야 합니다. "무적 부분 집합 기준" 섹션을 참조하십시오.

  • 라이브 파일의 기준 sha256은 불변 조건에 대한 유일한 경험적 증거입니다. 쓰기 작업 전에 캡처하고 이후에 차이를 확인하십시오. 불일치 = 롤백.

  • DIR i_size는 sum(name_len × 2)로 저장되며 sum(name_len)이 아닙니다. 항목 제거 시 i_size를 감소시키는 고아 정리 도구는 namelen × 2만큼 감소해야 합니다. 이를 잘못하면 DIR이 잘못된 상태로 남을 수 있으며, 나중에 nlink = 2로 나타날 수 있습니다. 이는 풀이 RW로 마운트된 경우 rmdir 폭탄을 유발합니다(단일 rm -rf가 상위에서 수천 개의 서브디렉토리를 조용히 삭제할 수 있음).

  • 경험적 증거를 가진 전문 검토 에이전트가 중요합니다. 2026-04-05 세션은 두 개의 병렬 Opus 검토자(btrfs 내부 + 운영)를 사용하여 제안된 계획을 덤프-트리 출력에 대해 분석했습니다. 그들은 이전 실패를 반복했을 결정적 충돌 벡터(push_leaf_left → 오래된 형제)를 발견했습니다. 경험적 덤프-트리 분석 없는 텍스트 계획 검토는 이를 놓쳤을 것입니다.