diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-12-30 22:17:06 -0700 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-12-30 22:17:06 -0700 |
commit | 9971e38110d5f90d15c7b78f396f2638b3952a96 (patch) | |
tree | 28692225122d6d9c91d826801a4986d1c850744d /cmd/btrfs-rec | |
parent | bfe111c950da328b673ed4e3f8da0503bbd793d8 (diff) | |
parent | 3d0937e9ab148c074922b0d46ed33bdbcbef85b5 (diff) |
Merge branch 'lukeshu/log'
Diffstat (limited to 'cmd/btrfs-rec')
-rw-r--r-- | cmd/btrfs-rec/inspect_dumptrees.go | 7 | ||||
-rw-r--r-- | cmd/btrfs-rec/inspect_lsfiles.go | 29 | ||||
-rw-r--r-- | cmd/btrfs-rec/inspect_lstrees.go | 24 | ||||
-rw-r--r-- | cmd/btrfs-rec/inspect_rebuildmappings.go | 3 | ||||
-rw-r--r-- | cmd/btrfs-rec/inspect_rebuildnodes.go | 3 | ||||
-rw-r--r-- | cmd/btrfs-rec/inspect_scandevices.go | 14 | ||||
-rw-r--r-- | cmd/btrfs-rec/inspect_spewitems.go | 6 | ||||
-rw-r--r-- | cmd/btrfs-rec/main.go | 37 | ||||
-rw-r--r-- | cmd/btrfs-rec/util.go | 83 |
9 files changed, 129 insertions, 77 deletions
diff --git a/cmd/btrfs-rec/inspect_dumptrees.go b/cmd/btrfs-rec/inspect_dumptrees.go index 4abeaba..610f502 100644 --- a/cmd/btrfs-rec/inspect_dumptrees.go +++ b/cmd/btrfs-rec/inspect_dumptrees.go @@ -5,7 +5,6 @@ package main import ( - "fmt" "os" "github.com/datawire/ocibuild/pkg/cliutil" @@ -13,6 +12,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsinspect" + "git.lukeshu.com/btrfs-progs-ng/lib/textui" ) func init() { @@ -24,8 +24,9 @@ func init() { }, RunE: func(fs *btrfs.FS, cmd *cobra.Command, _ []string) error { const version = "5.18.1" - fmt.Printf("btrfs-progs v%v\n", version) - btrfsinspect.DumpTrees(cmd.Context(), os.Stdout, fs) + out := os.Stdout + textui.Fprintf(out, "btrfs-progs v%v\n", version) + btrfsinspect.DumpTrees(cmd.Context(), out, fs) return nil }, }) diff --git a/cmd/btrfs-rec/inspect_lsfiles.go b/cmd/btrfs-rec/inspect_lsfiles.go index 9267f77..502d91d 100644 --- a/cmd/btrfs-rec/inspect_lsfiles.go +++ b/cmd/btrfs-rec/inspect_lsfiles.go @@ -22,6 +22,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsutil" "git.lukeshu.com/btrfs-progs-ng/lib/maps" + "git.lukeshu.com/btrfs-progs-ng/lib/textui" ) func init() { @@ -32,20 +33,20 @@ func init() { Args: cliutil.WrapPositionalArgs(cobra.NoArgs), }, RunE: func(fs *btrfs.FS, cmd *cobra.Command, _ []string) (err error) { + out := bufio.NewWriter(os.Stdout) + defer out.Flush() defer func() { if r := derror.PanicToError(recover()); r != nil { - fmt.Printf("\n\n%+v\n", r) + textui.Fprintf(out, "\n\n%+v\n", r) err = fmt.Errorf("panicked") } }() ctx := cmd.Context() - out := bufio.NewWriter(os.Stdout) printSubvol(out, "", true, "/", &btrfs.Subvolume{ FS: btrfsutil.NewBrokenTrees(ctx, fs), TreeID: btrfsprim.FS_TREE_OBJECTID, }) - out.Flush() return nil }, @@ -64,7 +65,7 @@ func printText(out io.Writer, prefix string, isLast bool, name, text string) { if isLast { first, rest = tL, tS } - for i, line := range strings.Split(fmt.Sprintf("%q %s", name, text), "\n") { + for i, line := range strings.Split(textui.Sprintf("%q %s", name, text), "\n") { _, _ = io.WriteString(out, prefix) if i == 0 { _, _ = io.WriteString(out, first) @@ -79,13 +80,13 @@ func printText(out io.Writer, prefix string, isLast bool, name, text string) { func printSubvol(out io.Writer, prefix string, isLast bool, name string, subvol *btrfs.Subvolume) { rootInode, err := subvol.GetRootInode() if err != nil { - printText(out, prefix, isLast, name+"/", fmt.Sprintf("subvol_id=%v err=%v", + printText(out, prefix, isLast, name+"/", textui.Sprintf("subvol_id=%v err=%v", subvol.TreeID, fmtErr(err))) return } dir, err := subvol.LoadDir(rootInode) if err != nil { - printText(out, prefix, isLast, name+"/", fmt.Sprintf("subvol_id=%v err=%v", + printText(out, prefix, isLast, name+"/", textui.Sprintf("subvol_id=%v err=%v", subvol.TreeID, fmtErr(err))) return } @@ -93,7 +94,7 @@ func printSubvol(out io.Writer, prefix string, isLast bool, name string, subvol printDir(out, prefix, isLast, name, dir) return } - printText(out, prefix, isLast, name+"/", fmt.Sprintf("subvol_id=%v", subvol.TreeID)) + printText(out, prefix, isLast, name+"/", textui.Sprintf("subvol_id=%v", subvol.TreeID)) if isLast { prefix += tS } else { @@ -117,7 +118,7 @@ func fmtInode(inode btrfs.BareInode) string { } else { mode = inode.InodeItem.Mode } - ret := fmt.Sprintf("ino=%v mode=%v", inode.Inode, mode) + ret := textui.Sprintf("ino=%v mode=%v", inode.Inode, mode) if len(inode.Errs) > 0 { ret += " err=" + fmtErr(inode.Errs) } @@ -152,7 +153,7 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv case btrfsitem.INODE_ITEM_KEY: dir, err := subvol.LoadDir(entry.Location.ObjectID) if err != nil { - printText(out, prefix, isLast, name, fmt.Sprintf("%v err=%v", entry.Type, fmtErr(err))) + printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err))) return } printDir(out, prefix, isLast, name, dir) @@ -172,7 +173,7 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv } file, err := subvol.LoadFile(entry.Location.ObjectID) if err != nil { - printText(out, prefix, isLast, name, fmt.Sprintf("%v err=%v", entry.Type, fmtErr(err))) + printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err))) return } printSymlink(out, prefix, isLast, name, file) @@ -183,7 +184,7 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv } file, err := subvol.LoadFile(entry.Location.ObjectID) if err != nil { - printText(out, prefix, isLast, name, fmt.Sprintf("%v err=%v", entry.Type, fmtErr(err))) + printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err))) return } printFile(out, prefix, isLast, name, file) @@ -194,7 +195,7 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv } file, err := subvol.LoadFile(entry.Location.ObjectID) if err != nil { - printText(out, prefix, isLast, name, fmt.Sprintf("%v err=%v", entry.Type, fmtErr(err))) + printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err))) return } printSocket(out, prefix, isLast, name, file) @@ -205,7 +206,7 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv } file, err := subvol.LoadFile(entry.Location.ObjectID) if err != nil { - printText(out, prefix, isLast, name, fmt.Sprintf("%v err=%v", entry.Type, fmtErr(err))) + printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err))) return } printPipe(out, prefix, isLast, name, file) @@ -224,7 +225,7 @@ func printSymlink(out io.Writer, prefix string, isLast bool, name string, file * file.Errs = append(file.Errs, err) } } - printText(out, prefix, isLast, name, fmt.Sprintf( + printText(out, prefix, isLast, name, textui.Sprintf( "-> %q : %s", tgt, fmtInode(file.BareInode))) diff --git a/cmd/btrfs-rec/inspect_lstrees.go b/cmd/btrfs-rec/inspect_lstrees.go index 54c2074..e92c544 100644 --- a/cmd/btrfs-rec/inspect_lstrees.go +++ b/cmd/btrfs-rec/inspect_lstrees.go @@ -5,8 +5,6 @@ package main import ( - "encoding/json" - "fmt" "os" "strconv" "text/tabwriter" @@ -25,6 +23,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/diskio" "git.lukeshu.com/btrfs-progs-ng/lib/maps" "git.lukeshu.com/btrfs-progs-ng/lib/slices" + "git.lukeshu.com/btrfs-progs-ng/lib/textui" ) func init() { @@ -36,15 +35,14 @@ func init() { Args: cliutil.WrapPositionalArgs(cobra.NoArgs), }, RunE: func(fs *btrfs.FS, cmd *cobra.Command, _ []string) error { - var scanResults map[btrfsvol.DeviceID]btrfsinspect.ScanOneDeviceResult + ctx := cmd.Context() + var scanResults btrfsinspect.ScanDevicesResult if scandevicesFilename != "" { - scanResultsBytes, err := os.ReadFile(scandevicesFilename) + var err error + scanResults, err = readJSONFile[btrfsinspect.ScanDevicesResult](ctx, scandevicesFilename) if err != nil { return err } - if err := json.Unmarshal(scanResultsBytes, &scanResults); err != nil { - return err - } } var treeErrCnt int @@ -57,19 +55,19 @@ func init() { numWidth := len(strconv.Itoa(slices.Max(treeErrCnt, totalItems))) table := tabwriter.NewWriter(os.Stdout, 0, 8, 2, ' ', 0) - fmt.Fprintf(table, " errors\t% *s\n", numWidth, strconv.Itoa(treeErrCnt)) + textui.Fprintf(table, " errors\t% *s\n", numWidth, strconv.Itoa(treeErrCnt)) for _, typ := range maps.SortedKeys(treeItemCnt) { - fmt.Fprintf(table, " %v items\t% *s\n", typ, numWidth, strconv.Itoa(treeItemCnt[typ])) + textui.Fprintf(table, " %v items\t% *s\n", typ, numWidth, strconv.Itoa(treeItemCnt[typ])) } - fmt.Fprintf(table, " total items\t% *s\n", numWidth, strconv.Itoa(totalItems)) + textui.Fprintf(table, " total items\t% *s\n", numWidth, strconv.Itoa(totalItems)) table.Flush() } visitedNodes := make(containers.Set[btrfsvol.LogicalAddr]) - btrfsutil.WalkAllTrees(cmd.Context(), fs, btrfsutil.WalkAllTreesHandler{ + btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ PreTree: func(name string, treeID btrfsprim.ObjID) { treeErrCnt = 0 treeItemCnt = make(map[btrfsitem.Type]int) - fmt.Printf("tree id=%v name=%q\n", treeID, name) + textui.Fprintf(os.Stdout, "tree id=%v name=%q\n", treeID, name) }, Err: func(_ *btrfsutil.WalkError) { treeErrCnt++ @@ -98,7 +96,7 @@ func init() { if scandevicesFilename != "" { treeErrCnt = 0 treeItemCnt = make(map[btrfsitem.Type]int) - fmt.Printf("lost+found\n") + textui.Fprintf(os.Stdout, "lost+found\n") sb, _ := fs.Superblock() for _, devResults := range scanResults { for laddr := range devResults.FoundNodes { diff --git a/cmd/btrfs-rec/inspect_rebuildmappings.go b/cmd/btrfs-rec/inspect_rebuildmappings.go index 54535ec..da7d12e 100644 --- a/cmd/btrfs-rec/inspect_rebuildmappings.go +++ b/cmd/btrfs-rec/inspect_rebuildmappings.go @@ -15,6 +15,7 @@ import ( "github.com/spf13/cobra" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsinspect" "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsinspect/rebuildmappings" ) @@ -37,7 +38,7 @@ func init() { ctx := cmd.Context() dlog.Infof(ctx, "Reading %q...", args[0]) - scanResults, err := readScanResults(args[0]) + scanResults, err := readJSONFile[btrfsinspect.ScanDevicesResult](ctx, args[0]) if err != nil { return err } diff --git a/cmd/btrfs-rec/inspect_rebuildnodes.go b/cmd/btrfs-rec/inspect_rebuildnodes.go index 5f6d9b5..0f3d60e 100644 --- a/cmd/btrfs-rec/inspect_rebuildnodes.go +++ b/cmd/btrfs-rec/inspect_rebuildnodes.go @@ -17,6 +17,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "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/btrfsprogs/btrfsinspect/rebuildnodes" "git.lukeshu.com/btrfs-progs-ng/lib/containers" ) @@ -31,7 +32,7 @@ func init() { ctx := cmd.Context() dlog.Infof(ctx, "Reading %q...", args[0]) - nodeScanResults, err := readScanResults(args[0]) + nodeScanResults, err := readJSONFile[btrfsinspect.ScanDevicesResult](ctx, args[0]) if err != nil { return err } diff --git a/cmd/btrfs-rec/inspect_scandevices.go b/cmd/btrfs-rec/inspect_scandevices.go index 5c8b2b0..7235e45 100644 --- a/cmd/btrfs-rec/inspect_scandevices.go +++ b/cmd/btrfs-rec/inspect_scandevices.go @@ -58,17 +58,3 @@ func writeScanResults(w io.Writer, results btrfsinspect.ScanDevicesResult) (err CompactIfUnder: 16, }, results) } - -func readScanResults(filename string) (btrfsinspect.ScanDevicesResult, error) { - fh, err := os.Open(filename) - if err != nil { - return nil, err - } - var scanResults btrfsinspect.ScanDevicesResult - buf := bufio.NewReader(fh) - if err := lowmemjson.DecodeThenEOF(buf, &scanResults); err != nil { - return nil, err - } - _ = fh.Close() - return scanResults, nil -} diff --git a/cmd/btrfs-rec/inspect_spewitems.go b/cmd/btrfs-rec/inspect_spewitems.go index a4e8d69..8d71797 100644 --- a/cmd/btrfs-rec/inspect_spewitems.go +++ b/cmd/btrfs-rec/inspect_spewitems.go @@ -5,7 +5,6 @@ package main import ( - "fmt" "os" "github.com/datawire/dlib/dlog" @@ -16,6 +15,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree" "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsutil" + "git.lukeshu.com/btrfs-progs-ng/lib/textui" ) func init() { @@ -37,13 +37,13 @@ func init() { }, TreeWalkHandler: btrfstree.TreeWalkHandler{ Item: func(path btrfstree.TreePath, item btrfstree.Item) error { - fmt.Printf("%s = ", path) + textui.Fprintf(os.Stdout, "%s = ", path) spew.Dump(item) os.Stdout.WriteString("\n") return nil }, BadItem: func(path btrfstree.TreePath, item btrfstree.Item) error { - fmt.Printf("%s = ", path) + textui.Fprintf(os.Stdout, "%s = ", path) spew.Dump(item) os.Stdout.WriteString("\n") return nil diff --git a/cmd/btrfs-rec/main.go b/cmd/btrfs-rec/main.go index c808237..13ae886 100644 --- a/cmd/btrfs-rec/main.go +++ b/cmd/btrfs-rec/main.go @@ -6,35 +6,19 @@ package main import ( "context" - "encoding/json" - "fmt" "os" "github.com/datawire/dlib/dgroup" "github.com/datawire/dlib/dlog" "github.com/datawire/ocibuild/pkg/cliutil" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/spf13/pflag" "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/btrfsutil" + "git.lukeshu.com/btrfs-progs-ng/lib/textui" ) -type logLevelFlag struct { - logrus.Level -} - -func (lvl *logLevelFlag) Type() string { return "loglevel" } -func (lvl *logLevelFlag) Set(str string) error { - var err error - lvl.Level, err = logrus.ParseLevel(str) - return err -} - -var _ pflag.Value = (*logLevelFlag)(nil) - type subcommand struct { cobra.Command RunE func(*btrfs.FS, *cobra.Command, []string) error @@ -43,8 +27,8 @@ type subcommand struct { var inspectors, repairers []subcommand func main() { - logLevelFlag := logLevelFlag{ - Level: logrus.InfoLevel, + logLevelFlag := textui.LogLevelFlag{ + Level: dlog.LogLevelInfo, } var pvsFlag []string var mappingsFlag string @@ -115,9 +99,10 @@ func main() { runE := child.RunE cmd.RunE = func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() - logger := logrus.New() - logger.SetLevel(logLevelFlag.Level) - ctx = dlog.WithLogger(ctx, dlog.WrapLogrus(logger)) + logger := textui.NewLogger(os.Stderr, logLevelFlag.Level) + ctx = dlog.WithLogger(ctx, logger) + ctx = dlog.WithField(ctx, "mem", new(textui.LiveMemUse)) + dlog.SetFallbackLogger(logger.WithField("btrfs-progs.THIS_IS_A_BUG", true)) grp := dgroup.NewGroup(ctx, dgroup.GroupConfig{ EnableSignalHandling: true, @@ -137,14 +122,10 @@ func main() { }() if mappingsFlag != "" { - bs, err := os.ReadFile(mappingsFlag) + mappingsJSON, err := readJSONFile[[]btrfsvol.Mapping](ctx, mappingsFlag) if err != nil { return err } - var mappingsJSON []btrfsvol.Mapping - if err := json.Unmarshal(bs, &mappingsJSON); err != nil { - return err - } for _, mapping := range mappingsJSON { if err := fs.LV.AddMapping(mapping); err != nil { return err @@ -162,7 +143,7 @@ func main() { } if err := argparser.ExecuteContext(context.Background()); err != nil { - fmt.Fprintf(os.Stderr, "%v: error: %v\n", argparser.CommandPath(), err) + textui.Fprintf(os.Stderr, "%v: error: %v\n", argparser.CommandPath(), err) os.Exit(1) } } diff --git a/cmd/btrfs-rec/util.go b/cmd/btrfs-rec/util.go new file mode 100644 index 0000000..adfe97e --- /dev/null +++ b/cmd/btrfs-rec/util.go @@ -0,0 +1,83 @@ +// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com> +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package main + +import ( + "bufio" + "context" + "io" + "os" + "time" + + "git.lukeshu.com/go/lowmemjson" + "github.com/datawire/dlib/dlog" + + "git.lukeshu.com/btrfs-progs-ng/lib/textui" +) + +type runeScanner struct { + progress textui.Portion[int64] + progressWriter *textui.Progress[textui.Portion[int64]] + unreadCnt uint64 + reader *bufio.Reader + closer io.Closer +} + +func newRuneScanner(ctx context.Context, fh *os.File) (*runeScanner, error) { + fi, err := fh.Stat() + if err != nil { + return nil, err + } + ret := &runeScanner{ + progress: textui.Portion[int64]{ + D: fi.Size(), + }, + progressWriter: textui.NewProgress[textui.Portion[int64]](ctx, dlog.LogLevelInfo, 1*time.Second), + reader: bufio.NewReader(fh), + closer: fh, + } + return ret, nil +} + +func (rs *runeScanner) ReadRune() (r rune, size int, err error) { + r, size, err = rs.reader.ReadRune() + if rs.unreadCnt > 0 { + rs.unreadCnt-- + } else { + rs.progress.N += int64(size) + rs.progressWriter.Set(rs.progress) + } + return +} + +func (rs *runeScanner) UnreadRune() error { + rs.unreadCnt++ + return rs.reader.UnreadRune() +} + +func (rs *runeScanner) Close() error { + rs.progressWriter.Done() + return rs.closer.Close() +} + +func readJSONFile[T any](ctx context.Context, filename string) (T, error) { + fh, err := os.Open(filename) + if err != nil { + var zero T + return zero, err + } + buf, err := newRuneScanner(dlog.WithField(ctx, "btrfs.read-json-file", filename), fh) + if err != nil { + var zero T + return zero, err + } + var ret T + if err := lowmemjson.DecodeThenEOF(buf, &ret); err != nil { + var zero T + return zero, err + } + _ = buf.Close() + return ret, nil +} |