summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-07-17 15:29:17 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-07-17 15:29:17 -0600
commit1793ed01f3d4a25d2144d3c766d917bc06f8be83 (patch)
tree0a66e2c7f80720cc02fc3c2f4a5b8ff2437e8d8e
parent94ba50701819889814583bd593581f1ca69ebaeb (diff)
handle gaps in blockgroups
-rw-r--r--lib/btrfsprogs/btrfsinspect/scanforextents/csums.go49
-rw-r--r--lib/btrfsprogs/btrfsinspect/scanforextents/scan.go9
2 files changed, 53 insertions, 5 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go b/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
index 5ec87d9..c1a1597 100644
--- a/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
+++ b/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
@@ -22,6 +22,7 @@ import (
"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"
)
const CSumBlockSize = 4 * 1024
@@ -81,6 +82,54 @@ func (run SumRun[Addr]) Walk(ctx context.Context, fn func(Addr, ShortSum) error)
return nil
}
+// SumRunWithGaps ////////////////////////////////////////////////////
+
+type SumRunWithGaps[Addr btrfsvol.IntAddr[Addr]] []SumRun[Addr]
+
+func (sg SumRunWithGaps[Addr]) end() Addr {
+ return sg[len(sg)-1].Addr.Add(sg[len(sg)-1].Size())
+}
+
+func (sg SumRunWithGaps[Addr]) Size() btrfsvol.AddrDelta {
+ if len(sg) == 0 {
+ return 0
+ }
+ return sg.end().Sub(sg[0].Addr)
+}
+
+func (sg SumRunWithGaps[Addr]) NumSums() int {
+ return int(sg.Size() / CSumBlockSize)
+}
+
+func (sg SumRunWithGaps[Addr]) SumForAddr(addr Addr) (ShortSum, error) {
+ if len(sg) == 0 {
+ return "", io.EOF
+ }
+ if addr < sg[0].Addr || addr >= sg.end() {
+ return "", io.EOF
+ }
+ for _, run := range sg {
+ if run.Addr > addr {
+ return "", diskio.ErrWildcard
+ }
+ if run.Addr.Add(run.Size()) <= addr {
+ continue
+ }
+ off := int((addr-run.Addr)/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) {
+ if len(sg) == 0 {
+ return "", io.EOF
+ }
+ addr := sg[0].Addr.Add(btrfsvol.AddrDelta(sumIdx) * CSumBlockSize)
+ return sg.SumForAddr(addr)
+}
+
// AllSums ///////////////////////////////////////////////////////////
type AllSums struct {
diff --git a/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go b/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go
index 64e0871..ca3036a 100644
--- a/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go
+++ b/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go
@@ -20,7 +20,7 @@ import (
func ScanForExtents(ctx context.Context, fs *btrfs.FS, blockgroups map[btrfsvol.LogicalAddr]BlockGroup, sums AllSums) error {
dlog.Info(ctx, "Pairing up blockgroups and sums...")
- bgSums := make(map[btrfsvol.LogicalAddr][]SumRun[btrfsvol.LogicalAddr])
+ bgSums := make(map[btrfsvol.LogicalAddr]SumRunWithGaps[btrfsvol.LogicalAddr])
for i, bgLAddr := range maps.SortedKeys(blockgroups) {
blockgroup := blockgroups[bgLAddr]
for laddr := blockgroup.LAddr; laddr < blockgroup.LAddr.Add(blockgroup.Size); {
@@ -51,10 +51,9 @@ func ScanForExtents(ctx context.Context, fs *btrfs.FS, blockgroups map[btrfsvol.
bgMatches := make(map[btrfsvol.LogicalAddr][]btrfsvol.QualifiedPhysicalAddr)
for i, bgLAddr := range maps.SortedKeys(blockgroups) {
bgRuns := bgSums[bgLAddr]
- if len(bgRuns) != 1 {
- // TODO(lukeshu): We aught to handle this rather than erroring and skipping
- // it.
- dlog.Errorf(ctx, "blockgroup laddr=%v has holes (%v runs)", bgLAddr, len(bgRuns))
+ if len(bgRuns) == 0 {
+ dlog.Errorf(ctx, "... (%v/%v) blockgroup[laddr=%v] can't be matched because it has 0 runs",
+ i+1, len(bgSums), bgLAddr)
continue
}
bgRun := bgRuns[0]