summaryrefslogtreecommitdiff
path: root/lib/btrfsprogs/btrfsinspect/rebuildmappings/physicalsums.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-08-24 09:27:49 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-08-24 12:05:31 -0600
commitc95ae0b25133dc068e3d471a4a2c798be45b7930 (patch)
tree889caa49d5f023cfdfb3cce0fc4b73c2d4546c5c /lib/btrfsprogs/btrfsinspect/rebuildmappings/physicalsums.go
parent6f73ced9a723aa68694593ebc1bb4e1e621b2f2d (diff)
wip: work on rebuildmappings
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/rebuildmappings/physicalsums.go')
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildmappings/physicalsums.go89
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildmappings/physicalsums.go b/lib/btrfsprogs/btrfsinspect/rebuildmappings/physicalsums.go
new file mode 100644
index 0000000..0806a63
--- /dev/null
+++ b/lib/btrfsprogs/btrfsinspect/rebuildmappings/physicalsums.go
@@ -0,0 +1,89 @@
+// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package rebuildmappings
+
+import (
+ "context"
+ "sort"
+
+ "golang.org/x/exp/constraints"
+
+ "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/btrfsprogs/btrfsinspect"
+ "git.lukeshu.com/btrfs-progs-ng/lib/maps"
+)
+
+func ExtractPhysicalSums(scanResults btrfsinspect.ScanDevicesResult) map[btrfsvol.DeviceID]btrfssum.SumRun[btrfsvol.PhysicalAddr] {
+ ret := make(map[btrfsvol.DeviceID]btrfssum.SumRun[btrfsvol.PhysicalAddr], len(scanResults))
+ for devID, devResults := range scanResults {
+ ret[devID] = devResults.Checksums
+ }
+ return ret
+}
+
+type PhysicalRegion struct {
+ Beg, End btrfsvol.PhysicalAddr
+}
+
+func ListUnmappedPhysicalRegions(fs *btrfs.FS) map[btrfsvol.DeviceID][]PhysicalRegion {
+ regions := make(map[btrfsvol.DeviceID][]PhysicalRegion)
+ pos := make(map[btrfsvol.DeviceID]btrfsvol.PhysicalAddr)
+ mappings := fs.LV.Mappings()
+ sort.Slice(mappings, func(i, j int) bool {
+ return mappings[i].PAddr.Cmp(mappings[j].PAddr) < 0
+ })
+ for _, mapping := range mappings {
+ if pos[mapping.PAddr.Dev] < mapping.PAddr.Addr {
+ regions[mapping.PAddr.Dev] = append(regions[mapping.PAddr.Dev], PhysicalRegion{
+ Beg: pos[mapping.PAddr.Dev],
+ End: mapping.PAddr.Addr,
+ })
+ }
+ if pos[mapping.PAddr.Dev] < mapping.PAddr.Addr.Add(mapping.Size) {
+ pos[mapping.PAddr.Dev] = mapping.PAddr.Addr.Add(mapping.Size)
+ }
+ }
+ for devID, dev := range fs.LV.PhysicalVolumes() {
+ devSize := dev.Size()
+ if pos[devID] < devSize {
+ regions[devID] = append(regions[devID], PhysicalRegion{
+ Beg: pos[devID],
+ End: devSize,
+ })
+ }
+ }
+ return regions
+}
+
+func roundUp[T constraints.Integer](x, multiple T) T {
+ return ((x + multiple - 1) / multiple) * multiple
+}
+
+func WalkUnmappedPhysicalRegions(ctx context.Context,
+ physicalSums map[btrfsvol.DeviceID]btrfssum.SumRun[btrfsvol.PhysicalAddr],
+ gaps map[btrfsvol.DeviceID][]PhysicalRegion,
+ fn func(btrfsvol.DeviceID, btrfssum.SumRun[btrfsvol.PhysicalAddr]) error,
+) error {
+ for _, devID := range maps.SortedKeys(gaps) {
+ for _, gap := range gaps[devID] {
+ if err := ctx.Err(); err != nil {
+ return err
+ }
+ begAddr := roundUp(gap.Beg, btrfssum.BlockSize)
+ begOff := int(begAddr/btrfssum.BlockSize) * physicalSums[devID].ChecksumSize
+ endOff := int(gap.End/btrfssum.BlockSize) * physicalSums[devID].ChecksumSize
+ if err := fn(devID, btrfssum.SumRun[btrfsvol.PhysicalAddr]{
+ ChecksumSize: physicalSums[devID].ChecksumSize,
+ Addr: begAddr,
+ Sums: physicalSums[devID].Sums[begOff:endOff],
+ }); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}