summaryrefslogtreecommitdiff
path: root/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/scanforextents/csums.go')
-rw-r--r--lib/btrfsprogs/btrfsinspect/scanforextents/csums.go316
1 files changed, 0 insertions, 316 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go b/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
deleted file mode 100644
index 0fb4818..0000000
--- a/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
-//
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package scanforextents
-
-import (
- "context"
- "encoding/gob"
- "io"
- "math"
- "os"
- "runtime"
- "strings"
- "sync"
-
- "github.com/datawire/dlib/dgroup"
- "github.com/datawire/dlib/dlog"
-
- "git.lukeshu.com/btrfs-progs-ng/lib/btrfs"
- "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem"
- "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum"
- "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/diskio"
-)
-
-// ShortSum //////////////////////////////////////////////////////////
-
-type ShortSum string
-
-// SumRun ////////////////////////////////////////////////////////////
-
-type SumRun[Addr btrfsvol.IntAddr[Addr]] struct {
- // How big a ShortSum is in this Run.
- ChecksumSize int
- // Base address where this run starts.
- Addr Addr
- // All of the ShortSums in this run, concatenated together.
- //
- // This is a 'string' rather than a 'ShortSum' to make it hard
- // to accidentally use it as a single sum.
- Sums string
-}
-
-func (run SumRun[Addr]) NumSums() int {
- return len(run.Sums) / run.ChecksumSize
-}
-
-func (run SumRun[Addr]) Size() btrfsvol.AddrDelta {
- return btrfsvol.AddrDelta(run.NumSums()) * btrfsitem.CSumBlockSize
-}
-
-// Get implements diskio.Sequence[int, ShortSum]
-func (run SumRun[Addr]) Get(sumIdx int64) (ShortSum, error) {
- if sumIdx < 0 || int(sumIdx) >= run.NumSums() {
- return "", io.EOF
- }
- off := int(sumIdx) * run.ChecksumSize
- return ShortSum(run.Sums[off : off+run.ChecksumSize]), nil
-}
-
-func (run SumRun[Addr]) SumForAddr(addr Addr) (ShortSum, bool) {
- if addr < run.Addr || addr >= run.Addr.Add(run.Size()) {
- return "", false
- }
- off := int((addr-run.Addr)/btrfsitem.CSumBlockSize) * run.ChecksumSize
- return ShortSum(run.Sums[off : off+run.ChecksumSize]), true
-}
-
-func (run SumRun[Addr]) Walk(ctx context.Context, fn func(Addr, ShortSum) error) error {
- for addr, off := run.Addr, 0; off < len(run.Sums); addr, off = addr+btrfsitem.CSumBlockSize, off+run.ChecksumSize {
- if err := ctx.Err(); err != nil {
- return err
- }
- if err := fn(addr, ShortSum(run.Sums[off:off+run.ChecksumSize])); err != nil {
- return err
- }
- }
- return nil
-}
-
-// SumRunWithGaps ////////////////////////////////////////////////////
-
-type SumRunWithGaps[Addr btrfsvol.IntAddr[Addr]] struct {
- Addr Addr
- Size btrfsvol.AddrDelta
- Runs []SumRun[Addr]
-}
-
-func (sg SumRunWithGaps[Addr]) NumSums() int {
- return int(sg.Size / btrfsitem.CSumBlockSize)
-}
-
-func (sg SumRunWithGaps[Addr]) PctFull() float64 {
- total := sg.NumSums()
- var full int
- for _, run := range sg.Runs {
- full += run.NumSums()
- }
- return float64(full) / float64(total)
-}
-
-func (sg SumRunWithGaps[Addr]) SumForAddr(addr Addr) (ShortSum, error) {
- if addr < sg.Addr || addr >= sg.Addr.Add(sg.Size) {
- return "", io.EOF
- }
- for _, run := range sg.Runs {
- if run.Addr > addr {
- return "", diskio.ErrWildcard
- }
- if run.Addr.Add(run.Size()) <= addr {
- continue
- }
- off := int((addr-run.Addr)/btrfsitem.CSumBlockSize) * run.ChecksumSize
- return ShortSum(run.Sums[off : off+run.ChecksumSize]), nil
- }
- return "", diskio.ErrWildcard
-}
-
-// Get implements diskio.Sequence[int, ShortSum]
-func (sg SumRunWithGaps[Addr]) Get(sumIdx int64) (ShortSum, error) {
- addr := sg.Addr.Add(btrfsvol.AddrDelta(sumIdx) * btrfsitem.CSumBlockSize)
- return sg.SumForAddr(addr)
-}
-
-// AllSums ///////////////////////////////////////////////////////////
-
-type AllSums struct {
- Logical []SumRun[btrfsvol.LogicalAddr]
- Physical map[btrfsvol.DeviceID]SumRun[btrfsvol.PhysicalAddr]
-}
-
-func (as AllSums) SumForPAddr(paddr btrfsvol.QualifiedPhysicalAddr) (ShortSum, bool) {
- run, ok := as.Physical[paddr.Dev]
- if !ok {
- return "", false
- }
- return run.SumForAddr(paddr.Addr)
-}
-
-func (as AllSums) RunForLAddr(laddr btrfsvol.LogicalAddr) (SumRun[btrfsvol.LogicalAddr], btrfsvol.LogicalAddr, bool) {
- for _, run := range as.Logical {
- if run.Addr > laddr {
- return SumRun[btrfsvol.LogicalAddr]{}, run.Addr, false
- }
- if run.Addr.Add(run.Size()) <= laddr {
- continue
- }
- return run, 0, true
- }
- return SumRun[btrfsvol.LogicalAddr]{}, math.MaxInt64, false
-}
-
-func (as AllSums) SumForLAddr(laddr btrfsvol.LogicalAddr) (ShortSum, bool) {
- run, _, ok := as.RunForLAddr(laddr)
- if !ok {
- return "", false
- }
- return run.SumForAddr(laddr)
-}
-
-func (as AllSums) WalkLogical(ctx context.Context, fn func(btrfsvol.LogicalAddr, ShortSum) error) error {
- for _, run := range as.Logical {
- if err := run.Walk(ctx, fn); err != nil {
- return err
- }
- }
- return nil
-}
-
-// Read/Write AllSums ////////////////////////////////////////////////
-
-func ReadAllSums(filename string) (AllSums, error) {
- fh, err := os.Open(filename)
- if err != nil {
- return AllSums{}, err
- }
- defer fh.Close()
- var val AllSums
- if err := gob.NewDecoder(fh).Decode(&val); err != nil {
- return AllSums{}, err
- }
- return val, nil
-}
-
-func WriteAllSums(w io.Writer, sums AllSums) error {
- return gob.NewEncoder(w).Encode(sums)
-}
-
-func SumEverything(ctx context.Context, fs *btrfs.FS) (AllSums, error) {
- var ret AllSums
-
- // ChecksumSize
- var alg btrfssum.CSumType
- var csumSize int
- if err := func() error {
- sb, err := fs.Superblock()
- if err != nil {
- return err
- }
- alg = sb.ChecksumType
- csumSize = alg.Size()
- return nil
- }(); err != nil {
- return ret, err
- }
-
- // Logical
- dlog.Info(ctx, "Walking CSUM_TREE...")
- func() {
- var curAddr btrfsvol.LogicalAddr
- var curSums strings.Builder
- btrfsutil.NewBrokenTrees(ctx, fs).TreeWalk(ctx, btrfs.CSUM_TREE_OBJECTID,
- func(err *btrfs.TreeError) {
- dlog.Error(ctx, err)
- },
- btrfs.TreeWalkHandler{
- Item: func(path btrfs.TreePath, item btrfs.Item) error {
- if item.Key.ItemType != btrfsitem.EXTENT_CSUM_KEY {
- return nil
- }
- body := item.Body.(btrfsitem.ExtentCSum)
-
- for i, sum := range body.Sums {
- laddr := btrfsvol.LogicalAddr(item.Key.Offset) + (btrfsvol.LogicalAddr(i) * btrfsitem.CSumBlockSize)
- if laddr != curAddr+(btrfsvol.LogicalAddr(curSums.Len()/csumSize)*btrfsitem.CSumBlockSize) {
- if curSums.Len() > 0 {
- ret.Logical = append(ret.Logical, SumRun[btrfsvol.LogicalAddr]{
- ChecksumSize: csumSize,
- Addr: curAddr,
- Sums: curSums.String(),
- })
- }
- curAddr = laddr
- curSums.Reset()
- }
- curSums.Write(sum[:csumSize])
- }
- return nil
- },
- },
- )
- if curSums.Len() > 0 {
- ret.Logical = append(ret.Logical, SumRun[btrfsvol.LogicalAddr]{
- ChecksumSize: csumSize,
- Addr: curAddr,
- Sums: curSums.String(),
- })
- }
- }()
- if err := ctx.Err(); err != nil {
- return ret, err
- }
- dlog.Info(ctx, "... done walking")
- runtime.GC()
- dlog.Info(ctx, "... GC'd")
-
- // Physical
- dlog.Info(ctx, "Summing devices...")
- if err := func() error {
- devs := fs.LV.PhysicalVolumes()
-
- var mu sync.Mutex
- ret.Physical = make(map[btrfsvol.DeviceID]SumRun[btrfsvol.PhysicalAddr], len(devs))
-
- grp := dgroup.NewGroup(ctx, dgroup.GroupConfig{})
- for devID, dev := range devs {
- devID, dev := devID, dev
- grp.Go(dev.Name(), func(ctx context.Context) error {
- devSize := dev.Size()
- numSums := int(devSize / btrfsitem.CSumBlockSize)
- sums := make([]byte, numSums*csumSize)
- lastPct := -1
- progress := func(curSum int) {
- pct := int(100 * float64(curSum) / float64(numSums))
- if pct != lastPct || curSum == numSums {
- dlog.Infof(ctx, "... dev[%q] summed %v%%",
- dev.Name(), pct)
- lastPct = pct
- }
- }
- for i := 0; i < numSums; i++ {
- if err := ctx.Err(); err != nil {
- return err
- }
- progress(i)
- sum, err := ChecksumPhysical(dev, alg, btrfsvol.PhysicalAddr(i*btrfsitem.CSumBlockSize))
- if err != nil {
- return err
- }
- copy(sums[i*csumSize:], sum[:csumSize])
- }
- progress(numSums)
- sumsStr := string(sums)
- mu.Lock()
- ret.Physical[devID] = SumRun[btrfsvol.PhysicalAddr]{
- ChecksumSize: csumSize,
- Addr: 0,
- Sums: sumsStr,
- }
- mu.Unlock()
- return nil
- })
- }
- return grp.Wait()
- }(); err != nil {
- return ret, err
- }
- dlog.Info(ctx, "... done summing devices")
- runtime.GC()
- dlog.Info(ctx, "... GC'd")
-
- // Return
- return ret, nil
-}