From 3acca04bb629e0f898f022fbbcaad78815aaaee3 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 14 Jul 2022 01:30:19 -0600 Subject: have rebuilding the mappings use the scan-for-nodes result --- cmd/btrfs-rec/inspect_rebuildmappings.go | 80 ++++++++++++++++++++++++++++++++ cmd/btrfs-rec/inspect_recoverchunks.go | 75 ------------------------------ cmd/btrfs-rec/inspect_scanfornodes.go | 5 +- cmd/btrfs-rec/main.go | 6 +-- 4 files changed, 85 insertions(+), 81 deletions(-) create mode 100644 cmd/btrfs-rec/inspect_rebuildmappings.go delete mode 100644 cmd/btrfs-rec/inspect_recoverchunks.go (limited to 'cmd/btrfs-rec') diff --git a/cmd/btrfs-rec/inspect_rebuildmappings.go b/cmd/btrfs-rec/inspect_rebuildmappings.go new file mode 100644 index 0000000..c32bf53 --- /dev/null +++ b/cmd/btrfs-rec/inspect_rebuildmappings.go @@ -0,0 +1,80 @@ +// Copyright (C) 2022 Luke Shumaker +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package main + +import ( + "encoding/json" + "fmt" + "io" + "os" + + "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" + "git.lukeshu.com/btrfs-progs-ng/lib/maps" +) + +func init() { + inspectors = append(inspectors, subcommand{ + Command: cobra.Command{ + Use: "rebuild-mappings SCAN_RESULT.json", + Short: "Rebuild broken chunk/dev-extent/blockgroup trees", + Long: "" + + "The rebuilt information is printed as JSON on stdout, and can\n" + + "be loaded by the --mappings flag.\n" + + "\n" + + "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)), + }, + RunE: func(fs *btrfs.FS, cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + scanResultsBytes, err := os.ReadFile(args[0]) + if err != nil { + return err + } + var scanResults map[btrfsvol.DeviceID]btrfsinspect.ScanOneDevResult + if err := json.Unmarshal(scanResultsBytes, &scanResults); err != nil { + return err + } + + devices := fs.LV.PhysicalVolumes() + for _, devID := range maps.SortedKeys(scanResults) { + dev, ok := devices[devID] + if !ok { + return fmt.Errorf("device ID %v mentioned in %q is not part of the filesystem", + devID, args[0]) + } + dlog.Infof(ctx, "Rebuilding mappings from results on device %v...", + dev.Name()) + scanResults[devID].AddToLV(ctx, fs, dev) + } + + dlog.Infof(ctx, "Writing reconstructed mappings to stdout...") + mappings := fs.LV.Mappings() + _, _ = io.WriteString(os.Stdout, "[\n") + for i, mapping := range mappings { + suffix := "," + if i == len(mappings)-1 { + suffix = "" + } + bs, err := json.Marshal(mapping) + if err != nil { + return err + } + fmt.Printf(" %s%s\n", bs, suffix) + } + _, _ = io.WriteString(os.Stdout, "]\n") + return nil + }, + }) +} diff --git a/cmd/btrfs-rec/inspect_recoverchunks.go b/cmd/btrfs-rec/inspect_recoverchunks.go deleted file mode 100644 index 4314b66..0000000 --- a/cmd/btrfs-rec/inspect_recoverchunks.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2022 Luke Shumaker -// -// SPDX-License-Identifier: GPL-2.0-or-later - -package main - -import ( - "encoding/json" - "fmt" - "io" - "os" - - "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/btrfsprogs/btrfsinspect" -) - -func init() { - inspectors = append(inspectors, subcommand{ - Command: cobra.Command{ - Use: "recover-chunks", - Short: "Rebuild broken chunk/dev-extent/blockgroup trees", - Long: "" + - "The rebuilt information is printed as JSON on stdout, and can\n" + - "be loaded by the --mappings flag.\n" + - "\n" + - "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.NoArgs), - }, - RunE: func(fs *btrfs.FS, cmd *cobra.Command, _ []string) error { - ctx := cmd.Context() - - dlog.Info(ctx, "Reading superblock...") - superblock, err := fs.Superblock() - if err != nil { - return err - } - - for _, dev := range fs.LV.PhysicalVolumes() { - dlog.Infof(ctx, "dev[%q] Scanning for unreachable nodes...", dev.Name()) - devResult, err := btrfsinspect.ScanOneDev(ctx, dev, *superblock) - if err != nil { - return err - } - - dlog.Infof(ctx, "dev[%q] Re-inserting lost+found mappings...", dev.Name()) - devResult.AddToLV(ctx, fs, dev) - } - - dlog.Infof(ctx, "Writing reconstructed mappings to stdout...") - - mappings := fs.LV.Mappings() - _, _ = io.WriteString(os.Stdout, "{\n \"Mappings\": [\n") - for i, mapping := range mappings { - suffix := "," - if i == len(mappings)-1 { - suffix = "" - } - bs, err := json.Marshal(mapping) - if err != nil { - return err - } - fmt.Printf(" %s%s\n", bs, suffix) - } - _, _ = io.WriteString(os.Stdout, " ]\n}\n") - return nil - }, - }) -} diff --git a/cmd/btrfs-rec/inspect_scanfornodes.go b/cmd/btrfs-rec/inspect_scanfornodes.go index 3eee46c..9dbc3a5 100644 --- a/cmd/btrfs-rec/inspect_scanfornodes.go +++ b/cmd/btrfs-rec/inspect_scanfornodes.go @@ -26,7 +26,8 @@ func init() { Use: "scan-for-nodes", Short: "Scan devices for (potentially lost) nodes", Long: "" + - "The found information is printed as JSON on stdout.\n" + + "The found information is printed as JSON on stdout, and can\n" + + "be read by `btrfs-rec inspect rebuild-mappings`.\n" + "\n" + "This information is mostly useful for rebuilding a broken\n" + "chunk/dev-extent/blockgroup trees, but can also have some\n" + @@ -63,7 +64,7 @@ func init() { return err } - dlog.Info(ctx, "Serializing results...") + dlog.Info(ctx, "Writing scan results to stdout...") return json.NewEncoder(os.Stdout).Encode(results) }, }) diff --git a/cmd/btrfs-rec/main.go b/cmd/btrfs-rec/main.go index b17c8ec..c808237 100644 --- a/cmd/btrfs-rec/main.go +++ b/cmd/btrfs-rec/main.go @@ -141,13 +141,11 @@ func main() { if err != nil { return err } - var mappingsJSON struct { - Mappings []btrfsvol.Mapping - } + var mappingsJSON []btrfsvol.Mapping if err := json.Unmarshal(bs, &mappingsJSON); err != nil { return err } - for _, mapping := range mappingsJSON.Mappings { + for _, mapping := range mappingsJSON { if err := fs.LV.AddMapping(mapping); err != nil { return err } -- cgit v1.2.3-2-g168b