diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-08-28 11:51:11 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-08-28 18:10:25 -0600 |
commit | 8bd5cfbedb026ac64bd26fc9b9ae5bd358893203 (patch) | |
tree | 4bb8bcd7f544d535fc1a2fca1ea6e32046dc20e6 /lib/btrfsprogs/btrfsinspect/rebuildnodes | |
parent | e2cdb05eac6726c59fe1831876fddd8037156d67 (diff) |
wip: rebuild-nodes
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/rebuildnodes')
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go | 20 |
1 files changed, 15 insertions, 5 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 |