summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-07-13 23:45:14 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-07-14 00:50:23 -0600
commit913acf193bfac666cec68e8c3fb13829a7a0c794 (patch)
tree9e26b25fa2ed2b966f256b0580c17c9291c29ba6 /cmd
parentb8c5940165399f9dc404c912aa455822347bb367 (diff)
implement scan-for-nodes command
Diffstat (limited to 'cmd')
-rw-r--r--cmd/btrfs-rec/inspect_scanfornodes.go70
1 files changed, 70 insertions, 0 deletions
diff --git a/cmd/btrfs-rec/inspect_scanfornodes.go b/cmd/btrfs-rec/inspect_scanfornodes.go
new file mode 100644
index 0000000..3eee46c
--- /dev/null
+++ b/cmd/btrfs-rec/inspect_scanfornodes.go
@@ -0,0 +1,70 @@
+// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "os"
+ "sync"
+
+ "github.com/datawire/dlib/dgroup"
+ "github.com/datawire/dlib/dlog"
+ "github.com/datawire/ocibuild/pkg/cliutil"
+ "github.com/spf13/cobra"
+
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsinspect"
+)
+
+func init() {
+ inspectors = append(inspectors, subcommand{
+ Command: cobra.Command{
+ Use: "scan-for-nodes",
+ Short: "Scan devices for (potentially lost) nodes",
+ Long: "" +
+ "The found information is printed as JSON on stdout.\n" +
+ "\n" +
+ "This information is mostly useful for rebuilding a broken\n" +
+ "chunk/dev-extent/blockgroup trees, but can also have some\n" +
+ "minimal utility in repairing other trees.\n" +
+ "\n" +
+ "This is very similar the initial scan done by\n" +
+ "`btrfs rescue chunk-recover`. Like `btrfs rescue chunk-recover`,\n" +
+ "this is likely probably slow because it reads the entirety of\n" +
+ "each device.",
+ Args: cliutil.WrapPositionalArgs(cobra.NoArgs),
+ },
+ RunE: func(fs *btrfs.FS, cmd *cobra.Command, _ []string) error {
+ ctx := cmd.Context()
+
+ var resultsMu sync.Mutex
+ results := make(map[btrfsvol.DeviceID]btrfsinspect.ScanOneDevResult)
+ grp := dgroup.NewGroup(ctx, dgroup.GroupConfig{})
+ for _, dev := range fs.LV.PhysicalVolumes() {
+ grp.Go(dev.Name(), func(ctx context.Context) error {
+ superblock, err := dev.Superblock()
+ if err != nil {
+ return err
+ }
+ dlog.Infof(ctx, "dev[%q] Scanning for unreachable nodes...", dev.Name())
+ devResult, err := btrfsinspect.ScanOneDev(ctx, dev, *superblock)
+ dlog.Infof(ctx, "dev[%q] Finished scanning", dev.Name())
+ resultsMu.Lock()
+ results[superblock.DevItem.DevID] = devResult
+ resultsMu.Unlock()
+ return err
+ })
+ }
+ if err := grp.Wait(); err != nil {
+ return err
+ }
+
+ dlog.Info(ctx, "Serializing results...")
+ return json.NewEncoder(os.Stdout).Encode(results)
+ },
+ })
+}