summaryrefslogtreecommitdiff
path: root/cmd/btrfs-rec
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/btrfs-rec')
-rw-r--r--cmd/btrfs-rec/inspect_lstrees.go2
-rw-r--r--cmd/btrfs-rec/inspect_rebuildmappings.go71
-rw-r--r--cmd/btrfs-rec/inspect_scandevices.go69
-rw-r--r--cmd/btrfs-rec/util.go25
4 files changed, 93 insertions, 74 deletions
diff --git a/cmd/btrfs-rec/inspect_lstrees.go b/cmd/btrfs-rec/inspect_lstrees.go
index be72860..1ff7671 100644
--- a/cmd/btrfs-rec/inspect_lstrees.go
+++ b/cmd/btrfs-rec/inspect_lstrees.go
@@ -114,7 +114,7 @@ func init() {
return nil
}),
}
- cmd.Flags().StringVar(&scandevicesFilename, "scandevices", "", "Output of 'scandevices' to use for a lost+found tree")
+ cmd.Flags().StringVar(&scandevicesFilename, "scandevices", "", "Output of 'btrfs-recs inspect rebuild-mappings scan' to use for a lost+found tree")
noError(cmd.MarkFlagFilename("scandevices"))
inspectors.AddCommand(cmd)
diff --git a/cmd/btrfs-rec/inspect_rebuildmappings.go b/cmd/btrfs-rec/inspect_rebuildmappings.go
index 81660b0..55e3408 100644
--- a/cmd/btrfs-rec/inspect_rebuildmappings.go
+++ b/cmd/btrfs-rec/inspect_rebuildmappings.go
@@ -17,8 +17,8 @@ import (
)
func init() {
- inspectors.AddCommand(&cobra.Command{
- Use: "rebuild-mappings SCAN_RESULT.json",
+ cmd := &cobra.Command{
+ Use: "rebuild-mappings",
Short: "Rebuild broken chunk/dev-extent/blockgroup trees",
Long: "" +
"The rebuilt information is printed as JSON on stdout, and can\n" +
@@ -27,8 +27,69 @@ func init() {
"This is very similar to `btrfs rescue chunk-recover`, but (1)\n" +
"does a better job, (2) is less buggy, and (3) doesn't actually\n" +
"write the info back to the filesystem; instead writing it\n" +
- "out-of-band to stdout.",
- Args: cliutil.WrapPositionalArgs(cobra.ExactArgs(1)),
+ "out-of-band to stdout.\n" +
+ "\n" +
+ "The I/O and the CPU parts of this can be split up as:\n" +
+ "\n" +
+ "\tbtrfs-rec inspect rebuild-mappings scan > SCAN.json # read\n" +
+ "\tbtrfs-rec inspect rebuild-mappings process SCAN.json # CPU\n",
+ Args: cliutil.WrapPositionalArgs(cobra.NoArgs),
+ RunE: runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error {
+ ctx := cmd.Context()
+
+ scanResults, err := rebuildmappings.ScanDevices(ctx, fs)
+ if err != nil {
+ return err
+ }
+
+ if err := rebuildmappings.RebuildMappings(ctx, fs, scanResults); err != nil {
+ return err
+ }
+
+ dlog.Infof(ctx, "Writing reconstructed mappings to stdout...")
+ if err := writeJSONFile(os.Stdout, fs.LV.Mappings(), lowmemjson.ReEncoderConfig{
+ Indent: "\t",
+ ForceTrailingNewlines: true,
+ CompactIfUnder: 120, //nolint:gomnd // This is what looks nice.
+ }); err != nil {
+ return err
+ }
+ dlog.Info(ctx, "... done writing")
+
+ return nil
+ }),
+ }
+
+ cmd.AddCommand(&cobra.Command{
+ Use: "scan",
+ Short: "Read from the filesystem all data nescessary to rebuild the mappings",
+ Args: cliutil.WrapPositionalArgs(cobra.NoArgs),
+ RunE: runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, _ []string) (err error) {
+ ctx := cmd.Context()
+
+ scanResults, err := rebuildmappings.ScanDevices(ctx, fs)
+ if err != nil {
+ return err
+ }
+
+ dlog.Info(ctx, "Writing scan results to stdout...")
+ if err := writeJSONFile(os.Stdout, scanResults, lowmemjson.ReEncoderConfig{
+ Indent: "\t",
+ ForceTrailingNewlines: true,
+ CompactIfUnder: 16, //nolint:gomnd // This is what looks nice.
+ }); err != nil {
+ return err
+ }
+ dlog.Info(ctx, "... done writing")
+
+ return nil
+ }),
+ })
+
+ cmd.AddCommand(&cobra.Command{
+ Use: "process",
+ Short: "Rebuild the mappings based on previously read data",
+ Args: cliutil.WrapPositionalArgs(cobra.ExactArgs(1)),
RunE: runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
@@ -56,4 +117,6 @@ func init() {
return nil
}),
})
+
+ inspectors.AddCommand(cmd)
}
diff --git a/cmd/btrfs-rec/inspect_scandevices.go b/cmd/btrfs-rec/inspect_scandevices.go
deleted file mode 100644
index 4172c7c..0000000
--- a/cmd/btrfs-rec/inspect_scandevices.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
-//
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package main
-
-import (
- "context"
- "os"
-
- "git.lukeshu.com/go/lowmemjson"
- "github.com/datawire/dlib/dlog"
- "github.com/datawire/ocibuild/pkg/cliutil"
- "github.com/spf13/cobra"
-
- "git.lukeshu.com/btrfs-progs-ng/cmd/btrfs-rec/inspect/rebuildmappings"
- "git.lukeshu.com/btrfs-progs-ng/lib/btrfs"
- "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"
-)
-
-func init() {
- inspectors.AddCommand(&cobra.Command{
- Use: "scandevices",
- Args: cliutil.WrapPositionalArgs(cobra.NoArgs),
- RunE: runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, _ []string) (err error) {
- ctx := cmd.Context()
-
- results, err := rebuildmappings.ScanDevices(ctx, fs)
- if err != nil {
- return err
- }
-
- dlog.Info(ctx, "Writing scan results to stdout...")
- if err := writeJSONFile(os.Stdout, results, lowmemjson.ReEncoderConfig{
- Indent: "\t",
- ForceTrailingNewlines: true,
- CompactIfUnder: 16, //nolint:gomnd // This is what looks nice.
- }); err != nil {
- return err
- }
- dlog.Info(ctx, "... done writing")
-
- return nil
- }),
- })
-}
-
-func readNodeList(ctx context.Context, filename string) ([]btrfsvol.LogicalAddr, error) {
- if filename == "" {
- return nil, nil
- }
- results, err := readJSONFile[rebuildmappings.ScanDevicesResult](ctx, filename)
- if err != nil {
- return nil, err
- }
- var cnt int
- for _, devResults := range results {
- cnt += len(devResults.FoundNodes)
- }
- set := make(containers.Set[btrfsvol.LogicalAddr], cnt)
- for _, devResults := range results {
- for laddr := range devResults.FoundNodes {
- set.Insert(laddr)
- }
- }
- return maps.SortedKeys(set), nil
-}
diff --git a/cmd/btrfs-rec/util.go b/cmd/btrfs-rec/util.go
index 3d751a6..2e4bb84 100644
--- a/cmd/btrfs-rec/util.go
+++ b/cmd/btrfs-rec/util.go
@@ -13,6 +13,10 @@ import (
"git.lukeshu.com/go/lowmemjson"
"github.com/datawire/dlib/dlog"
+ "git.lukeshu.com/btrfs-progs-ng/cmd/btrfs-rec/inspect/rebuildmappings"
+ "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/streamio"
)
@@ -47,3 +51,24 @@ func writeJSONFile(w io.Writer, obj any, cfg lowmemjson.ReEncoderConfig) (err er
}()
return lowmemjson.NewEncoder(lowmemjson.NewReEncoder(buffer, cfg)).Encode(obj)
}
+
+func readNodeList(ctx context.Context, filename string) ([]btrfsvol.LogicalAddr, error) {
+ if filename == "" {
+ return nil, nil
+ }
+ results, err := readJSONFile[rebuildmappings.ScanDevicesResult](ctx, filename)
+ if err != nil {
+ return nil, err
+ }
+ var cnt int
+ for _, devResults := range results {
+ cnt += len(devResults.FoundNodes)
+ }
+ set := make(containers.Set[btrfsvol.LogicalAddr], cnt)
+ for _, devResults := range results {
+ for laddr := range devResults.FoundNodes {
+ set.Insert(laddr)
+ }
+ }
+ return maps.SortedKeys(set), nil
+}