summaryrefslogtreecommitdiff
path: root/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/btrfs-rec/inspect/rebuildtrees/scan.go')
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/scan.go77
1 files changed, 77 insertions, 0 deletions
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/scan.go b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
new file mode 100644
index 0000000..17949ab
--- /dev/null
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
@@ -0,0 +1,77 @@
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package rebuildnodes
+
+import (
+ "context"
+ "time"
+
+ "github.com/datawire/dlib/dlog"
+
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs"
+ "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/btrfsinspect/rebuildnodes/graph"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsinspect/rebuildnodes/keyio"
+ "git.lukeshu.com/btrfs-progs-ng/lib/containers"
+ "git.lukeshu.com/btrfs-progs-ng/lib/maps"
+ "git.lukeshu.com/btrfs-progs-ng/lib/textui"
+)
+
+func ScanDevices(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.ScanDevicesResult) (btrfstree.Superblock, graph.Graph, *keyio.Handle, error) {
+ dlog.Info(ctx, "Reading superblock...")
+ sb, err := fs.Superblock()
+ if err != nil {
+ return btrfstree.Superblock{}, graph.Graph{}, nil, err
+ }
+
+ dlog.Infof(ctx, "Reading node data from FS...")
+
+ var stats textui.Portion[int]
+ stats.D = countNodes(scanResults)
+ progressWriter := textui.NewProgress[textui.Portion[int]](
+ dlog.WithField(ctx, "btrfsinspect.rebuild-nodes.read.substep", "read-nodes"),
+ dlog.LogLevelInfo, textui.Tunable(1*time.Second))
+
+ nodeGraph := graph.New(*sb)
+ keyIO := keyio.NewHandle(fs, *sb)
+
+ progressWriter.Set(stats)
+ for _, devResults := range scanResults {
+ for _, laddr := range maps.SortedKeys(devResults.FoundNodes) {
+ if err := ctx.Err(); err != nil {
+ return btrfstree.Superblock{}, graph.Graph{}, nil, err
+ }
+ nodeRef, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, laddr, btrfstree.NodeExpectations{
+ LAddr: containers.Optional[btrfsvol.LogicalAddr]{OK: true, Val: laddr},
+ })
+ if err != nil {
+ btrfstree.FreeNodeRef(nodeRef)
+ return btrfstree.Superblock{}, graph.Graph{}, nil, err
+ }
+
+ nodeGraph.InsertNode(nodeRef)
+ keyIO.InsertNode(nodeRef)
+
+ btrfstree.FreeNodeRef(nodeRef)
+
+ stats.N++
+ progressWriter.Set(stats)
+ }
+ }
+ if stats.N != stats.D {
+ panic("should not happen")
+ }
+ progressWriter.Done()
+ dlog.Info(ctx, "... done reading node data")
+
+ if err := nodeGraph.FinalCheck(ctx, fs, *sb); err != nil {
+ return btrfstree.Superblock{}, graph.Graph{}, nil, err
+ }
+ keyIO.SetGraph(*nodeGraph)
+
+ return *sb, *nodeGraph, keyIO, nil
+}