summaryrefslogtreecommitdiff
path: root/lib/btrfsprogs/btrfsinspect/rebuildnodes/s4_reattach.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/rebuildnodes/s4_reattach.go')
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/s4_reattach.go41
1 files changed, 34 insertions, 7 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/s4_reattach.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s4_reattach.go
index 8f3553e..32269fc 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/s4_reattach.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s4_reattach.go
@@ -14,20 +14,30 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
"git.lukeshu.com/btrfs-progs-ng/lib/containers"
+ "git.lukeshu.com/btrfs-progs-ng/lib/maps"
"git.lukeshu.com/btrfs-progs-ng/lib/slices"
)
func reAttachNodes(ctx context.Context, fs _FS, foundRoots map[btrfsvol.LogicalAddr]struct{}, rebuiltNodes map[btrfsvol.LogicalAddr]*RebuiltNode) error {
+ dlog.Info(ctx, "Attaching lost+found nodes to rebuilt nodes...")
+
+ sb, err := fs.Superblock()
+ if err != nil {
+ return err
+ }
+
// Index 'rebuiltNodes' for fast lookups.
+ dlog.Info(ctx, "... indexing rebuilt nodes...")
gaps := make(map[btrfsprim.ObjID]map[uint8][]*RebuiltNode)
maxLevel := make(map[btrfsprim.ObjID]uint8)
for _, node := range rebuiltNodes {
- maxLevel[node.Head.Owner] = slices.Max(maxLevel[node.Head.Owner], node.Head.Level)
-
- if gaps[node.Head.Owner] == nil {
- gaps[node.Head.Owner] = make(map[uint8][]*RebuiltNode)
+ for treeID := range node.InTrees {
+ maxLevel[treeID] = slices.Max(maxLevel[treeID], node.Head.Level)
+ if gaps[treeID] == nil {
+ gaps[treeID] = make(map[uint8][]*RebuiltNode)
+ }
+ gaps[treeID][node.Head.Level] = append(gaps[treeID][node.Head.Level], node)
}
- gaps[node.Head.Owner][node.Head.Level] = append(gaps[node.Head.Owner][node.Head.Level], node)
}
for _, byTreeID := range gaps {
for _, slice := range byTreeID {
@@ -36,10 +46,22 @@ func reAttachNodes(ctx context.Context, fs _FS, foundRoots map[btrfsvol.LogicalA
})
}
}
+ dlog.Info(ctx, "... done indexing")
// Attach foundRoots to the gaps.
- sb, _ := fs.Superblock()
- for foundLAddr := range foundRoots {
+ dlog.Info(ctx, "... attaching nodes...")
+ lastPct := -1
+ progress := func(done int) {
+ pct := int(100 * float64(done) / float64(len(foundRoots)))
+ if pct != lastPct || done == len(foundRoots) {
+ dlog.Infof(ctx, "... %v%% (%v/%v)",
+ pct, done, len(foundRoots))
+ lastPct = pct
+ }
+ }
+ numAttached := 0
+ for i, foundLAddr := range maps.SortedKeys(foundRoots) {
+ progress(i)
foundRef, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, foundLAddr, btrfstree.NodeExpectations{
LAddr: containers.Optional[btrfsvol.LogicalAddr]{OK: true, Val: foundLAddr},
})
@@ -84,12 +106,17 @@ func reAttachNodes(ctx context.Context, fs _FS, foundRoots map[btrfsvol.LogicalA
Generation: foundRef.Data.Head.Generation,
})
attached = true
+ numAttached++
}
if !attached {
dlog.Errorf(ctx, "could not find a broken node to attach node to reattach node@%v to",
foundRef.Addr)
}
}
+ progress(len(foundRoots))
+ dlog.Info(ctx, "... ... done attaching")
+ dlog.Infof(ctx, "... re-attached %d nodes (%v%% success rate)",
+ numAttached, int(100*float64(numAttached)/float64(len(foundRoots))))
return nil
}