diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-06-26 19:55:49 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-06-26 19:55:49 -0600 |
commit | 502cdc72771de93ce41e2a00bc201fc488603f59 (patch) | |
tree | d8b7bc9890d0f8f8069c70376220ab54daae52f7 /pkg/btrfs/btrfsvol/devext.go | |
parent | e6b7c243462b1412390d0048dafe3430d07c05be (diff) |
better volume!
Diffstat (limited to 'pkg/btrfs/btrfsvol/devext.go')
-rw-r--r-- | pkg/btrfs/btrfsvol/devext.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/pkg/btrfs/btrfsvol/devext.go b/pkg/btrfs/btrfsvol/devext.go new file mode 100644 index 0000000..7696624 --- /dev/null +++ b/pkg/btrfs/btrfsvol/devext.go @@ -0,0 +1,80 @@ +package btrfsvol + +import ( + "fmt" + + "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsitem" + "lukeshu.com/btrfs-tools/pkg/util" +) + +// physical => logical +type devextMapping struct { + PAddr PhysicalAddr + LAddr LogicalAddr + Size AddrDelta + Flags *btrfsitem.BlockGroupFlags +} + +// return -1 if 'a' is wholly to the left of 'b' +// return 0 if there is some overlap between 'a' and 'b' +// return 1 if 'a is wholly to the right of 'b' +func (a devextMapping) cmpRange(b devextMapping) int { + switch { + case a.PAddr.Add(a.Size) <= b.PAddr: + // 'a' is wholly to the left of 'b'. + return -1 + case b.PAddr.Add(b.Size) <= a.PAddr: + // 'a' is wholly to the right of 'b'. + return 1 + default: + // There is some overlap. + return 0 + } +} + +func (a devextMapping) union(rest ...devextMapping) (devextMapping, error) { + // sanity check + for _, ext := range rest { + if a.cmpRange(ext) != 0 { + return devextMapping{}, fmt.Errorf("devexts don't overlap") + } + } + exts := append([]devextMapping{a}, rest...) + // figure out the physical range (.PAddr and .Size) + beg := exts[0].PAddr + end := beg.Add(exts[0].Size) + for _, ext := range exts { + beg = util.Min(beg, ext.PAddr) + end = util.Max(end, ext.PAddr.Add(ext.Size)) + } + ret := devextMapping{ + PAddr: beg, + Size: end.Sub(beg), + } + // figure out the logical range (.LAddr) + first := true + for _, ext := range exts { + offsetWithinRet := ext.PAddr.Sub(ret.PAddr) + laddr := ext.LAddr.Add(-offsetWithinRet) + if first { + ret.LAddr = laddr + } else if laddr != ret.LAddr { + return ret, fmt.Errorf("devexts don't agree on laddr: %v != %v", ret.LAddr, laddr) + } + } + // figure out the flags (.Flags) + for _, ext := range exts { + if ext.Flags == nil { + continue + } + if ret.Flags == nil { + val := *ext.Flags + ret.Flags = &val + } + if *ret.Flags != *ext.Flags { + return ret, fmt.Errorf("mismatch flags: %v != %v", *ret.Flags, *ext.Flags) + } + } + // done + return ret, nil +} |