diff options
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go | 20 | ||||
-rwxr-xr-x | scripts/main.sh | 26 |
2 files changed, 22 insertions, 24 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go index 5923b6c..16b1e84 100644 --- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go +++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go @@ -7,6 +7,7 @@ package rebuildnodes import ( "context" "fmt" + iofs "io/fs" "math" "sort" @@ -133,15 +134,19 @@ func lostAndFoundNodes(ctx context.Context, fs *btrfs.FS, nodeScanResults btrfsi lastPct = pct } } - var done int attachedNodes := make(map[btrfsvol.LogicalAddr]struct{}) btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ TreeWalkHandler: btrfstree.TreeWalkHandler{ Node: func(path btrfstree.TreePath, _ *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error { - attachedNodes[path.Node(-1).ToNodeAddr] = struct{}{} - done++ - progress(done) + addr := path.Node(-1).ToNodeAddr + if _, alreadyVisited := attachedNodes[addr]; alreadyVisited { + // Can happen because of COW subvolumes; + // this is really a DAG not a tree. + return iofs.SkipDir + } + attachedNodes[addr] = struct{}{} + progress(len(attachedNodes)) return nil }, }, @@ -160,7 +165,7 @@ func lostAndFoundNodes(ctx context.Context, fs *btrfs.FS, nodeScanResults btrfsi } dlog.Infof(ctx, "... (finished processing %v attached nodes, proceeding to process %v lost nodes, for a total of %v)", - done, len(orphanedNodes), done+len(orphanedNodes)) + len(attachedNodes), len(orphanedNodes), len(attachedNodes)+len(orphanedNodes)) // 'orphanedRoots' is a subset of 'orphanedNodes'; start with // it as the complete orphanedNodes, and then remove entries. @@ -168,6 +173,7 @@ func lostAndFoundNodes(ctx context.Context, fs *btrfs.FS, nodeScanResults btrfsi for node := range orphanedNodes { orphanedRoots[node] = struct{}{} } + done := len(attachedNodes) for potentialRoot := range orphanedRoots { done++ progress(done) @@ -276,6 +282,10 @@ func reInitBrokenNodes(ctx context.Context, fs *btrfs.FS, nodeScanResults btrfsi }, } + // We use WalkAllTrees instead of just iterating over + // nodeScanResults so that we don't need to specifically check + // if any of the root nodes referenced directly by the + // superblock are dead. btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ Err: func(err *btrfsutil.WalkError) { // do nothing diff --git a/scripts/main.sh b/scripts/main.sh index 57e3e81..4e0d57a 100755 --- a/scripts/main.sh +++ b/scripts/main.sh @@ -23,24 +23,12 @@ gen $b.gen/0.scandevices.json \ gen $b.gen/1.mappings.json \ ./btrfs-rec --pv=$b.img \ inspect rebuild-mappings $b.gen/0.scandevices.json -# gen $b.gen/1.mappings.json \ -# ./btrfs-rec --pv=$b.img \ -# inspect rebuild-mappings $b.gen/0.scan-for-nodes.json -# gen $b.gen/2.csums.gob \ +gen $b.gen/2.nodes.json \ + ./btrfs-rec --pv=$b.img --mappings=$b.gen/1.mappings.json \ + inspect rebuild-nodes $b.gen/0.scandevices.json +# gen $b.gen/3.ls-files.txt \ # ./btrfs-rec --pv=$b.img --mappings=$b.gen/1.mappings.json \ -# inspect dump-sums -# # gen $b.gen/3.dbg.txt \ -# # ./btrfs-rec --pv=$b.img --mappings=$b.gen/1.mappings.json \ -# # inspect dbg $b.gen/2.csums.gob -# gen $b.gen/3.mappings.json \ -# ./btrfs-rec --pv=$b.img --mappings=$b.gen/1.mappings.json \ -# inspect scan-for-extents $b.gen/0.scan-for-nodes.json $b.gen/2.csums.gob -# gen $b.gen/4.ls-files.txt \ -# ./btrfs-rec --pv=$b.img --mappings=$b.gen/3.mappings.json \ # inspect ls-files -# gen $b.gen/4.ls-trees.txt \ -# ./btrfs-rec --pv=$b.img --mappings=$b.gen/3.mappings.json \ -# inspect ls-trees --nodescan=$b.gen/0.scan-for-nodes.json -# gen $b.gen/4.nodes.json \ -# ./btrfs-rec --pv=$b.img --mappings=$b.gen/3.mappings.json \ -# inspect rebuild-nodes $b.gen/0.scan-for-nodes.json +# gen $b.gen/3.ls-trees.txt \ +# ./btrfs-rec --pv=$b.img --mappings=$b.gen/1.mappings.json \ +# inspect ls-trees |