summaryrefslogtreecommitdiff
path: root/pkg/btrfs/btrfsvol
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/btrfs/btrfsvol')
-rw-r--r--pkg/btrfs/btrfsvol/addr.go45
-rw-r--r--pkg/btrfs/btrfsvol/addr_test.go36
-rw-r--r--pkg/btrfs/btrfsvol/blockgroupflags.go51
-rw-r--r--pkg/btrfs/btrfsvol/chunk.go3
-rw-r--r--pkg/btrfs/btrfsvol/devext.go3
-rw-r--r--pkg/btrfs/btrfsvol/lvm.go25
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 {