summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-06-26 22:19:29 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-06-26 22:19:41 -0600
commit8463b2bff37978124e5210a59590f1ac33e453c0 (patch)
tree37fc4c13f1fdaedf20ee48a53653414fbb3d9ed7
parent64c04fc690ec5a276e11500691173962bbe4d99e (diff)
use devid instead of devuuid, add a Mapping struct
-rw-r--r--cmd/btrfs-fsck/pass1.go4
-rw-r--r--pkg/btrfs/btrfsitem/item_chunk.go18
-rw-r--r--pkg/btrfs/btrfsitem/item_dev.go3
-rw-r--r--pkg/btrfs/btrfsitem/item_devextent.go12
-rw-r--r--pkg/btrfs/btrfsvol/addr.go6
-rw-r--r--pkg/btrfs/btrfsvol/lvm.go86
-rw-r--r--pkg/btrfs/io2_fs.go33
-rw-r--r--pkg/btrfsmisc/print_tree.go2
8 files changed, 91 insertions, 73 deletions
diff --git a/cmd/btrfs-fsck/pass1.go b/cmd/btrfs-fsck/pass1.go
index aada80d..fada257 100644
--- a/cmd/btrfs-fsck/pass1.go
+++ b/cmd/btrfs-fsck/pass1.go
@@ -229,7 +229,7 @@ func pass1ReconstructChunksOneDev(
resolvedPAddrs, _ := fs.Resolve(laddr)
for _, readPAddr := range readPAddrs {
if _, ok := resolvedPAddrs[btrfs.QualifiedPhysicalAddr{
- Dev: superblock.Data.DevItem.DevUUID,
+ Dev: superblock.Data.DevItem.DevID,
Addr: readPAddr,
}]; !ok {
lostAndFoundNodes[readPAddr] = laddr
@@ -288,7 +288,7 @@ func pass1ReconstructChunksOneDev(
panic("TODO: mismatch")
}
chunk.Stripes = append(chunk.Stripes, btrfsitem.ChunkStripe{
- DeviceID: superblock.Data.DevItem.DeviceID,
+ DeviceID: superblock.Data.DevItem.DevID,
DeviceUUID: superblock.Data.DevItem.DevUUID,
Offset: stripe.PAddr,
})
diff --git a/pkg/btrfs/btrfsitem/item_chunk.go b/pkg/btrfs/btrfsitem/item_chunk.go
index a77ae33..efd9d31 100644
--- a/pkg/btrfs/btrfsitem/item_chunk.go
+++ b/pkg/btrfs/btrfsitem/item_chunk.go
@@ -32,12 +32,28 @@ type ChunkHeader struct {
}
type ChunkStripe struct {
- DeviceID internal.ObjID `bin:"off=0x0, siz=0x8"`
+ DeviceID btrfsvol.DeviceID `bin:"off=0x0, siz=0x8"`
Offset btrfsvol.PhysicalAddr `bin:"off=0x8, siz=0x8"`
DeviceUUID util.UUID `bin:"off=0x10, siz=0x10"`
binstruct.End `bin:"off=0x20"`
}
+func (chunk Chunk) Mappings(key internal.Key) []btrfsvol.Mapping {
+ ret := make([]btrfsvol.Mapping, 0, len(chunk.Stripes))
+ for _, stripe := range chunk.Stripes {
+ ret = append(ret, btrfsvol.Mapping{
+ LAddr: btrfsvol.LogicalAddr(key.Offset),
+ PAddr: btrfsvol.QualifiedPhysicalAddr{
+ Dev: stripe.DeviceID,
+ Addr: stripe.Offset,
+ },
+ Size: chunk.Head.Size,
+ Flags: &chunk.Head.Type,
+ })
+ }
+ return ret
+}
+
func (chunk *Chunk) UnmarshalBinary(dat []byte) (int, error) {
n, err := binstruct.Unmarshal(dat, &chunk.Head)
if err != nil {
diff --git a/pkg/btrfs/btrfsitem/item_dev.go b/pkg/btrfs/btrfsitem/item_dev.go
index 848f338..1c0fea0 100644
--- a/pkg/btrfs/btrfsitem/item_dev.go
+++ b/pkg/btrfs/btrfsitem/item_dev.go
@@ -2,12 +2,13 @@ package btrfsitem
import (
"lukeshu.com/btrfs-tools/pkg/binstruct"
+ "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsvol"
"lukeshu.com/btrfs-tools/pkg/btrfs/internal"
"lukeshu.com/btrfs-tools/pkg/util"
)
type Dev struct { // DEV_ITEM=216
- DeviceID internal.ObjID `bin:"off=0x0, siz=0x8"`
+ DevID btrfsvol.DeviceID `bin:"off=0x0, siz=0x8"`
NumBytes uint64 `bin:"off=0x8, siz=0x8"`
NumBytesUsed uint64 `bin:"off=0x10, siz=0x8"`
diff --git a/pkg/btrfs/btrfsitem/item_devextent.go b/pkg/btrfs/btrfsitem/item_devextent.go
index 03d696a..c7707bd 100644
--- a/pkg/btrfs/btrfsitem/item_devextent.go
+++ b/pkg/btrfs/btrfsitem/item_devextent.go
@@ -17,3 +17,15 @@ type DevExtent struct { // DEV_EXTENT=204
ChunkTreeUUID util.UUID `bin:"off=32, siz=16"`
binstruct.End `bin:"off=48"`
}
+
+func (devext DevExtent) Mapping(key internal.Key) btrfsvol.Mapping {
+ return btrfsvol.Mapping{
+ LAddr: devext.ChunkOffset,
+ PAddr: btrfsvol.QualifiedPhysicalAddr{
+ Dev: btrfsvol.DeviceID(key.ObjectID),
+ Addr: btrfsvol.PhysicalAddr(key.Offset),
+ },
+ Size: devext.Length,
+ Flags: nil,
+ }
+}
diff --git a/pkg/btrfs/btrfsvol/addr.go b/pkg/btrfs/btrfsvol/addr.go
index e8b578a..b426611 100644
--- a/pkg/btrfs/btrfsvol/addr.go
+++ b/pkg/btrfs/btrfsvol/addr.go
@@ -32,13 +32,15 @@ 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 DeviceID uint64
+
type QualifiedPhysicalAddr struct {
- Dev util.UUID
+ Dev DeviceID
Addr PhysicalAddr
}
func (a QualifiedPhysicalAddr) Cmp(b QualifiedPhysicalAddr) int {
- if d := a.Dev.Cmp(b.Dev); d != 0 {
+ if d := int(a.Dev - b.Dev); d != 0 {
return d
}
return int(a.Addr - b.Addr)
diff --git a/pkg/btrfs/btrfsvol/lvm.go b/pkg/btrfs/btrfsvol/lvm.go
index 4e6b058..c0264b3 100644
--- a/pkg/btrfs/btrfsvol/lvm.go
+++ b/pkg/btrfs/btrfsvol/lvm.go
@@ -13,10 +13,10 @@ import (
type LogicalVolume[PhysicalVolume util.File[PhysicalAddr]] struct {
name string
- uuid2pv map[util.UUID]PhysicalVolume
+ id2pv map[DeviceID]PhysicalVolume
logical2physical []chunkMapping
- physical2logical map[util.UUID][]devextMapping
+ physical2logical map[DeviceID][]devextMapping
}
var _ util.File[LogicalAddr] = (*LogicalVolume[util.File[PhysicalAddr]])(nil)
@@ -37,31 +37,24 @@ func (lv *LogicalVolume[PhysicalVolume]) Size() (LogicalAddr, error) {
return lastChunk.LAddr.Add(lastChunk.Size), nil
}
-func (lv *LogicalVolume[PhysicalVolume]) AddPhysicalVolume(uuid util.UUID, dev PhysicalVolume) error {
- if lv.uuid2pv == nil {
- lv.uuid2pv = make(map[util.UUID]PhysicalVolume)
+func (lv *LogicalVolume[PhysicalVolume]) AddPhysicalVolume(id DeviceID, dev PhysicalVolume) error {
+ if lv.id2pv == nil {
+ lv.id2pv = make(map[DeviceID]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",
- lv, dev.Name(), other.Name(), uuid)
+ if other, exists := lv.id2pv[id]; exists {
+ return fmt.Errorf("(%p).AddPhysicalVolume: cannot add physical volume %q: already have physical volume %q with id=%v",
+ lv, dev.Name(), other.Name(), id)
}
- lv.uuid2pv[uuid] = dev
+ lv.id2pv[id] = dev
return nil
}
-func (lv *LogicalVolume[PhysicalVolume]) PhysicalVolumes() []PhysicalVolume {
- uuids := make([]util.UUID, 0, len(lv.uuid2pv))
- for uuid := range lv.uuid2pv {
- uuids = append(uuids, uuid)
+func (lv *LogicalVolume[PhysicalVolume]) PhysicalVolumes() map[DeviceID]PhysicalVolume {
+ dup := make(map[DeviceID]PhysicalVolume, len(lv.id2pv))
+ for k, v := range lv.id2pv {
+ dup[k] = v
}
- sort.Slice(uuids, func(i, j int) bool {
- return uuids[i].Cmp(uuids[j]) < 0
- })
- ret := make([]PhysicalVolume, 0, len(lv.uuid2pv))
- for _, uuid := range uuids {
- ret = append(ret, lv.uuid2pv[uuid])
- }
- return ret
+ return dup
}
func (lv *LogicalVolume[PhysicalVolume]) ClearMappings() {
@@ -69,22 +62,29 @@ func (lv *LogicalVolume[PhysicalVolume]) ClearMappings() {
lv.physical2logical = nil
}
-func (lv *LogicalVolume[PhysicalVolume]) AddMapping(laddr LogicalAddr, paddr QualifiedPhysicalAddr, size AddrDelta, flags *BlockGroupFlags) error {
+type Mapping struct {
+ LAddr LogicalAddr
+ PAddr QualifiedPhysicalAddr
+ Size AddrDelta
+ Flags *BlockGroupFlags
+}
+
+func (lv *LogicalVolume[PhysicalVolume]) AddMapping(m Mapping) 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 _, haveDev := lv.id2pv[m.PAddr.Dev]; !haveDev {
+ return fmt.Errorf("(%p).AddMapping: do not have a physical volume with id=%v",
+ lv, m.PAddr.Dev)
}
if lv.physical2logical == nil {
- lv.physical2logical = make(map[util.UUID][]devextMapping)
+ lv.physical2logical = make(map[DeviceID][]devextMapping)
}
// logical2physical
newChunk := chunkMapping{
- LAddr: laddr,
- PAddrs: []QualifiedPhysicalAddr{paddr},
- Size: size,
- Flags: flags,
+ LAddr: m.LAddr,
+ PAddrs: []QualifiedPhysicalAddr{m.PAddr},
+ Size: m.Size,
+ Flags: m.Flags,
}
var logicalOverlaps []chunkMapping
for _, chunk := range lv.logical2physical {
@@ -105,13 +105,13 @@ func (lv *LogicalVolume[PhysicalVolume]) AddMapping(laddr LogicalAddr, paddr Qua
// physical2logical
newExt := devextMapping{
- PAddr: paddr.Addr,
- LAddr: laddr,
- Size: size,
- Flags: flags,
+ PAddr: m.PAddr.Addr,
+ LAddr: m.LAddr,
+ Size: m.Size,
+ Flags: m.Flags,
}
var physicalOverlaps []devextMapping
- for _, ext := range lv.physical2logical[paddr.Dev] {
+ for _, ext := range lv.physical2logical[m.PAddr.Dev] {
switch newExt.cmpRange(ext) {
case 0:
physicalOverlaps = append(physicalOverlaps, ext)
@@ -140,11 +140,11 @@ func (lv *LogicalVolume[PhysicalVolume]) AddMapping(laddr LogicalAddr, paddr Qua
// physical2logical
for _, ext := range physicalOverlaps {
- lv.physical2logical[paddr.Dev] = util.RemoveAllFromSlice(lv.physical2logical[paddr.Dev], ext)
+ lv.physical2logical[m.PAddr.Dev] = util.RemoveAllFromSlice(lv.physical2logical[m.PAddr.Dev], ext)
}
- lv.physical2logical[paddr.Dev] = append(lv.physical2logical[paddr.Dev], newExt)
- sort.Slice(lv.physical2logical[paddr.Dev], func(i, j int) bool {
- return lv.physical2logical[paddr.Dev][i].PAddr < lv.physical2logical[paddr.Dev][j].PAddr
+ lv.physical2logical[m.PAddr.Dev] = append(lv.physical2logical[m.PAddr.Dev], newExt)
+ sort.Slice(lv.physical2logical[m.PAddr.Dev], func(i, j int) bool {
+ return lv.physical2logical[m.PAddr.Dev][i].PAddr < lv.physical2logical[m.PAddr.Dev][j].PAddr
})
// sanity check
@@ -160,10 +160,10 @@ func (lv *LogicalVolume[PhysicalVolume]) AddMapping(laddr LogicalAddr, paddr Qua
}
func (lv *LogicalVolume[PhysicalVolume]) fsck() error {
- physical2logical := make(map[util.UUID][]devextMapping)
+ physical2logical := make(map[DeviceID][]devextMapping)
for _, chunk := range lv.logical2physical {
for _, stripe := range chunk.PAddrs {
- if _, devOK := lv.uuid2pv[stripe.Dev]; !devOK {
+ if _, devOK := lv.id2pv[stripe.Dev]; !devOK {
return fmt.Errorf("(%p).fsck: chunk references physical volume %v which does not exist",
lv, stripe.Dev)
}
@@ -247,7 +247,7 @@ func (lv *LogicalVolume[PhysicalVolume]) maybeShortReadAt(dat []byte, laddr Logi
buf := make([]byte, len(dat))
first := true
for paddr := range paddrs {
- dev, ok := lv.uuid2pv[paddr.Dev]
+ dev, ok := lv.id2pv[paddr.Dev]
if !ok {
return 0, fmt.Errorf("device=%v does not exist", paddr.Dev)
}
@@ -287,7 +287,7 @@ func (lv *LogicalVolume[PhysicalVolume]) maybeShortWriteAt(dat []byte, laddr Log
}
for paddr := range paddrs {
- dev, ok := lv.uuid2pv[paddr.Dev]
+ dev, ok := lv.id2pv[paddr.Dev]
if !ok {
return 0, fmt.Errorf("device=%v does not exist", paddr.Dev)
}
diff --git a/pkg/btrfs/io2_fs.go b/pkg/btrfs/io2_fs.go
index 80f0862..dcf7df8 100644
--- a/pkg/btrfs/io2_fs.go
+++ b/pkg/btrfs/io2_fs.go
@@ -24,7 +24,7 @@ func (fs *FS) AddDevice(dev *Device) error {
if err != nil {
return err
}
- if err := fs.LV.AddPhysicalVolume(sb.Data.DevItem.DevUUID, dev); err != nil {
+ if err := fs.LV.AddPhysicalVolume(sb.Data.DevItem.DevID, dev); err != nil {
return err
}
fs.cacheSuperblocks = nil
@@ -68,7 +68,11 @@ func (fs *FS) Superblocks() ([]*util.Ref[PhysicalAddr, Superblock], error) {
return fs.cacheSuperblocks, nil
}
var ret []*util.Ref[PhysicalAddr, Superblock]
- for _, dev := range fs.LV.PhysicalVolumes() {
+ devs := fs.LV.PhysicalVolumes()
+ if len(devs) == 0 {
+ return nil, fmt.Errorf("no devices")
+ }
+ for _, dev := range devs {
sbs, err := dev.Superblocks()
if err != nil {
return nil, fmt.Errorf("file %q: %w", dev.Name(), err)
@@ -139,16 +143,8 @@ func (fs *FS) initDev(sb *util.Ref[PhysicalAddr, Superblock]) error {
return err
}
for _, chunk := range syschunks {
- for _, stripe := range chunk.Chunk.Stripes {
- if err := fs.LV.AddMapping(
- LogicalAddr(chunk.Key.Offset),
- QualifiedPhysicalAddr{
- Dev: stripe.DeviceUUID,
- Addr: stripe.Offset,
- },
- chunk.Chunk.Head.Size,
- &chunk.Chunk.Head.Type,
- ); err != nil {
+ for _, mapping := range chunk.Chunk.Mappings(chunk.Key) {
+ if err := fs.LV.AddMapping(mapping); err != nil {
return err
}
}
@@ -158,17 +154,8 @@ func (fs *FS) initDev(sb *util.Ref[PhysicalAddr, Superblock]) error {
if item.Head.Key.ItemType != btrfsitem.CHUNK_ITEM_KEY {
return nil
}
- body := item.Body.(btrfsitem.Chunk)
- for _, stripe := range body.Stripes {
- if err := fs.LV.AddMapping(
- LogicalAddr(item.Head.Key.Offset),
- QualifiedPhysicalAddr{
- Dev: stripe.DeviceUUID,
- Addr: stripe.Offset,
- },
- body.Head.Size,
- &body.Head.Type,
- ); err != nil {
+ for _, mapping := range item.Body.(btrfsitem.Chunk).Mappings(item.Head.Key) {
+ if err := fs.LV.AddMapping(mapping); err != nil {
return err
}
}
diff --git a/pkg/btrfsmisc/print_tree.go b/pkg/btrfsmisc/print_tree.go
index a57e69e..c11a294 100644
--- a/pkg/btrfsmisc/print_tree.go
+++ b/pkg/btrfsmisc/print_tree.go
@@ -174,7 +174,7 @@ func PrintTree(fs *btrfs.FS, root btrfs.LogicalAddr) error {
"\t\tseek_speed %v bandwidth %v\n"+
"\t\tuuid %v\n"+
"\t\tfsid %v\n",
- body.DeviceID, body.NumBytes, body.NumBytesUsed,
+ body.DevID, body.NumBytes, body.NumBytesUsed,
body.IOOptimalAlign, body.IOOptimalWidth, body.IOMinSize, body.Type,
body.Generation, body.StartOffset, body.DevGroup,
body.SeekSpeed, body.Bandwidth,