diff options
Diffstat (limited to 'pkg/btrfs/btrfsvol')
-rw-r--r-- | pkg/btrfs/btrfsvol/addr.go | 45 | ||||
-rw-r--r-- | pkg/btrfs/btrfsvol/addr_test.go | 36 | ||||
-rw-r--r-- | pkg/btrfs/btrfsvol/blockgroupflags.go | 51 | ||||
-rw-r--r-- | pkg/btrfs/btrfsvol/chunk.go | 3 | ||||
-rw-r--r-- | pkg/btrfs/btrfsvol/devext.go | 3 | ||||
-rw-r--r-- | pkg/btrfs/btrfsvol/lvm.go | 25 |
6 files changed, 142 insertions, 21 deletions
diff --git a/pkg/btrfs/btrfsvol/addr.go b/pkg/btrfs/btrfsvol/addr.go new file mode 100644 index 0000000..e8b578a --- /dev/null +++ b/pkg/btrfs/btrfsvol/addr.go @@ -0,0 +1,45 @@ +package btrfsvol + +import ( + "fmt" + + "lukeshu.com/btrfs-tools/pkg/util" +) + +type ( + PhysicalAddr int64 + LogicalAddr int64 + AddrDelta int64 +) + +func formatAddr(addr int64, f fmt.State, verb rune) { + switch verb { + case 'v', 's', 'q': + str := fmt.Sprintf("%#016x", addr) + fmt.Fprintf(f, util.FmtStateString(f, verb), str) + default: + fmt.Fprintf(f, util.FmtStateString(f, verb), addr) + } +} + +func (a PhysicalAddr) Format(f fmt.State, verb rune) { formatAddr(int64(a), f, verb) } +func (a LogicalAddr) Format(f fmt.State, verb rune) { formatAddr(int64(a), f, verb) } +func (d AddrDelta) Format(f fmt.State, verb rune) { formatAddr(int64(d), f, verb) } + +func (a PhysicalAddr) Sub(b PhysicalAddr) AddrDelta { return AddrDelta(a - b) } +func (a LogicalAddr) Sub(b LogicalAddr) AddrDelta { return AddrDelta(a - b) } + +func (a PhysicalAddr) Add(b AddrDelta) PhysicalAddr { return a + PhysicalAddr(b) } +func (a LogicalAddr) Add(b AddrDelta) LogicalAddr { return a + LogicalAddr(b) } + +type QualifiedPhysicalAddr struct { + Dev util.UUID + Addr PhysicalAddr +} + +func (a QualifiedPhysicalAddr) Cmp(b QualifiedPhysicalAddr) int { + if d := a.Dev.Cmp(b.Dev); d != 0 { + return d + } + return int(a.Addr - b.Addr) +} diff --git a/pkg/btrfs/btrfsvol/addr_test.go b/pkg/btrfs/btrfsvol/addr_test.go new file mode 100644 index 0000000..83af1ac --- /dev/null +++ b/pkg/btrfs/btrfsvol/addr_test.go @@ -0,0 +1,36 @@ +package btrfsvol_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsvol" +) + +func TestAddrFormat(t *testing.T) { + t.Parallel() + type TestCase struct { + InputAddr btrfsvol.LogicalAddr + InputFmt string + Output string + } + addr := btrfsvol.LogicalAddr(0x3a41678000) + testcases := map[string]TestCase{ + "v": TestCase{InputAddr: addr, InputFmt: "%v", Output: "0x0000003a41678000"}, + "s": TestCase{InputAddr: addr, InputFmt: "%s", Output: "0x0000003a41678000"}, + "q": TestCase{InputAddr: addr, InputFmt: "%q", Output: `"0x0000003a41678000"`}, + "x": TestCase{InputAddr: addr, InputFmt: "%x", Output: "3a41678000"}, + "d": TestCase{InputAddr: addr, InputFmt: "%d", Output: "250205405184"}, + "neg": TestCase{InputAddr: -1, InputFmt: "%v", Output: "-0x000000000000001"}, + } + for tcName, tc := range testcases { + tc := tc + t.Run(tcName, func(t *testing.T) { + t.Parallel() + actual := fmt.Sprintf(tc.InputFmt, tc.InputAddr) + assert.Equal(t, tc.Output, actual) + }) + } +} diff --git a/pkg/btrfs/btrfsvol/blockgroupflags.go b/pkg/btrfs/btrfsvol/blockgroupflags.go new file mode 100644 index 0000000..ba1610b --- /dev/null +++ b/pkg/btrfs/btrfsvol/blockgroupflags.go @@ -0,0 +1,51 @@ +package btrfsvol + +import ( + "lukeshu.com/btrfs-tools/pkg/util" +) + +type BlockGroupFlags uint64 + +const ( + BLOCK_GROUP_DATA = BlockGroupFlags(1 << iota) + BLOCK_GROUP_SYSTEM + BLOCK_GROUP_METADATA + BLOCK_GROUP_RAID0 + BLOCK_GROUP_RAID1 + BLOCK_GROUP_DUP + BLOCK_GROUP_RAID10 + BLOCK_GROUP_RAID5 + BLOCK_GROUP_RAID6 + BLOCK_GROUP_RAID1C3 + BLOCK_GROUP_RAID1C4 + + 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) +) + +var blockGroupFlagNames = []string{ + "DATA", + "SYSTEM", + "METADATA", + + "RAID0", + "RAID1", + "DUP", + "RAID10", + "RAID5", + "RAID6", + "RAID1C3", + "RAID1C4", +} + +func (f BlockGroupFlags) Has(req BlockGroupFlags) bool { return f&req == req } +func (f BlockGroupFlags) String() string { + ret := util.BitfieldString(f, blockGroupFlagNames, util.HexNone) + if f&BLOCK_GROUP_RAID_MASK == 0 { + if ret == "" { + ret = "single" + } else { + ret += "|single" + } + } + return ret +} diff --git a/pkg/btrfs/btrfsvol/chunk.go b/pkg/btrfs/btrfsvol/chunk.go index 112d446..e53265f 100644 --- a/pkg/btrfs/btrfsvol/chunk.go +++ b/pkg/btrfs/btrfsvol/chunk.go @@ -4,7 +4,6 @@ import ( "fmt" "sort" - "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsitem" "lukeshu.com/btrfs-tools/pkg/util" ) @@ -13,7 +12,7 @@ type chunkMapping struct { LAddr LogicalAddr PAddrs []QualifiedPhysicalAddr Size AddrDelta - Flags *btrfsitem.BlockGroupFlags + Flags *BlockGroupFlags } // return -1 if 'a' is wholly to the left of 'b' diff --git a/pkg/btrfs/btrfsvol/devext.go b/pkg/btrfs/btrfsvol/devext.go index 7696624..736d39b 100644 --- a/pkg/btrfs/btrfsvol/devext.go +++ b/pkg/btrfs/btrfsvol/devext.go @@ -3,7 +3,6 @@ package btrfsvol import ( "fmt" - "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsitem" "lukeshu.com/btrfs-tools/pkg/util" ) @@ -12,7 +11,7 @@ type devextMapping struct { PAddr PhysicalAddr LAddr LogicalAddr Size AddrDelta - Flags *btrfsitem.BlockGroupFlags + Flags *BlockGroupFlags } // return -1 if 'a' is wholly to the left of 'b' diff --git a/pkg/btrfs/btrfsvol/lvm.go b/pkg/btrfs/btrfsvol/lvm.go index dc3bd06..a74e82c 100644 --- a/pkg/btrfs/btrfsvol/lvm.go +++ b/pkg/btrfs/btrfsvol/lvm.go @@ -7,27 +7,18 @@ import ( "reflect" "sort" - "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsitem" - "lukeshu.com/btrfs-tools/pkg/btrfs/internal" "lukeshu.com/btrfs-tools/pkg/util" ) -type ( - LogicalAddr = internal.LogicalAddr - PhysicalAddr = internal.PhysicalAddr - AddrDelta = internal.AddrDelta - QualifiedPhysicalAddr = internal.QualifiedPhysicalAddr -) - type PhysicalVolume = util.File[PhysicalAddr] type LogicalVolume struct { name string - uuid2pv map[internal.UUID]PhysicalVolume + uuid2pv map[util.UUID]PhysicalVolume logical2physical []chunkMapping - physical2logical map[internal.UUID][]devextMapping + physical2logical map[util.UUID][]devextMapping } var _ util.File[LogicalAddr] = (*LogicalVolume)(nil) @@ -48,9 +39,9 @@ func (lv *LogicalVolume) Size() (LogicalAddr, error) { return lastChunk.LAddr.Add(lastChunk.Size), nil } -func (lv *LogicalVolume) AddPhysicalVolume(uuid internal.UUID, dev PhysicalVolume) error { +func (lv *LogicalVolume) AddPhysicalVolume(uuid util.UUID, dev PhysicalVolume) error { if lv.uuid2pv == nil { - lv.uuid2pv = make(map[internal.UUID]PhysicalVolume) + lv.uuid2pv = make(map[util.UUID]PhysicalVolume) } if other, exists := lv.uuid2pv[uuid]; exists { return fmt.Errorf("(%p).AddPhysicalVolume: cannot add physical volume %q: already have physical volume %q with uuid=%v", @@ -61,7 +52,7 @@ func (lv *LogicalVolume) AddPhysicalVolume(uuid internal.UUID, dev PhysicalVolum } func (lv *LogicalVolume) PhysicalVolumes() []PhysicalVolume { - uuids := make([]internal.UUID, 0, len(lv.uuid2pv)) + uuids := make([]util.UUID, 0, len(lv.uuid2pv)) for uuid := range lv.uuid2pv { uuids = append(uuids, uuid) } @@ -80,14 +71,14 @@ func (lv *LogicalVolume) ClearMappings() { lv.physical2logical = nil } -func (lv *LogicalVolume) AddMapping(laddr LogicalAddr, paddr QualifiedPhysicalAddr, size AddrDelta, flags *btrfsitem.BlockGroupFlags) error { +func (lv *LogicalVolume) AddMapping(laddr LogicalAddr, paddr QualifiedPhysicalAddr, size AddrDelta, flags *BlockGroupFlags) error { // sanity check if _, haveDev := lv.uuid2pv[paddr.Dev]; !haveDev { return fmt.Errorf("(%p).AddMapping: do not have a physical volume with uuid=%v", lv, paddr.Dev) } if lv.physical2logical == nil { - lv.physical2logical = make(map[internal.UUID][]devextMapping) + lv.physical2logical = make(map[util.UUID][]devextMapping) } // logical2physical @@ -171,7 +162,7 @@ func (lv *LogicalVolume) AddMapping(laddr LogicalAddr, paddr QualifiedPhysicalAd } func (lv *LogicalVolume) fsck() error { - physical2logical := make(map[internal.UUID][]devextMapping) + physical2logical := make(map[util.UUID][]devextMapping) for _, chunk := range lv.logical2physical { for _, stripe := range chunk.PAddrs { if _, devOK := lv.uuid2pv[stripe.Dev]; !devOK { |