summaryrefslogtreecommitdiff
path: root/cmd/btrfs-rec/inspect_rebuildmappings.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/btrfs-rec/inspect_rebuildmappings.go')
-rw-r--r--cmd/btrfs-rec/inspect_rebuildmappings.go71
1 files changed, 67 insertions, 4 deletions
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)
}