summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-05 10:21:33 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-12 02:43:16 -0700
commitb608e4cf9c9e6e5bf5a333e8d78b2800ffcb0c91 (patch)
tree2cebbe4d02dfb1b993f97977a4eb3aec278336c9 /lib
parenta20926015f050f34b8a4dff17f80af6c6224e22c (diff)
btrfsvol: Add a sanity check
Diffstat (limited to 'lib')
-rw-r--r--lib/btrfs/btrfsvol/blockgroupflags.go5
-rw-r--r--lib/btrfs/btrfsvol/lvm.go26
2 files changed, 31 insertions, 0 deletions
diff --git a/lib/btrfs/btrfsvol/blockgroupflags.go b/lib/btrfs/btrfsvol/blockgroupflags.go
index 4ca5544..0125664 100644
--- a/lib/btrfs/btrfsvol/blockgroupflags.go
+++ b/lib/btrfs/btrfsvol/blockgroupflags.go
@@ -23,6 +23,11 @@ const (
BLOCK_GROUP_RAID1C3
BLOCK_GROUP_RAID1C4
+ // BLOCK_GROUP_RAID_MASK is the set of bits that mean that
+ // mean the logical:physical relationship is a one:many
+ // relationship rather than a one:one relationship.
+ //
+ // Notably, this does not include BLOCK_GROUP_RAID0.
BLOCK_GROUP_RAID_MASK = (BLOCK_GROUP_RAID1 | BLOCK_GROUP_DUP | BLOCK_GROUP_RAID10 | BLOCK_GROUP_RAID5 | BLOCK_GROUP_RAID6 | BLOCK_GROUP_RAID1C3 | BLOCK_GROUP_RAID1C4)
)
diff --git a/lib/btrfs/btrfsvol/lvm.go b/lib/btrfs/btrfsvol/lvm.go
index b83e9cd..59ca609 100644
--- a/lib/btrfs/btrfsvol/lvm.go
+++ b/lib/btrfs/btrfsvol/lvm.go
@@ -144,6 +144,10 @@ func (lv *LogicalVolume[PhysicalVolume]) addMapping(m Mapping, dryRun bool) erro
Flags: m.Flags,
}
logicalOverlaps := lv.logical2physical.SearchRange(newChunk.compareRange)
+ numOverlappingStripes := 0
+ for _, chunk := range logicalOverlaps {
+ numOverlappingStripes += len(chunk.PAddrs)
+ }
var err error
newChunk, err = newChunk.union(logicalOverlaps...)
if err != nil {
@@ -164,6 +168,28 @@ func (lv *LogicalVolume[PhysicalVolume]) addMapping(m Mapping, dryRun bool) erro
return fmt.Errorf("(%p).AddMapping: %w", lv, err)
}
+ if newChunk.Flags != newExt.Flags {
+ // If these don't match up, it's a bug in this code.
+ panic(fmt.Errorf("should not happen: newChunk.Flags:%+v != newExt.Flags:%+v",
+ newChunk.Flags, newExt.Flags))
+ }
+ switch {
+ case len(physicalOverlaps) == numOverlappingStripes:
+ // normal case
+ case len(physicalOverlaps) < numOverlappingStripes:
+ // .Flags = DUP or RAID{X}
+ if newChunk.Flags.OK && newChunk.Flags.Val&BLOCK_GROUP_RAID_MASK == 0 {
+ return fmt.Errorf("multiple stripes but flags=%v does not allow multiple stripes",
+ newChunk.Flags.Val)
+ }
+ case len(physicalOverlaps) > numOverlappingStripes:
+ // This should not happen because calling .AddMapping
+ // should update the two in lockstep; if these don't
+ // match up, it's a bug in this code.
+ panic(fmt.Errorf("should not happen: len(physicalOverlaps):%d != numOverlappingStripes:%d",
+ len(physicalOverlaps), numOverlappingStripes))
+ }
+
if dryRun {
return nil
}