summaryrefslogtreecommitdiff
path: root/lib/btrfs/btrfssum
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-03 19:06:22 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-04 19:31:54 -0700
commit47f66c084291040fb11212956df9033bf263a892 (patch)
tree988624ae776fa172ba1882c18a7039032af88c16 /lib/btrfs/btrfssum
parentab4296c75bfecbce1c2f68820ec43b82e524d617 (diff)
btrfssum: Split shortsum.go in to several files
Diffstat (limited to 'lib/btrfs/btrfssum')
-rw-r--r--lib/btrfs/btrfssum/csum.go2
-rw-r--r--lib/btrfs/btrfssum/shortsum.go201
-rw-r--r--lib/btrfs/btrfssum/sumrun.go58
-rw-r--r--lib/btrfs/btrfssum/sumrunwithgaps.go160
4 files changed, 220 insertions, 201 deletions
diff --git a/lib/btrfs/btrfssum/csum.go b/lib/btrfs/btrfssum/csum.go
index 6df9efd..f436e2c 100644
--- a/lib/btrfs/btrfssum/csum.go
+++ b/lib/btrfs/btrfssum/csum.go
@@ -14,6 +14,8 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/fmtutil"
)
+const BlockSize = 4 * 1024
+
type CSum [0x20]byte
var (
diff --git a/lib/btrfs/btrfssum/shortsum.go b/lib/btrfs/btrfssum/shortsum.go
index e3441ae..754a79d 100644
--- a/lib/btrfs/btrfssum/shortsum.go
+++ b/lib/btrfs/btrfssum/shortsum.go
@@ -5,22 +5,14 @@
package btrfssum
import (
- "context"
"fmt"
"io"
"math"
"strings"
"git.lukeshu.com/go/lowmemjson"
-
- "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
- "git.lukeshu.com/btrfs-progs-ng/lib/diskio"
)
-const BlockSize = 4 * 1024
-
-// ShortSum //////////////////////////////////////////////////////////
-
type ShortSum string
var (
@@ -105,196 +97,3 @@ func (sum *ShortSum) DecodeJSON(r io.RuneScanner) error {
*sum = ShortSum(out.String())
return nil
}
-
-// SumRun ////////////////////////////////////////////////////////////
-
-type SumRun[Addr btrfsvol.IntAddr[Addr]] struct {
- // How big a ShortSum is in this Run.
- ChecksumSize int `json:",omitempty"`
- // Base address where this run starts.
- Addr Addr `json:",omitempty"`
- // All of the ShortSums in this run, concatenated together.
- Sums ShortSum
-}
-
-func (run SumRun[Addr]) NumSums() int {
- return len(run.Sums) / run.ChecksumSize
-}
-
-func (run SumRun[Addr]) Size() btrfsvol.AddrDelta {
- return btrfsvol.AddrDelta(run.NumSums()) * BlockSize
-}
-
-// 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 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)/BlockSize) * run.ChecksumSize
- return 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+BlockSize, off+run.ChecksumSize {
- if err := ctx.Err(); err != nil {
- return err
- }
- if err := fn(addr, run.Sums[off:off+run.ChecksumSize]); err != nil {
- return err
- }
- }
- return nil
-}
-
-// SumRunWithGaps ////////////////////////////////////////////////////
-
-type SumRunWithGaps[Addr btrfsvol.IntAddr[Addr]] struct {
- // Store the start address and size, in order to facilitate
- // leading and trailing gaps.
- Addr Addr
- Size btrfsvol.AddrDelta
-
- Runs []SumRun[Addr]
-}
-
-var (
- _ lowmemjson.Encodable = SumRunWithGaps[btrfsvol.LogicalAddr]{}
- _ lowmemjson.Decodable = (*SumRunWithGaps[btrfsvol.LogicalAddr])(nil)
-)
-
-func (sg SumRunWithGaps[Addr]) NumSums() int {
- return int(sg.Size / BlockSize)
-}
-
-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]) RunForAddr(addr Addr) (SumRun[Addr], Addr, bool) {
- for _, run := range sg.Runs {
- if run.Addr > addr {
- return SumRun[Addr]{}, run.Addr, false
- }
- if run.Addr.Add(run.Size()) <= addr {
- continue
- }
- return run, 0, true
- }
- return SumRun[Addr]{}, math.MaxInt64, false
-}
-
-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)/BlockSize) * run.ChecksumSize
- return run.Sums[off : off+run.ChecksumSize], nil
- }
- return "", diskio.ErrWildcard
-}
-
-func (sg SumRunWithGaps[Addr]) Walk(ctx context.Context, fn func(Addr, ShortSum) error) error {
- for _, run := range sg.Runs {
- if err := run.Walk(ctx, fn); err != nil {
- return err
- }
- }
- return nil
-}
-
-// Get implements diskio.Sequence[int, ShortSum]
-func (sg SumRunWithGaps[Addr]) Get(sumIdx int64) (ShortSum, error) {
- addr := sg.Addr.Add(btrfsvol.AddrDelta(sumIdx) * BlockSize)
- return sg.SumForAddr(addr)
-}
-
-func (sg SumRunWithGaps[Addr]) EncodeJSON(w io.Writer) error {
- if _, err := fmt.Fprintf(w, `{"Addr":%d,"Size":%d,"Runs":[`, sg.Addr, sg.Size); err != nil {
- return err
- }
- cur := sg.Addr
- for i, run := range sg.Runs {
- if i > 0 {
- if _, err := w.Write([]byte{','}); err != nil {
- return err
- }
- }
- switch {
- case run.Addr < cur:
- return fmt.Errorf("invalid %T: addr went backwards: %v < %v", sg, run.Addr, cur)
- case run.Addr > cur:
- if _, err := fmt.Fprintf(w, `{"Gap":%d},`, run.Addr.Sub(cur)); err != nil {
- return err
- }
- fallthrough
- default:
- if err := lowmemjson.NewEncoder(w).Encode(run); err != nil {
- return err
- }
- cur = run.Addr.Add(run.Size())
- }
- }
- end := sg.Addr.Add(sg.Size)
- switch {
- case end < cur:
- return fmt.Errorf("invalid %T: addr went backwards: %v < %v", sg, end, cur)
- case end > cur:
- if _, err := fmt.Fprintf(w, `,{"Gap":%d}`, end.Sub(cur)); err != nil {
- return err
- }
- }
- if _, err := w.Write([]byte("]}")); err != nil {
- return err
- }
- return nil
-}
-
-func (sg *SumRunWithGaps[Addr]) DecodeJSON(r io.RuneScanner) error {
- *sg = SumRunWithGaps[Addr]{}
- var name string
- return lowmemjson.DecodeObject(r,
- func(r io.RuneScanner) error {
- return lowmemjson.NewDecoder(r).Decode(&name)
- },
- func(r io.RuneScanner) error {
- switch name {
- case "Addr":
- return lowmemjson.NewDecoder(r).Decode(&sg.Addr)
- case "Size":
- return lowmemjson.NewDecoder(r).Decode(&sg.Size)
- case "Runs":
- return lowmemjson.DecodeArray(r, func(r io.RuneScanner) error {
- var run SumRun[Addr]
- if err := lowmemjson.NewDecoder(r).Decode(&run); err != nil {
- return err
- }
- if run.ChecksumSize > 0 {
- sg.Runs = append(sg.Runs, run)
- }
- return nil
- })
- default:
- return fmt.Errorf("unknown key %q", name)
- }
- })
-}
diff --git a/lib/btrfs/btrfssum/sumrun.go b/lib/btrfs/btrfssum/sumrun.go
new file mode 100644
index 0000000..1000e7a
--- /dev/null
+++ b/lib/btrfs/btrfssum/sumrun.go
@@ -0,0 +1,58 @@
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package btrfssum
+
+import (
+ "context"
+ "io"
+
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
+)
+
+type SumRun[Addr btrfsvol.IntAddr[Addr]] struct {
+ // How big a ShortSum is in this Run.
+ ChecksumSize int `json:",omitempty"`
+ // Base address where this run starts.
+ Addr Addr `json:",omitempty"`
+ // All of the ShortSums in this run, concatenated together.
+ Sums ShortSum
+}
+
+func (run SumRun[Addr]) NumSums() int {
+ return len(run.Sums) / run.ChecksumSize
+}
+
+func (run SumRun[Addr]) Size() btrfsvol.AddrDelta {
+ return btrfsvol.AddrDelta(run.NumSums()) * BlockSize
+}
+
+// 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 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)/BlockSize) * run.ChecksumSize
+ return 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+BlockSize, off+run.ChecksumSize {
+ if err := ctx.Err(); err != nil {
+ return err
+ }
+ if err := fn(addr, run.Sums[off:off+run.ChecksumSize]); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/lib/btrfs/btrfssum/sumrunwithgaps.go b/lib/btrfs/btrfssum/sumrunwithgaps.go
new file mode 100644
index 0000000..8362a49
--- /dev/null
+++ b/lib/btrfs/btrfssum/sumrunwithgaps.go
@@ -0,0 +1,160 @@
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package btrfssum
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "math"
+
+ "git.lukeshu.com/go/lowmemjson"
+
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
+ "git.lukeshu.com/btrfs-progs-ng/lib/diskio"
+)
+
+type SumRunWithGaps[Addr btrfsvol.IntAddr[Addr]] struct {
+ // Store the start address and size, in order to facilitate
+ // leading and trailing gaps.
+ Addr Addr
+ Size btrfsvol.AddrDelta
+
+ Runs []SumRun[Addr]
+}
+
+var (
+ _ lowmemjson.Encodable = SumRunWithGaps[btrfsvol.LogicalAddr]{}
+ _ lowmemjson.Decodable = (*SumRunWithGaps[btrfsvol.LogicalAddr])(nil)
+)
+
+func (sg SumRunWithGaps[Addr]) NumSums() int {
+ return int(sg.Size / BlockSize)
+}
+
+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]) RunForAddr(addr Addr) (SumRun[Addr], Addr, bool) {
+ for _, run := range sg.Runs {
+ if run.Addr > addr {
+ return SumRun[Addr]{}, run.Addr, false
+ }
+ if run.Addr.Add(run.Size()) <= addr {
+ continue
+ }
+ return run, 0, true
+ }
+ return SumRun[Addr]{}, math.MaxInt64, false
+}
+
+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)/BlockSize) * run.ChecksumSize
+ return run.Sums[off : off+run.ChecksumSize], nil
+ }
+ return "", diskio.ErrWildcard
+}
+
+func (sg SumRunWithGaps[Addr]) Walk(ctx context.Context, fn func(Addr, ShortSum) error) error {
+ for _, run := range sg.Runs {
+ if err := run.Walk(ctx, fn); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Get implements diskio.Sequence[int, ShortSum]
+func (sg SumRunWithGaps[Addr]) Get(sumIdx int64) (ShortSum, error) {
+ addr := sg.Addr.Add(btrfsvol.AddrDelta(sumIdx) * BlockSize)
+ return sg.SumForAddr(addr)
+}
+
+func (sg SumRunWithGaps[Addr]) EncodeJSON(w io.Writer) error {
+ if _, err := fmt.Fprintf(w, `{"Addr":%d,"Size":%d,"Runs":[`, sg.Addr, sg.Size); err != nil {
+ return err
+ }
+ cur := sg.Addr
+ for i, run := range sg.Runs {
+ if i > 0 {
+ if _, err := w.Write([]byte{','}); err != nil {
+ return err
+ }
+ }
+ switch {
+ case run.Addr < cur:
+ return fmt.Errorf("invalid %T: addr went backwards: %v < %v", sg, run.Addr, cur)
+ case run.Addr > cur:
+ if _, err := fmt.Fprintf(w, `{"Gap":%d},`, run.Addr.Sub(cur)); err != nil {
+ return err
+ }
+ fallthrough
+ default:
+ if err := lowmemjson.NewEncoder(w).Encode(run); err != nil {
+ return err
+ }
+ cur = run.Addr.Add(run.Size())
+ }
+ }
+ end := sg.Addr.Add(sg.Size)
+ switch {
+ case end < cur:
+ return fmt.Errorf("invalid %T: addr went backwards: %v < %v", sg, end, cur)
+ case end > cur:
+ if _, err := fmt.Fprintf(w, `,{"Gap":%d}`, end.Sub(cur)); err != nil {
+ return err
+ }
+ }
+ if _, err := w.Write([]byte("]}")); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (sg *SumRunWithGaps[Addr]) DecodeJSON(r io.RuneScanner) error {
+ *sg = SumRunWithGaps[Addr]{}
+ var name string
+ return lowmemjson.DecodeObject(r,
+ func(r io.RuneScanner) error {
+ return lowmemjson.NewDecoder(r).Decode(&name)
+ },
+ func(r io.RuneScanner) error {
+ switch name {
+ case "Addr":
+ return lowmemjson.NewDecoder(r).Decode(&sg.Addr)
+ case "Size":
+ return lowmemjson.NewDecoder(r).Decode(&sg.Size)
+ case "Runs":
+ return lowmemjson.DecodeArray(r, func(r io.RuneScanner) error {
+ var run SumRun[Addr]
+ if err := lowmemjson.NewDecoder(r).Decode(&run); err != nil {
+ return err
+ }
+ if run.ChecksumSize > 0 {
+ sg.Runs = append(sg.Runs, run)
+ }
+ return nil
+ })
+ default:
+ return fmt.Errorf("unknown key %q", name)
+ }
+ })
+}