From 08f36346efae090737ff70b33b73e360d41a5856 Mon Sep 17 00:00:00 2001
From: Luke Shumaker <lukeshu@lukeshu.com>
Date: Sun, 17 Jul 2022 20:20:51 -0600
Subject: Make sure there's enough free space for gaps at the beginning or end
 of bgs

---
 .../btrfsinspect/scanforextents/csums.go           | 36 ++++++++++------------
 lib/btrfsprogs/btrfsinspect/scanforextents/scan.go | 16 ++++++----
 2 files changed, 26 insertions(+), 26 deletions(-)

(limited to 'lib/btrfsprogs/btrfsinspect/scanforextents')

diff --git a/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go b/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
index c1a1597..0ab933e 100644
--- a/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
+++ b/lib/btrfsprogs/btrfsinspect/scanforextents/csums.go
@@ -84,31 +84,30 @@ func (run SumRun[Addr]) Walk(ctx context.Context, fn func(Addr, ShortSum) error)
 
 // 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())
+type SumRunWithGaps[Addr btrfsvol.IntAddr[Addr]] struct {
+	Addr Addr
+	Size btrfsvol.AddrDelta
+	Runs []SumRun[Addr]
 }
 
-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]) NumSums() int {
-	return int(sg.Size() / 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 len(sg) == 0 {
-		return "", io.EOF
-	}
-	if addr < sg[0].Addr || addr >= sg.end() {
+	if addr < sg.Addr || addr >= sg.Addr.Add(sg.Size) {
 		return "", io.EOF
 	}
-	for _, run := range sg {
+	for _, run := range sg.Runs {
 		if run.Addr > addr {
 			return "", diskio.ErrWildcard
 		}
@@ -123,10 +122,7 @@ func (sg SumRunWithGaps[Addr]) SumForAddr(addr Addr) (ShortSum, error) {
 
 // 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)
+	addr := sg.Addr.Add(btrfsvol.AddrDelta(sumIdx) * CSumBlockSize)
 	return sg.SumForAddr(addr)
 }
 
diff --git a/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go b/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go
index ca3036a..9219787 100644
--- a/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go
+++ b/lib/btrfsprogs/btrfsinspect/scanforextents/scan.go
@@ -23,6 +23,10 @@ func ScanForExtents(ctx context.Context, fs *btrfs.FS, blockgroups map[btrfsvol.
 	bgSums := make(map[btrfsvol.LogicalAddr]SumRunWithGaps[btrfsvol.LogicalAddr])
 	for i, bgLAddr := range maps.SortedKeys(blockgroups) {
 		blockgroup := blockgroups[bgLAddr]
+		runs := SumRunWithGaps[btrfsvol.LogicalAddr]{
+			Addr: blockgroup.LAddr,
+			Size: blockgroup.Size,
+		}
 		for laddr := blockgroup.LAddr; laddr < blockgroup.LAddr.Add(blockgroup.Size); {
 			run, next, ok := sums.RunForLAddr(laddr)
 			if !ok {
@@ -34,15 +38,16 @@ func ScanForExtents(ctx context.Context, fs *btrfs.FS, blockgroups map[btrfsvol.
 				blockgroup.Size-laddr.Sub(blockgroup.LAddr),
 				btrfsvol.AddrDelta((len(run.Sums)-off)/run.ChecksumSize)*CSumBlockSize)
 			deltaOff := int(deltaAddr/CSumBlockSize) * run.ChecksumSize
-			bgSums[blockgroup.LAddr] = append(bgSums[blockgroup.LAddr], SumRun[btrfsvol.LogicalAddr]{
+			runs.Runs = append(runs.Runs, SumRun[btrfsvol.LogicalAddr]{
 				ChecksumSize: run.ChecksumSize,
 				Addr:         laddr,
 				Sums:         run.Sums[off : off+deltaOff],
 			})
 			laddr = laddr.Add(deltaAddr)
 		}
-		dlog.Infof(ctx, "... (%v/%v) blockgroup[laddr=%v] has %v runs",
-			i+1, len(blockgroups), bgLAddr, len(bgSums[blockgroup.LAddr]))
+		bgSums[blockgroup.LAddr] = runs
+		dlog.Infof(ctx, "... (%v/%v) blockgroup[laddr=%v] has %v runs covering %v%%",
+			i+1, len(blockgroups), bgLAddr, len(runs.Runs), int(runs.PctFull()))
 	}
 	dlog.Info(ctx, "... done pairing")
 
@@ -50,13 +55,12 @@ func ScanForExtents(ctx context.Context, fs *btrfs.FS, blockgroups map[btrfsvol.
 	gaps := ListPhysicalGaps(fs)
 	bgMatches := make(map[btrfsvol.LogicalAddr][]btrfsvol.QualifiedPhysicalAddr)
 	for i, bgLAddr := range maps.SortedKeys(blockgroups) {
-		bgRuns := bgSums[bgLAddr]
-		if len(bgRuns) == 0 {
+		bgRun := bgSums[bgLAddr]
+		if len(bgRun.Runs) == 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]
 
 		if err := WalkGaps(ctx, sums, gaps, func(devID btrfsvol.DeviceID, gap SumRun[btrfsvol.PhysicalAddr]) error {
 			matches, err := diskio.IndexAll[int64, ShortSum](gap, bgRun)
-- 
cgit v1.2.3-2-g168b