summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-08-29 21:09:04 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-08-30 21:29:17 -0600
commit66a0058a5c2921b5c4e35732011d32810a9d2f7a (patch)
tree27049d6e802d64ba4c288acc493483b5b68dbd3e /lib
parent079c2a1316616b997e0050a1423c0a5e6bda4f16 (diff)
move things between files
Diffstat (limited to 'lib')
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go87
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/s1_uuidmap.go (renamed from lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go)0
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_lostandfound.go105
3 files changed, 105 insertions, 87 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go
index 7950393..e5ae5e4 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go
@@ -6,12 +6,10 @@ package rebuildnodes
import (
"context"
- "errors"
"fmt"
iofs "io/fs"
"math"
"sort"
- "strings"
"github.com/datawire/dlib/dlog"
@@ -135,91 +133,6 @@ func countNodes(nodeScanResults btrfsinspect.ScanDevicesResult) int {
return cnt
}
-func lostAndFoundNodes(ctx context.Context, fs _FS, nodeScanResults btrfsinspect.ScanDevicesResult) (map[btrfsvol.LogicalAddr]struct{}, error) {
- lastPct := -1
- total := countNodes(nodeScanResults)
- progress := func(done int) {
- pct := int(100 * float64(done) / float64(total))
- if pct != lastPct || done == total {
- dlog.Infof(ctx, "... %v%% (%v/%v)",
- pct, done, total)
- lastPct = pct
- }
- }
-
- 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 {
- 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
- },
- },
- Err: func(err *btrfsutil.WalkError) {
- // do nothing
- if !errors.Is(err, btrfstree.ErrNotANode) && !strings.Contains(err.Error(), "read: could not map logical address") {
- dlog.Errorf(ctx, "dbg walk err: %v", err)
- }
- },
- })
-
- orphanedNodes := make(map[btrfsvol.LogicalAddr]int)
- for _, devResults := range nodeScanResults {
- for laddr := range devResults.FoundNodes {
- if _, attached := attachedNodes[laddr]; !attached {
- orphanedNodes[laddr] = 0
- }
- }
- }
- dlog.Infof(ctx,
- "... (finished processing %v attached nodes, proceeding to process %v lost nodes, for a total of %v)",
- 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.
- orphanedRoots := make(map[btrfsvol.LogicalAddr]struct{}, len(orphanedNodes))
- for node := range orphanedNodes {
- orphanedRoots[node] = struct{}{}
- }
- done := len(attachedNodes)
- for potentialRoot := range orphanedRoots {
- done++
- progress(done)
- if orphanedNodes[potentialRoot] > 1 {
- continue
- }
- walkCtx, cancel := context.WithCancel(ctx)
- walkFromNode(walkCtx, fs, potentialRoot,
- func(err *btrfstree.TreeError) {
- // do nothing
- },
- btrfstree.TreeWalkHandler{
- PreNode: func(path btrfstree.TreePath) error {
- nodeAddr := path.Node(-1).ToNodeAddr
- if nodeAddr != potentialRoot {
- delete(orphanedRoots, nodeAddr)
- }
- visitCnt := orphanedNodes[nodeAddr] + 1
- orphanedNodes[nodeAddr] = visitCnt
- if visitCnt > 1 {
- cancel()
- }
- return nil
- },
- },
- )
- }
-
- return orphanedRoots, nil
-}
-
func getChunkTreeUUID(ctx context.Context, fs _FS) (btrfsprim.UUID, bool) {
ctx, cancel := context.WithCancel(ctx)
var ret btrfsprim.UUID
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s1_uuidmap.go
index ba090fb..ba090fb 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s1_uuidmap.go
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_lostandfound.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_lostandfound.go
new file mode 100644
index 0000000..8da8588
--- /dev/null
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_lostandfound.go
@@ -0,0 +1,105 @@
+// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package rebuildnodes
+
+import (
+ "context"
+ "errors"
+ iofs "io/fs"
+ "strings"
+
+ "github.com/datawire/dlib/dlog"
+
+ "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/btrfsprogs/btrfsinspect"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsutil"
+ "git.lukeshu.com/btrfs-progs-ng/lib/diskio"
+)
+
+func lostAndFoundNodes(ctx context.Context, fs _FS, nodeScanResults btrfsinspect.ScanDevicesResult) (map[btrfsvol.LogicalAddr]struct{}, error) {
+ lastPct := -1
+ total := countNodes(nodeScanResults)
+ progress := func(done int) {
+ pct := int(100 * float64(done) / float64(total))
+ if pct != lastPct || done == total {
+ dlog.Infof(ctx, "... %v%% (%v/%v)",
+ pct, done, total)
+ lastPct = pct
+ }
+ }
+
+ 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 {
+ 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
+ },
+ },
+ Err: func(err *btrfsutil.WalkError) {
+ // do nothing
+ if !errors.Is(err, btrfstree.ErrNotANode) && !strings.Contains(err.Error(), "read: could not map logical address") {
+ dlog.Errorf(ctx, "dbg walk err: %v", err)
+ }
+ },
+ })
+
+ orphanedNodes := make(map[btrfsvol.LogicalAddr]int)
+ for _, devResults := range nodeScanResults {
+ for laddr := range devResults.FoundNodes {
+ if _, attached := attachedNodes[laddr]; !attached {
+ orphanedNodes[laddr] = 0
+ }
+ }
+ }
+ dlog.Infof(ctx,
+ "... (finished processing %v attached nodes, proceeding to process %v lost nodes, for a total of %v)",
+ 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.
+ orphanedRoots := make(map[btrfsvol.LogicalAddr]struct{}, len(orphanedNodes))
+ for node := range orphanedNodes {
+ orphanedRoots[node] = struct{}{}
+ }
+ done := len(attachedNodes)
+ for potentialRoot := range orphanedRoots {
+ done++
+ progress(done)
+ if orphanedNodes[potentialRoot] > 1 {
+ continue
+ }
+ walkCtx, cancel := context.WithCancel(ctx)
+ walkFromNode(walkCtx, fs, potentialRoot,
+ func(err *btrfstree.TreeError) {
+ // do nothing
+ },
+ btrfstree.TreeWalkHandler{
+ PreNode: func(path btrfstree.TreePath) error {
+ nodeAddr := path.Node(-1).ToNodeAddr
+ if nodeAddr != potentialRoot {
+ delete(orphanedRoots, nodeAddr)
+ }
+ visitCnt := orphanedNodes[nodeAddr] + 1
+ orphanedNodes[nodeAddr] = visitCnt
+ if visitCnt > 1 {
+ cancel()
+ }
+ return nil
+ },
+ },
+ )
+ }
+
+ return orphanedRoots, nil
+}