
Benutzerdefinierte BTRFS-Reparaturwerkzeuge für schwere Extent-Baum-Korrumpierung, wenn btrfs check --repair fehlschlägt (Segfault, Endlosschleife oder Deadlock)
Eigene Werkzeuge, die während der Wiederherstellung eines 12-TB-Multi-Device-BTRFS-Pools mit schwerwiegender Korruption des Extent-Baums geschrieben wurden, den die nativen Befehle (btrfs check --repair, --init-extent-tree, usw.) nicht reparieren konnten.
Siehe INCIDENT-ANALYSIS.md für eine strukturierte Fallstudie der Wiederherstellung, eine Klassifizierung der Ursachen und eine Reihe konstruktiver Vorschläge für Verbesserungen des Upstream-btrfs-progs, die die Notwendigkeit der meisten dieser Werkzeuge verhindert hätten.
Verwenden Sie diese Werkzeuge NUR, wenn btrfs check --repair einen Segfault verursacht, in eine Endlosschleife gerät oder das Dateisystem in einem schlechteren Zustand hinterlässt als zuvor.
Dokumentierte Fälle, in denen sie helfen:
btrfs check --repair stürzt bei [3/8] checking extents ab (Issue #525)btrfs check --init-extent-tree verursacht einen Deadlockbtrfs check --repair gerät in eine Endlosschleife, die dieselben Reparaturen wiederholtrescue=all,ro, kann nicht RW gemountet werdenDiese Werkzeuge sind NICHT für leichte Korruption. Versuchen Sie bei normalen Schäden zuerst btrfs check --repair.
--write:
for DEV in sda1 sdb1 sdc1; do
sudo dd if=/dev/$DEV of=sb_${DEV}.bin bs=4096 count=1 skip=16
done
--write ist optional)Die Werkzeuge verwenden die interne btrfs-progs-API und müssen innerhalb des btrfs-progs-Quellbaums erstellt werden:
# 1. Clone btrfs-progs
git clone --depth 1 --branch v6.19.1 https://github.com/kdave/btrfs-progs.git
cd btrfs-progs
# 2. Apply the EEXIST patch (required for batch backref injection)
patch -p1 < path/to/btrfs_fixes/patches/alloc_reserved_tree_block_eexist.patch
# 3. Configure and build base btrfs-progs
./autogen.sh
./configure
make -j$(nproc)
# 4. Copy the .c files from this repo into the btrfs-progs directory
cp path/to/btrfs_fixes/programs/*.c .
# 5. For each program, add to the Makefile:
echo '
PROGNAME: PROGNAME.o $(objects) $(libs_shared)
@echo " [LD] $@"
$(Q)$(CC) -o $@ PROGNAME.o $(objects) $(libs_shared) $(LDFLAGS) $(LIBS)
' >> Makefile
# 6. Build
make PROGNAME
Empfohlene Ausführungsreihenfolge:
scan_and_fix_all_backrefs.c (am wichtigsten)Das wichtigste Werkzeug. Durchläuft rekursiv jeden Baum im Dateisystem (ROOT, CHUNK, EXTENT, FS, DEV, CSUM, UUID, FREE_SPACE) und erkennt Metadatenblöcke, denen ein METADATA_ITEM-Backref im Extent-Baum fehlt. Fügt alle fehlenden Backrefs in einer einzigen Transaktion ein, um das Problem zu vermeiden, dass „der Root-Baum zwischen Commits verschoben wird".
Verwendung:
sudo ./scan_and_fix_all_backrefs /dev/sdX # scan only
sudo ./scan_and_fix_all_backrefs /dev/sdX --write # scan + inject
fix_owner_refs.cKorrigiert den owner im Inline-TREE_BLOCK_REF, wenn er nicht mit dem tatsächlichen btrfs_header_owner() des Blocks übereinstimmt. Fehlpaarungen treten auf, wenn Blöcke bei fehlgeschlagenen Reparaturen zwischen Bäumen neu zugewiesen werden.
sudo ./fix_owner_refs /dev/sdX # scan
sudo ./fix_owner_refs /dev/sdX --write # fix
fix_bad_levels.cKorrigiert METADATA_ITEM- und EXTENT_ITEM-Einträge mit einem falschen Level. Korrupte Level (z. B. 50, 55, 237) sind Datenmüll, der von einer Endlosschleife von btrfs check --repair hinterlassen wurde. Überprüft gegen das tatsächliche btrfs_header_level() des Blocks.
sudo ./fix_bad_levels /dev/sdX # scan
sudo ./fix_bad_levels /dev/sdX --write # fix
fix_duplicate_extents.cLöscht doppelte METADATA_ITEMs (gleiche Bytenr, verschiedene Level im Schlüssel). Behält denjenigen, dessen Level mit btrfs_header_level übereinstimmt, und löscht den anderen.
sudo ./fix_duplicate_extents /dev/sdX # scan
sudo ./fix_duplicate_extents /dev/sdX --write # delete duplicates
remove_stale_ptrs.cDurchläuft jeden Level-1-Knoten des FS_TREE. Erkennt veraltete Child-Zeiger anhand von drei Prüfungen: Owner-Konflikt, first_key-Konflikt oder ein first_key dessen Typ für den FS_TREE ungültig ist (z.B. BLOCK_GROUP_ITEM). Entfernt sie mit btrfs_del_ptr.
sudo ./remove_stale_ptrs /dev/sdX # scan
sudo ./remove_stale_ptrs /dev/sdX --write # remove
fix_uuid_tree.c / fix_csum_tree.cErstellt ein leeres Blatt für den UUID-Baum bzw. CSUM-Baum. Nützlich, wenn der ROOT_ITEM auf einen Block zeigt, der einem anderen Baum neu zugewiesen wurde. Der Kernel regeneriert den UUID-Baum automatisch beim RW-Mount. Mit einem leeren CSUM-Baum schlagen Dateien mit dem Flag NODATASUM bei der Überprüfung nicht fehl.
sudo ./fix_uuid_tree /dev/sdX
sudo ./fix_csum_tree /dev/sdX
set_nodatasum.cSetzt das Flag BTRFS_INODE_NODATASUM auf regulären Datei-Inodes. Verwenden Sie dies, wenn der CSUM-Baum leer ist, Dateien aber weiterhin erwartete Prüfsummen haben, was zu Lesefehlern führt. Mit NODATASUM überspringt der Kernel die CSUM-Suche.
sudo ./set_nodatasum /dev/sdX # scan
sudo ./set_nodatasum /dev/sdX --write # apply
fix_fstree_node.cVersion mit einer fest codierten Liste veralteter Blöcke. Bevorzugen Sie remove_stale_ptrs, das sie automatisch erkennt. Verwenden Sie dies nur, wenn Sie die manuelle Kontrolle darüber benötigen, welche bestimmten Blöcke entfernt werden sollen.
add_backrefs.cErste Version mit einer fest codierten Liste fehlender Backrefs. Bevorzugen Sie scan_and_fix_all_backrefs, das sie automatisch erkennt.
Wenn die Basiswerkzeuge oben nicht ausreichten (Pool mit 200K+ Fehlern, verteilt auf mehrere Bäume), wurden diese zusätzlichen Werkzeuge erstellt:
scan_fstree_extents.c + scan_extent_tree.cScanner für Durchlauf 1 und 2, die den FS_TREE bzw. den Extent-Baum durchlaufen und TSV-Dateien mit jeder Referenz-/Extent-Zuordnung erstellen. Dienen zur Erstellung der Eingabe für rebuild_extent_tree_apply, wenn der Extent-Baum von Grund auf neu aufgebaut werden muss.
rebuild_extent_tree_apply.c (Schreib-Schwergewicht)Der Hauptschreiber von Phase 3. Nimmt eine vorgefaltete Liste von Referenzen (aus der Differenz von scan_fstree_extents + scan_extent_tree) und fügt 3M+ EXTENT_DATA_REFs in Blöcken von 5000 pro Transaktion in den Extent-Baum ein. Drosselt alle 50K Einträge, um DM-SMR-Neuüberlagerungsstaus zu vermeiden. Erfolgreich verifiziert mit 3.248.617 Einfügungen in ~34 Min auf 3× WD40EFAX SMR-Festplatten.
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