diff options
Diffstat (limited to 'cmd/btrfs-rec/inspect/rebuildmappings/process_matchsums_exact.go')
-rw-r--r-- | cmd/btrfs-rec/inspect/rebuildmappings/process_matchsums_exact.go | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/cmd/btrfs-rec/inspect/rebuildmappings/process_matchsums_exact.go b/cmd/btrfs-rec/inspect/rebuildmappings/process_matchsums_exact.go new file mode 100644 index 0000000..a3e724e --- /dev/null +++ b/cmd/btrfs-rec/inspect/rebuildmappings/process_matchsums_exact.go @@ -0,0 +1,78 @@ +// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com> +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package rebuildmappings + +import ( + "context" + + "github.com/datawire/dlib/dlog" + "golang.org/x/text/number" + + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" + "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/containers" + "git.lukeshu.com/btrfs-progs-ng/lib/maps" +) + +func matchBlockGroupSums(ctx context.Context, + fs *btrfs.FS, + blockgroups map[btrfsvol.LogicalAddr]BlockGroup, + physicalSums map[btrfsvol.DeviceID]btrfssum.SumRun[btrfsvol.PhysicalAddr], + logicalSums SumRunWithGaps[btrfsvol.LogicalAddr], +) error { + regions := ListUnmappedPhysicalRegions(fs) + numBlockgroups := len(blockgroups) + for i, bgLAddr := range maps.SortedKeys(blockgroups) { + blockgroup := blockgroups[bgLAddr] + bgRun := SumsForLogicalRegion(logicalSums, blockgroup.LAddr, blockgroup.Size) + if len(bgRun.Runs) == 0 { + dlog.Errorf(ctx, "(%v/%v) blockgroup[laddr=%v] can't be matched because it has 0 runs", + i+1, numBlockgroups, bgLAddr) + continue + } + + var matches []btrfsvol.QualifiedPhysicalAddr + if err := WalkUnmappedPhysicalRegions(ctx, physicalSums, regions, func(devID btrfsvol.DeviceID, region btrfssum.SumRun[btrfsvol.PhysicalAddr]) error { + rawMatches := indexAll[int, btrfssum.ShortSum](region, bgRun) + for _, match := range rawMatches { + matches = append(matches, btrfsvol.QualifiedPhysicalAddr{ + Dev: devID, + Addr: region.Addr + (btrfsvol.PhysicalAddr(match) * btrfssum.BlockSize), + }) + } + return nil + }); err != nil { + return err + } + + lvl := dlog.LogLevelError + if len(matches) == 1 { + lvl = dlog.LogLevelInfo + } + dlog.Logf(ctx, lvl, "(%v/%v) blockgroup[laddr=%v] has %v matches based on %v coverage from %v runs", + i+1, numBlockgroups, bgLAddr, len(matches), number.Percent(bgRun.PctFull()), len(bgRun.Runs)) + if len(matches) != 1 { + continue + } + + mapping := btrfsvol.Mapping{ + LAddr: blockgroup.LAddr, + PAddr: matches[0], + Size: blockgroup.Size, + SizeLocked: true, + Flags: containers.Optional[btrfsvol.BlockGroupFlags]{ + OK: true, + Val: blockgroup.Flags, + }, + } + if err := fs.LV.AddMapping(mapping); err != nil { + dlog.Errorf(ctx, "error: %v", err) + continue + } + delete(blockgroups, bgLAddr) + } + return nil +} |