From 913acf193bfac666cec68e8c3fb13829a7a0c794 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 13 Jul 2022 23:45:14 -0600 Subject: implement scan-for-nodes command --- cmd/btrfs-rec/inspect_scanfornodes.go | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 cmd/btrfs-rec/inspect_scanfornodes.go (limited to 'cmd/btrfs-rec/inspect_scanfornodes.go') 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 +// +// 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) + }, + }) +} -- cgit v1.2.3-2-g168b