diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-06-26 22:19:29 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-06-26 22:19:41 -0600 |
commit | 8463b2bff37978124e5210a59590f1ac33e453c0 (patch) | |
tree | 37fc4c13f1fdaedf20ee48a53653414fbb3d9ed7 | |
parent | 64c04fc690ec5a276e11500691173962bbe4d99e (diff) |
use devid instead of devuuid, add a Mapping struct
-rw-r--r-- | cmd/btrfs-fsck/pass1.go | 4 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/item_chunk.go | 18 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/item_dev.go | 3 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/item_devextent.go | 12 | ||||
-rw-r--r-- | pkg/btrfs/btrfsvol/addr.go | 6 | ||||
-rw-r--r-- | pkg/btrfs/btrfsvol/lvm.go | 86 | ||||
-rw-r--r-- | pkg/btrfs/io2_fs.go | 33 | ||||
-rw-r--r-- | pkg/btrfsmisc/print_tree.go | 2 |
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, |