From 1793ed01f3d4a25d2144d3c766d917bc06f8be83 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 17 Jul 2022 15:29:17 -0600 Subject: handle gaps in blockgroups --- .../btrfsinspect/scanforextents/csums.go | 49 ++++++++++++++++++++++ lib/btrfsprogs/btrfsinspect/scanforextents/scan.go | 9 ++-- 2 files changed, 53 insertions(+), 5 deletions(-) (limited to 'lib') 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] -- cgit v1.2.3-2-g168b