1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
package rebuildmappings
import (
"context"
"github.com/datawire/dlib/dlog"
"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/diskio"
"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 btrfssum.SumRunWithGaps[btrfsvol.LogicalAddr],
) error {
regions := ListUnmappedPhysicalRegions(fs)
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, len(blockgroups), bgLAddr)
continue
}
var matches []btrfsvol.QualifiedPhysicalAddr
if err := WalkUnmappedPhysicalRegions(ctx, physicalSums, regions, func(devID btrfsvol.DeviceID, region btrfssum.SumRun[btrfsvol.PhysicalAddr]) error {
rawMatches, err := diskio.IndexAll[int64, btrfssum.ShortSum](region, bgRun)
if err != nil {
return err
}
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, len(blockgroups), bgLAddr, len(matches), int(100*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
}
|