From b78fe1835fed316bd8e9e51c91fcc05422330490 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 30 Jun 2022 04:14:55 -0600 Subject: lock sizes, use blockgroups --- pkg/btrfs/btrfsitem/item_blockgroup.go | 2 +- pkg/btrfs/btrfsitem/item_chunk.go | 5 ++-- pkg/btrfs/btrfsitem/item_devextent.go | 5 ++-- pkg/btrfs/btrfsvol/chunk.go | 20 ++++++++++++---- pkg/btrfs/btrfsvol/devext.go | 18 ++++++++++---- pkg/btrfs/btrfsvol/lvm.go | 44 +++++++++++++++++++++++----------- 6 files changed, 67 insertions(+), 27 deletions(-) (limited to 'pkg') diff --git a/pkg/btrfs/btrfsitem/item_blockgroup.go b/pkg/btrfs/btrfsitem/item_blockgroup.go index 8f7847d..63cbcbb 100644 --- a/pkg/btrfs/btrfsitem/item_blockgroup.go +++ b/pkg/btrfs/btrfsitem/item_blockgroup.go @@ -10,7 +10,7 @@ import ( // key.offset = size of chunk type BlockGroup struct { // BLOCK_GROUP_ITEM=192 Used int64 `bin:"off=0, siz=8"` - ChunkObjectID internal.ObjID `bin:"off=8, siz=8"` + ChunkObjectID internal.ObjID `bin:"off=8, siz=8"` // always BTRFS_FIRST_CHUNK_TREE_OBJECTID Flags btrfsvol.BlockGroupFlags `bin:"off=16, siz=8"` binstruct.End `bin:"off=24"` } diff --git a/pkg/btrfs/btrfsitem/item_chunk.go b/pkg/btrfs/btrfsitem/item_chunk.go index efd9d31..f567506 100644 --- a/pkg/btrfs/btrfsitem/item_chunk.go +++ b/pkg/btrfs/btrfsitem/item_chunk.go @@ -47,8 +47,9 @@ func (chunk Chunk) Mappings(key internal.Key) []btrfsvol.Mapping { Dev: stripe.DeviceID, Addr: stripe.Offset, }, - Size: chunk.Head.Size, - Flags: &chunk.Head.Type, + Size: chunk.Head.Size, + SizeLocked: true, + Flags: &chunk.Head.Type, }) } return ret diff --git a/pkg/btrfs/btrfsitem/item_devextent.go b/pkg/btrfs/btrfsitem/item_devextent.go index c7707bd..56fba27 100644 --- a/pkg/btrfs/btrfsitem/item_devextent.go +++ b/pkg/btrfs/btrfsitem/item_devextent.go @@ -25,7 +25,8 @@ func (devext DevExtent) Mapping(key internal.Key) btrfsvol.Mapping { Dev: btrfsvol.DeviceID(key.ObjectID), Addr: btrfsvol.PhysicalAddr(key.Offset), }, - Size: devext.Length, - Flags: nil, + Size: devext.Length, + SizeLocked: true, + Flags: nil, } } diff --git a/pkg/btrfs/btrfsvol/chunk.go b/pkg/btrfs/btrfsvol/chunk.go index e53265f..146193d 100644 --- a/pkg/btrfs/btrfsvol/chunk.go +++ b/pkg/btrfs/btrfsvol/chunk.go @@ -9,12 +9,15 @@ import ( // logical => []physical type chunkMapping struct { - LAddr LogicalAddr - PAddrs []QualifiedPhysicalAddr - Size AddrDelta - Flags *BlockGroupFlags + LAddr LogicalAddr + PAddrs []QualifiedPhysicalAddr + Size AddrDelta + SizeLocked bool + Flags *BlockGroupFlags } +type ChunkMapping = chunkMapping + // 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' @@ -51,6 +54,15 @@ func (a chunkMapping) union(rest ...chunkMapping) (chunkMapping, error) { LAddr: beg, Size: end.Sub(beg), } + for _, chunk := range chunks { + if chunk.SizeLocked { + ret.SizeLocked = true + if ret.Size != chunk.Size { + return chunkMapping{}, fmt.Errorf("member chunk has locked size=%v, but union would have size=%v", + chunk.Size, ret.Size) + } + } + } // figure out the physical stripes (.PAddrs) paddrs := make(map[QualifiedPhysicalAddr]struct{}) for _, chunk := range chunks { diff --git a/pkg/btrfs/btrfsvol/devext.go b/pkg/btrfs/btrfsvol/devext.go index 736d39b..8a69c7e 100644 --- a/pkg/btrfs/btrfsvol/devext.go +++ b/pkg/btrfs/btrfsvol/devext.go @@ -8,10 +8,11 @@ import ( // physical => logical type devextMapping struct { - PAddr PhysicalAddr - LAddr LogicalAddr - Size AddrDelta - Flags *BlockGroupFlags + PAddr PhysicalAddr + LAddr LogicalAddr + Size AddrDelta + SizeLocked bool + Flags *BlockGroupFlags } // return -1 if 'a' is wholly to the left of 'b' @@ -50,6 +51,15 @@ func (a devextMapping) union(rest ...devextMapping) (devextMapping, error) { PAddr: beg, Size: end.Sub(beg), } + for _, ext := range exts { + if ext.SizeLocked { + ret.SizeLocked = true + if ret.Size != ext.Size { + return devextMapping{}, fmt.Errorf("member devext has locked size=%v, but union would have size=%v", + ext.Size, ret.Size) + } + } + } // figure out the logical range (.LAddr) first := true for _, ext := range exts { diff --git a/pkg/btrfs/btrfsvol/lvm.go b/pkg/btrfs/btrfsvol/lvm.go index 078b18e..2857762 100644 --- a/pkg/btrfs/btrfsvol/lvm.go +++ b/pkg/btrfs/btrfsvol/lvm.go @@ -3,6 +3,7 @@ package btrfsvol import ( "bytes" "fmt" + "os" "reflect" "lukeshu.com/btrfs-tools/pkg/rbtree" @@ -91,10 +92,11 @@ func (lv *LogicalVolume[PhysicalVolume]) ClearMappings() { } type Mapping struct { - LAddr LogicalAddr - PAddr QualifiedPhysicalAddr - Size AddrDelta - Flags *BlockGroupFlags + LAddr LogicalAddr + PAddr QualifiedPhysicalAddr + Size AddrDelta + SizeLocked bool + Flags *BlockGroupFlags } func (lv *LogicalVolume[PhysicalVolume]) AddMapping(m Mapping) error { @@ -107,10 +109,11 @@ func (lv *LogicalVolume[PhysicalVolume]) AddMapping(m Mapping) error { // logical2physical newChunk := chunkMapping{ - LAddr: m.LAddr, - PAddrs: []QualifiedPhysicalAddr{m.PAddr}, - Size: m.Size, - Flags: m.Flags, + LAddr: m.LAddr, + PAddrs: []QualifiedPhysicalAddr{m.PAddr}, + Size: m.Size, + SizeLocked: m.SizeLocked, + Flags: m.Flags, } logicalOverlaps := lv.logical2physical.SearchRange(newChunk.cmpRange) var err error @@ -121,10 +124,11 @@ func (lv *LogicalVolume[PhysicalVolume]) AddMapping(m Mapping) error { // physical2logical newExt := devextMapping{ - PAddr: m.PAddr.Addr, - LAddr: m.LAddr, - Size: m.Size, - Flags: m.Flags, + PAddr: m.PAddr.Addr, + LAddr: m.LAddr, + Size: m.Size, + SizeLocked: m.SizeLocked, + Flags: m.Flags, } physicalOverlaps := lv.physical2logical[m.PAddr.Dev].SearchRange(newExt.cmpRange) newExt, err = newExt.union(physicalOverlaps...) @@ -154,8 +158,10 @@ func (lv *LogicalVolume[PhysicalVolume]) AddMapping(m Mapping) error { // // This is in-theory unnescessary, but that assumes that I // made no mistakes in my algorithm above. - if err := lv.fsck(); err != nil { - return err + if os.Getenv("PARANOID") != "" { + if err := lv.fsck(); err != nil { + return err + } } // done @@ -249,6 +255,16 @@ func (lv *LogicalVolume[PhysicalVolume]) Resolve(laddr LogicalAddr) (paddrs map[ return paddrs, maxlen } +func (lv *LogicalVolume[PhysicalVolume]) ResolveAny(laddr LogicalAddr, size AddrDelta) (LogicalAddr, QualifiedPhysicalAddr) { + node := lv.logical2physical.Search(func(chunk chunkMapping) int { + return chunkMapping{LAddr: laddr, Size: size}.cmpRange(chunk) + }) + if node == nil { + return -1, QualifiedPhysicalAddr{0, -1} + } + return node.Value.LAddr, node.Value.PAddrs[0] +} + func (lv *LogicalVolume[PhysicalVolume]) UnResolve(paddr QualifiedPhysicalAddr) LogicalAddr { node := lv.physical2logical[paddr.Dev].Search(func(ext devextMapping) int { return devextMapping{PAddr: paddr.Addr, Size: 1}.cmpRange(ext) -- cgit v1.2.3-2-g168b