diff options
Diffstat (limited to 'lib/btrfs')
38 files changed, 334 insertions, 371 deletions
diff --git a/lib/btrfs/Makefile b/lib/btrfs/Makefile index 50577e0..f7f1422 100644 --- a/lib/btrfs/Makefile +++ b/lib/btrfs/Makefile @@ -26,22 +26,22 @@ btrfsitem/items_gen.go: btrfsitem/items.txt $(MAKEFILE_LIST) echo 'import ('; \ echo '"reflect"'; \ echo; \ - echo '"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal"'; \ + echo '"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim"'; \ echo ')'; \ echo 'const ('; \ - sed -E 's,(.*)=(.*) (.*),\1_KEY=internal.\1_KEY,' $<; \ + sed -E 's,(.*)=(.*) (.*),\1_KEY=btrfsprim.\1_KEY,' $<; \ echo ')'; \ echo 'var keytype2gotype = map[Type]reflect.Type{'; \ sed -En 's|(.*)=([^:]*) (.*)|\1_KEY: reflect.TypeOf(\3{}),|p' $<; \ echo '}'; \ - echo 'var untypedObjID2gotype = map[internal.ObjID]reflect.Type{'; \ - sed -En 's|UNTYPED=0:(.*) (.*)|internal.\1: reflect.TypeOf(\2{}),|p' $<; \ + echo 'var untypedObjID2gotype = map[btrfsprim.ObjID]reflect.Type{'; \ + sed -En 's|UNTYPED=0:(.*) (.*)|btrfsprim.\1: reflect.TypeOf(\2{}),|p' $<; \ echo '}'; \ sed -En 's,(.*)=(.*) (.+),\3,p' $< | LC_COLLATE=C sort -u | sed 's,.*,func (&) isItem() {},'; \ } | gofmt >$@ files += btrfsitem/items_gen.go -internal/itemtype.go: btrfsitem/items.txt $(MAKEFILE_LIST) +btrfsprim/itemtype.go: btrfsitem/items.txt $(MAKEFILE_LIST) { \ echo '// Code generated by Make. DO NOT EDIT.'; \ echo; \ @@ -63,23 +63,7 @@ internal/itemtype.go: btrfsitem/items.txt $(MAKEFILE_LIST) echo ' return fmt.Sprintf("%d", t)'; \ echo '}'; \ } | gofmt >$@ -files += internal/itemtype.go - -aliases_objid.go: internal/objid.go $(MAKEFILE_LIST) - { \ - echo '// Code generated by Make. DO NOT EDIT.'; \ - echo; \ - echo '// SPDX-License-Identifier: GPL-2.0-or-later'; \ - echo; \ - echo 'package btrfs'; \ - echo 'import ('; \ - echo '"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal"'; \ - echo ')'; \ - echo 'const('; \ - sed -En 's/^\s*(\S*_OBJECTIDS?)\s*=.*/\1 = internal.\1/p' <$<; \ - echo ')'; \ - } | gofmt >$@ -files += aliases_objid.go +files += btrfsprim/itemtype.go all: $(files) .PHONY: all diff --git a/lib/btrfs/aliases.go b/lib/btrfs/aliases.go deleted file mode 100644 index 6fe5661..0000000 --- a/lib/btrfs/aliases.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com> -// -// SPDX-License-Identifier: GPL-2.0-or-later - -package btrfs - -import ( - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" -) - -type ( - // (u)int64 types - - Generation = internal.Generation - ObjID = internal.ObjID - - // complex types - - Key = internal.Key - Time = internal.Time - UUID = internal.UUID -) diff --git a/lib/btrfs/aliases_objid.go b/lib/btrfs/aliases_objid.go deleted file mode 100644 index 21309b8..0000000 --- a/lib/btrfs/aliases_objid.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by Make. DO NOT EDIT. - -// SPDX-License-Identifier: GPL-2.0-or-later - -package btrfs - -import ( - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" -) - -const ( - ROOT_TREE_OBJECTID = internal.ROOT_TREE_OBJECTID - EXTENT_TREE_OBJECTID = internal.EXTENT_TREE_OBJECTID - CHUNK_TREE_OBJECTID = internal.CHUNK_TREE_OBJECTID - DEV_TREE_OBJECTID = internal.DEV_TREE_OBJECTID - FS_TREE_OBJECTID = internal.FS_TREE_OBJECTID - ROOT_TREE_DIR_OBJECTID = internal.ROOT_TREE_DIR_OBJECTID - CSUM_TREE_OBJECTID = internal.CSUM_TREE_OBJECTID - QUOTA_TREE_OBJECTID = internal.QUOTA_TREE_OBJECTID - UUID_TREE_OBJECTID = internal.UUID_TREE_OBJECTID - FREE_SPACE_TREE_OBJECTID = internal.FREE_SPACE_TREE_OBJECTID - BLOCK_GROUP_TREE_OBJECTID = internal.BLOCK_GROUP_TREE_OBJECTID - DEV_STATS_OBJECTID = internal.DEV_STATS_OBJECTID - BALANCE_OBJECTID = internal.BALANCE_OBJECTID - ORPHAN_OBJECTID = internal.ORPHAN_OBJECTID - TREE_LOG_OBJECTID = internal.TREE_LOG_OBJECTID - TREE_LOG_FIXUP_OBJECTID = internal.TREE_LOG_FIXUP_OBJECTID - TREE_RELOC_OBJECTID = internal.TREE_RELOC_OBJECTID - DATA_RELOC_TREE_OBJECTID = internal.DATA_RELOC_TREE_OBJECTID - EXTENT_CSUM_OBJECTID = internal.EXTENT_CSUM_OBJECTID - FREE_SPACE_OBJECTID = internal.FREE_SPACE_OBJECTID - FREE_INO_OBJECTID = internal.FREE_INO_OBJECTID - MULTIPLE_OBJECTIDS = internal.MULTIPLE_OBJECTIDS - FIRST_FREE_OBJECTID = internal.FIRST_FREE_OBJECTID - LAST_FREE_OBJECTID = internal.LAST_FREE_OBJECTID - FIRST_CHUNK_TREE_OBJECTID = internal.FIRST_CHUNK_TREE_OBJECTID - DEV_ITEMS_OBJECTID = internal.DEV_ITEMS_OBJECTID - EMPTY_SUBVOL_DIR_OBJECTID = internal.EMPTY_SUBVOL_DIR_OBJECTID -) diff --git a/lib/btrfs/btrfsitem/item_blockgroup.go b/lib/btrfs/btrfsitem/item_blockgroup.go index 776ff56..96ce218 100644 --- a/lib/btrfs/btrfsitem/item_blockgroup.go +++ b/lib/btrfs/btrfsitem/item_blockgroup.go @@ -6,15 +6,15 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" ) // key.objectid = logical_addr // 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"` // always BTRFS_FIRST_CHUNK_TREE_OBJECTID + ChunkObjectID btrfsprim.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/lib/btrfs/btrfsitem/item_chunk.go b/lib/btrfs/btrfsitem/item_chunk.go index fe2637d..1f1d577 100644 --- a/lib/btrfs/btrfsitem/item_chunk.go +++ b/lib/btrfs/btrfsitem/item_chunk.go @@ -6,8 +6,8 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" "git.lukeshu.com/btrfs-progs-ng/lib/containers" ) @@ -22,7 +22,7 @@ type Chunk struct { // CHUNK_ITEM=228 type ChunkHeader struct { Size btrfsvol.AddrDelta `bin:"off=0x0, siz=0x8"` - Owner internal.ObjID `bin:"off=0x8, siz=0x8"` // root referencing this chunk (always EXTENT_TREE_OBJECTID=2) + Owner btrfsprim.ObjID `bin:"off=0x8, siz=0x8"` // root referencing this chunk (always EXTENT_TREE_OBJECTID=2) StripeLen uint64 `bin:"off=0x10, siz=0x8"` // ??? Type btrfsvol.BlockGroupFlags `bin:"off=0x18, siz=0x8"` IOOptimalAlign uint32 `bin:"off=0x20, siz=0x4"` @@ -36,11 +36,11 @@ type ChunkHeader struct { type ChunkStripe struct { DeviceID btrfsvol.DeviceID `bin:"off=0x0, siz=0x8"` Offset btrfsvol.PhysicalAddr `bin:"off=0x8, siz=0x8"` - DeviceUUID internal.UUID `bin:"off=0x10, siz=0x10"` + DeviceUUID btrfsprim.UUID `bin:"off=0x10, siz=0x10"` binstruct.End `bin:"off=0x20"` } -func (chunk Chunk) Mappings(key internal.Key) []btrfsvol.Mapping { +func (chunk Chunk) Mappings(key btrfsprim.Key) []btrfsvol.Mapping { ret := make([]btrfsvol.Mapping, 0, len(chunk.Stripes)) for _, stripe := range chunk.Stripes { ret = append(ret, btrfsvol.Mapping{ diff --git a/lib/btrfs/btrfsitem/item_dev.go b/lib/btrfs/btrfsitem/item_dev.go index 020f2ca..fd7f458 100644 --- a/lib/btrfs/btrfsitem/item_dev.go +++ b/lib/btrfs/btrfsitem/item_dev.go @@ -6,8 +6,8 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" ) // key.objectid = BTRFS_DEV_ITEMS_OBJECTID @@ -22,15 +22,15 @@ type Dev struct { // DEV_ITEM=216 IOOptimalWidth uint32 `bin:"off=0x1c, siz=0x4"` IOMinSize uint32 `bin:"off=0x20, siz=0x4"` // sector size - Type uint64 `bin:"off=0x24, siz=0x8"` - Generation internal.Generation `bin:"off=0x2c, siz=0x8"` - StartOffset uint64 `bin:"off=0x34, siz=0x8"` - DevGroup uint32 `bin:"off=0x3c, siz=0x4"` - SeekSpeed uint8 `bin:"off=0x40, siz=0x1"` - Bandwidth uint8 `bin:"off=0x41, siz=0x1"` + Type uint64 `bin:"off=0x24, siz=0x8"` + Generation btrfsprim.Generation `bin:"off=0x2c, siz=0x8"` + StartOffset uint64 `bin:"off=0x34, siz=0x8"` + DevGroup uint32 `bin:"off=0x3c, siz=0x4"` + SeekSpeed uint8 `bin:"off=0x40, siz=0x1"` + Bandwidth uint8 `bin:"off=0x41, siz=0x1"` - DevUUID internal.UUID `bin:"off=0x42, siz=0x10"` - FSUUID internal.UUID `bin:"off=0x52, siz=0x10"` + DevUUID btrfsprim.UUID `bin:"off=0x42, siz=0x10"` + FSUUID btrfsprim.UUID `bin:"off=0x52, siz=0x10"` binstruct.End `bin:"off=0x62"` } diff --git a/lib/btrfs/btrfsitem/item_devextent.go b/lib/btrfs/btrfsitem/item_devextent.go index 4f26b27..8f5f05c 100644 --- a/lib/btrfs/btrfsitem/item_devextent.go +++ b/lib/btrfs/btrfsitem/item_devextent.go @@ -6,22 +6,22 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" ) // key.objectid = device_id // key.offset = physical_addr type DevExtent struct { // DEV_EXTENT=204 ChunkTree int64 `bin:"off=0, siz=8"` - ChunkObjectID internal.ObjID `bin:"off=8, siz=8"` + ChunkObjectID btrfsprim.ObjID `bin:"off=8, siz=8"` ChunkOffset btrfsvol.LogicalAddr `bin:"off=16, siz=8"` Length btrfsvol.AddrDelta `bin:"off=24, siz=8"` - ChunkTreeUUID internal.UUID `bin:"off=32, siz=16"` + ChunkTreeUUID btrfsprim.UUID `bin:"off=32, siz=16"` binstruct.End `bin:"off=48"` } -func (devext DevExtent) Mapping(key internal.Key) btrfsvol.Mapping { +func (devext DevExtent) Mapping(key btrfsprim.Key) btrfsvol.Mapping { return btrfsvol.Mapping{ LAddr: devext.ChunkOffset, PAddr: btrfsvol.QualifiedPhysicalAddr{ diff --git a/lib/btrfs/btrfsitem/item_dir.go b/lib/btrfs/btrfsitem/item_dir.go index 9df1b8d..836c477 100644 --- a/lib/btrfs/btrfsitem/item_dir.go +++ b/lib/btrfs/btrfsitem/item_dir.go @@ -10,7 +10,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct/binutil" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) const MaxNameLen = 255 @@ -24,11 +24,11 @@ func NameHash(dat []byte) uint64 { // - for DIR_ITEM and XATTR_ITEM = NameHash(name) // - for DIR_INDEX = index id in the directory (starting at 2, because "." and "..") type DirEntry struct { // DIR_ITEM=84 DIR_INDEX=96 XATTR_ITEM=24 - Location internal.Key `bin:"off=0x0, siz=0x11"` - TransID int64 `bin:"off=0x11, siz=8"` - DataLen uint16 `bin:"off=0x19, siz=2"` // [ignored-when-writing] - NameLen uint16 `bin:"off=0x1b, siz=2"` // [ignored-when-writing] - Type FileType `bin:"off=0x1d, siz=1"` + Location btrfsprim.Key `bin:"off=0x0, siz=0x11"` + TransID int64 `bin:"off=0x11, siz=8"` + DataLen uint16 `bin:"off=0x19, siz=2"` // [ignored-when-writing] + NameLen uint16 `bin:"off=0x1b, siz=2"` // [ignored-when-writing] + Type FileType `bin:"off=0x1d, siz=1"` binstruct.End `bin:"off=0x1e"` Data []byte `bin:"-"` Name []byte `bin:"-"` diff --git a/lib/btrfs/btrfsitem/item_extent.go b/lib/btrfs/btrfsitem/item_extent.go index e8cd9b9..97dc105 100644 --- a/lib/btrfs/btrfsitem/item_extent.go +++ b/lib/btrfs/btrfsitem/item_extent.go @@ -8,7 +8,7 @@ import ( "fmt" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) @@ -66,15 +66,15 @@ func (o Extent) MarshalBinary() ([]byte, error) { } type ExtentHeader struct { - Refs int64 `bin:"off=0, siz=8"` - Generation internal.Generation `bin:"off=8, siz=8"` - Flags ExtentFlags `bin:"off=16, siz=8"` + Refs int64 `bin:"off=0, siz=8"` + Generation btrfsprim.Generation `bin:"off=8, siz=8"` + Flags ExtentFlags `bin:"off=16, siz=8"` binstruct.End `bin:"off=24"` } type TreeBlockInfo struct { - Key internal.Key `bin:"off=0, siz=0x11"` - Level uint8 `bin:"off=0x11, siz=0x1"` + Key btrfsprim.Key `bin:"off=0, siz=0x11"` + Level uint8 `bin:"off=0x11, siz=0x1"` binstruct.End `bin:"off=0x12"` } diff --git a/lib/btrfs/btrfsitem/item_extentdataref.go b/lib/btrfs/btrfsitem/item_extentdataref.go index 6185202..74ce799 100644 --- a/lib/btrfs/btrfsitem/item_extentdataref.go +++ b/lib/btrfs/btrfsitem/item_extentdataref.go @@ -6,13 +6,13 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) type ExtentDataRef struct { // EXTENT_DATA_REF=178 - Root internal.ObjID `bin:"off=0, siz=8"` - ObjectID internal.ObjID `bin:"off=8, siz=8"` - Offset int64 `bin:"off=16, siz=8"` - Count int32 `bin:"off=24, siz=4"` + Root btrfsprim.ObjID `bin:"off=0, siz=8"` + ObjectID btrfsprim.ObjID `bin:"off=8, siz=8"` + Offset int64 `bin:"off=16, siz=8"` + Count int32 `bin:"off=24, siz=4"` binstruct.End `bin:"off=28"` } diff --git a/lib/btrfs/btrfsitem/item_fileextent.go b/lib/btrfs/btrfsitem/item_fileextent.go index b7e394e..83e5d34 100644 --- a/lib/btrfs/btrfsitem/item_fileextent.go +++ b/lib/btrfs/btrfsitem/item_fileextent.go @@ -8,15 +8,15 @@ import ( "fmt" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" ) // key.objectid = inode // key.offset = offset within file type FileExtent struct { // EXTENT_DATA=108 - Generation internal.Generation `bin:"off=0x0, siz=0x8"` // transaction ID that created this extent - RAMBytes int64 `bin:"off=0x8, siz=0x8"` // upper bound of what compressed data will decompress to + Generation btrfsprim.Generation `bin:"off=0x0, siz=0x8"` // transaction ID that created this extent + RAMBytes int64 `bin:"off=0x8, siz=0x8"` // upper bound of what compressed data will decompress to // 32 bits describing the data encoding Compression CompressionType `bin:"off=0x10, siz=0x1"` diff --git a/lib/btrfs/btrfsitem/item_inode.go b/lib/btrfs/btrfsitem/item_inode.go index 49b2031..8023156 100644 --- a/lib/btrfs/btrfsitem/item_inode.go +++ b/lib/btrfs/btrfsitem/item_inode.go @@ -6,28 +6,28 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) type Inode struct { // INODE_ITEM=1 - Generation internal.Generation `bin:"off=0x00, siz=0x08"` - TransID int64 `bin:"off=0x08, siz=0x08"` - Size int64 `bin:"off=0x10, siz=0x08"` // stat - NumBytes int64 `bin:"off=0x18, siz=0x08"` // allocated bytes, may be larger than size (or smaller if there are holes?) - BlockGroup int64 `bin:"off=0x20, siz=0x08"` - NLink int32 `bin:"off=0x28, siz=0x04"` // stat - UID int32 `bin:"off=0x2C, siz=0x04"` // stat - GID int32 `bin:"off=0x30, siz=0x04"` // stat - Mode StatMode `bin:"off=0x34, siz=0x04"` // stat - RDev int64 `bin:"off=0x38, siz=0x08"` // stat - Flags InodeFlags `bin:"off=0x40, siz=0x08"` // statx.stx_attributes, sorta - Sequence int64 `bin:"off=0x48, siz=0x08"` // NFS - Reserved [4]int64 `bin:"off=0x50, siz=0x20"` - ATime internal.Time `bin:"off=0x70, siz=0x0c"` // stat - CTime internal.Time `bin:"off=0x7c, siz=0x0c"` // stat - MTime internal.Time `bin:"off=0x88, siz=0x0c"` // stat - OTime internal.Time `bin:"off=0x94, siz=0x0c"` // statx.stx_btime (why is this called "otime" instead of "btime"?) + Generation btrfsprim.Generation `bin:"off=0x00, siz=0x08"` + TransID int64 `bin:"off=0x08, siz=0x08"` + Size int64 `bin:"off=0x10, siz=0x08"` // stat + NumBytes int64 `bin:"off=0x18, siz=0x08"` // allocated bytes, may be larger than size (or smaller if there are holes?) + BlockGroup int64 `bin:"off=0x20, siz=0x08"` + NLink int32 `bin:"off=0x28, siz=0x04"` // stat + UID int32 `bin:"off=0x2C, siz=0x04"` // stat + GID int32 `bin:"off=0x30, siz=0x04"` // stat + Mode StatMode `bin:"off=0x34, siz=0x04"` // stat + RDev int64 `bin:"off=0x38, siz=0x08"` // stat + Flags InodeFlags `bin:"off=0x40, siz=0x08"` // statx.stx_attributes, sorta + Sequence int64 `bin:"off=0x48, siz=0x08"` // NFS + Reserved [4]int64 `bin:"off=0x50, siz=0x20"` + ATime btrfsprim.Time `bin:"off=0x70, siz=0x0c"` // stat + CTime btrfsprim.Time `bin:"off=0x7c, siz=0x0c"` // stat + MTime btrfsprim.Time `bin:"off=0x88, siz=0x0c"` // stat + OTime btrfsprim.Time `bin:"off=0x94, siz=0x0c"` // statx.stx_btime (why is this called "otime" instead of "btime"?) binstruct.End `bin:"off=0xa0"` } diff --git a/lib/btrfs/btrfsitem/item_root.go b/lib/btrfs/btrfsitem/item_root.go index 7725363..2e0b327 100644 --- a/lib/btrfs/btrfsitem/item_root.go +++ b/lib/btrfs/btrfsitem/item_root.go @@ -6,37 +6,37 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) type Root struct { // ROOT_ITEM=132 Inode Inode `bin:"off=0x000, siz=0xa0"` - Generation internal.Generation `bin:"off=0x0a0, siz=0x08"` - RootDirID internal.ObjID `bin:"off=0x0a8, siz=0x08"` + Generation btrfsprim.Generation `bin:"off=0x0a0, siz=0x08"` + RootDirID btrfsprim.ObjID `bin:"off=0x0a8, siz=0x08"` ByteNr btrfsvol.LogicalAddr `bin:"off=0x0b0, siz=0x08"` ByteLimit int64 `bin:"off=0x0b8, siz=0x08"` BytesUsed int64 `bin:"off=0x0c0, siz=0x08"` LastSnapshot int64 `bin:"off=0x0c8, siz=0x08"` Flags RootFlags `bin:"off=0x0d0, siz=0x08"` Refs int32 `bin:"off=0x0d8, siz=0x04"` - DropProgress internal.Key `bin:"off=0x0dc, siz=0x11"` + DropProgress btrfsprim.Key `bin:"off=0x0dc, siz=0x11"` DropLevel uint8 `bin:"off=0x0ed, siz=0x01"` Level uint8 `bin:"off=0x0ee, siz=0x01"` - GenerationV2 internal.Generation `bin:"off=0x0ef, siz=0x08"` - UUID internal.UUID `bin:"off=0x0f7, siz=0x10"` - ParentUUID internal.UUID `bin:"off=0x107, siz=0x10"` - ReceivedUUID internal.UUID `bin:"off=0x117, siz=0x10"` + GenerationV2 btrfsprim.Generation `bin:"off=0x0ef, siz=0x08"` + UUID btrfsprim.UUID `bin:"off=0x0f7, siz=0x10"` + ParentUUID btrfsprim.UUID `bin:"off=0x107, siz=0x10"` + ReceivedUUID btrfsprim.UUID `bin:"off=0x117, siz=0x10"` CTransID int64 `bin:"off=0x127, siz=0x08"` OTransID int64 `bin:"off=0x12f, siz=0x08"` STransID int64 `bin:"off=0x137, siz=0x08"` RTransID int64 `bin:"off=0x13f, siz=0x08"` - CTime internal.Time `bin:"off=0x147, siz=0x0c"` - OTime internal.Time `bin:"off=0x153, siz=0x0c"` - STime internal.Time `bin:"off=0x15f, siz=0x0c"` - RTime internal.Time `bin:"off=0x16b, siz=0x0c"` - GlobalTreeID internal.ObjID `bin:"off=0x177, siz=0x08"` + CTime btrfsprim.Time `bin:"off=0x147, siz=0x0c"` + OTime btrfsprim.Time `bin:"off=0x153, siz=0x0c"` + STime btrfsprim.Time `bin:"off=0x15f, siz=0x0c"` + RTime btrfsprim.Time `bin:"off=0x16b, siz=0x0c"` + GlobalTreeID btrfsprim.ObjID `bin:"off=0x177, siz=0x08"` Reserved [7]int64 `bin:"off=0x17f, siz=0x38"` binstruct.End `bin:"off=0x1b7"` } diff --git a/lib/btrfs/btrfsitem/item_rootref.go b/lib/btrfs/btrfsitem/item_rootref.go index 1ee0ee4..d1dfd3b 100644 --- a/lib/btrfs/btrfsitem/item_rootref.go +++ b/lib/btrfs/btrfsitem/item_rootref.go @@ -9,13 +9,13 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct/binutil" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) type RootRef struct { // ROOT_REF=156 ROOT_BACKREF=144 - DirID internal.ObjID `bin:"off=0x00, siz=0x8"` - Sequence int64 `bin:"off=0x08, siz=0x8"` - NameLen uint16 `bin:"off=0x10, siz=0x2"` // [ignored-when-writing] + DirID btrfsprim.ObjID `bin:"off=0x00, siz=0x8"` + Sequence int64 `bin:"off=0x08, siz=0x8"` + NameLen uint16 `bin:"off=0x10, siz=0x2"` // [ignored-when-writing] binstruct.End `bin:"off=0x12"` Name []byte `bin:"-"` } diff --git a/lib/btrfs/btrfsitem/item_untyped.go b/lib/btrfs/btrfsitem/item_untyped.go index 04915c6..acf4ebe 100644 --- a/lib/btrfs/btrfsitem/item_untyped.go +++ b/lib/btrfs/btrfsitem/item_untyped.go @@ -6,13 +6,13 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) type FreeSpaceHeader struct { // UNTYPED=0:FREE_SPACE_OBJECTID - Location internal.Key `bin:"off=0x00, siz=0x11"` - Generation internal.Generation `bin:"off=0x11, siz=0x8"` - NumEntries int64 `bin:"off=0x19, siz=0x8"` - NumBitmaps int64 `bin:"off=0x21, siz=0x8"` + Location btrfsprim.Key `bin:"off=0x00, siz=0x11"` + Generation btrfsprim.Generation `bin:"off=0x11, siz=0x8"` + NumEntries int64 `bin:"off=0x19, siz=0x8"` + NumBitmaps int64 `bin:"off=0x21, siz=0x8"` binstruct.End `bin:"off=0x29"` } diff --git a/lib/btrfs/btrfsitem/item_uuid.go b/lib/btrfs/btrfsitem/item_uuid.go index ca82652..03823ce 100644 --- a/lib/btrfs/btrfsitem/item_uuid.go +++ b/lib/btrfs/btrfsitem/item_uuid.go @@ -6,7 +6,7 @@ package btrfsitem import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) // The Key for this item is a UUID, and the item is a subvolume IDs @@ -15,6 +15,6 @@ import ( // key.objectid = first half of UUID // key.offset = second half of UUID type UUIDMap struct { // UUID_SUBVOL=251 UUID_RECEIVED_SUBVOL=252 - ObjID internal.ObjID `bin:"off=0, siz=8"` + ObjID btrfsprim.ObjID `bin:"off=0, siz=8"` binstruct.End `bin:"off=8"` } diff --git a/lib/btrfs/btrfsitem/items.go b/lib/btrfs/btrfsitem/items.go index 35d8b4f..29b3cb0 100644 --- a/lib/btrfs/btrfsitem/items.go +++ b/lib/btrfs/btrfsitem/items.go @@ -9,12 +9,12 @@ import ( "reflect" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" ) -type Type = internal.ItemType +type Type = btrfsprim.ItemType type Item interface { isItem() @@ -37,7 +37,7 @@ func (o *Error) UnmarshalBinary(dat []byte) (int, error) { } // Rather than returning a separate error value, return an Error item. -func UnmarshalItem(key internal.Key, csumType btrfssum.CSumType, dat []byte) Item { +func UnmarshalItem(key btrfsprim.Key, csumType btrfssum.CSumType, dat []byte) Item { var gotyp reflect.Type if key.ItemType == UNTYPED_KEY { var ok bool diff --git a/lib/btrfs/btrfsitem/items_gen.go b/lib/btrfs/btrfsitem/items_gen.go index d21cd3e..89bc171 100644 --- a/lib/btrfs/btrfsitem/items_gen.go +++ b/lib/btrfs/btrfsitem/items_gen.go @@ -7,39 +7,39 @@ package btrfsitem import ( "reflect" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) const ( - BLOCK_GROUP_ITEM_KEY = internal.BLOCK_GROUP_ITEM_KEY - CHUNK_ITEM_KEY = internal.CHUNK_ITEM_KEY - DEV_EXTENT_KEY = internal.DEV_EXTENT_KEY - DEV_ITEM_KEY = internal.DEV_ITEM_KEY - DIR_INDEX_KEY = internal.DIR_INDEX_KEY - DIR_ITEM_KEY = internal.DIR_ITEM_KEY - EXTENT_CSUM_KEY = internal.EXTENT_CSUM_KEY - EXTENT_DATA_KEY = internal.EXTENT_DATA_KEY - EXTENT_DATA_REF_KEY = internal.EXTENT_DATA_REF_KEY - EXTENT_ITEM_KEY = internal.EXTENT_ITEM_KEY - FREE_SPACE_BITMAP_KEY = internal.FREE_SPACE_BITMAP_KEY - FREE_SPACE_EXTENT_KEY = internal.FREE_SPACE_EXTENT_KEY - FREE_SPACE_INFO_KEY = internal.FREE_SPACE_INFO_KEY - INODE_ITEM_KEY = internal.INODE_ITEM_KEY - INODE_REF_KEY = internal.INODE_REF_KEY - METADATA_ITEM_KEY = internal.METADATA_ITEM_KEY - ORPHAN_ITEM_KEY = internal.ORPHAN_ITEM_KEY - PERSISTENT_ITEM_KEY = internal.PERSISTENT_ITEM_KEY - QGROUP_RELATION_KEY = internal.QGROUP_RELATION_KEY - ROOT_BACKREF_KEY = internal.ROOT_BACKREF_KEY - ROOT_ITEM_KEY = internal.ROOT_ITEM_KEY - ROOT_REF_KEY = internal.ROOT_REF_KEY - SHARED_BLOCK_REF_KEY = internal.SHARED_BLOCK_REF_KEY - SHARED_DATA_REF_KEY = internal.SHARED_DATA_REF_KEY - TREE_BLOCK_REF_KEY = internal.TREE_BLOCK_REF_KEY - UNTYPED_KEY = internal.UNTYPED_KEY - UUID_RECEIVED_SUBVOL_KEY = internal.UUID_RECEIVED_SUBVOL_KEY - UUID_SUBVOL_KEY = internal.UUID_SUBVOL_KEY - XATTR_ITEM_KEY = internal.XATTR_ITEM_KEY + BLOCK_GROUP_ITEM_KEY = btrfsprim.BLOCK_GROUP_ITEM_KEY + CHUNK_ITEM_KEY = btrfsprim.CHUNK_ITEM_KEY + DEV_EXTENT_KEY = btrfsprim.DEV_EXTENT_KEY + DEV_ITEM_KEY = btrfsprim.DEV_ITEM_KEY + DIR_INDEX_KEY = btrfsprim.DIR_INDEX_KEY + DIR_ITEM_KEY = btrfsprim.DIR_ITEM_KEY + EXTENT_CSUM_KEY = btrfsprim.EXTENT_CSUM_KEY + EXTENT_DATA_KEY = btrfsprim.EXTENT_DATA_KEY + EXTENT_DATA_REF_KEY = btrfsprim.EXTENT_DATA_REF_KEY + EXTENT_ITEM_KEY = btrfsprim.EXTENT_ITEM_KEY + FREE_SPACE_BITMAP_KEY = btrfsprim.FREE_SPACE_BITMAP_KEY + FREE_SPACE_EXTENT_KEY = btrfsprim.FREE_SPACE_EXTENT_KEY + FREE_SPACE_INFO_KEY = btrfsprim.FREE_SPACE_INFO_KEY + INODE_ITEM_KEY = btrfsprim.INODE_ITEM_KEY + INODE_REF_KEY = btrfsprim.INODE_REF_KEY + METADATA_ITEM_KEY = btrfsprim.METADATA_ITEM_KEY + ORPHAN_ITEM_KEY = btrfsprim.ORPHAN_ITEM_KEY + PERSISTENT_ITEM_KEY = btrfsprim.PERSISTENT_ITEM_KEY + QGROUP_RELATION_KEY = btrfsprim.QGROUP_RELATION_KEY + ROOT_BACKREF_KEY = btrfsprim.ROOT_BACKREF_KEY + ROOT_ITEM_KEY = btrfsprim.ROOT_ITEM_KEY + ROOT_REF_KEY = btrfsprim.ROOT_REF_KEY + SHARED_BLOCK_REF_KEY = btrfsprim.SHARED_BLOCK_REF_KEY + SHARED_DATA_REF_KEY = btrfsprim.SHARED_DATA_REF_KEY + TREE_BLOCK_REF_KEY = btrfsprim.TREE_BLOCK_REF_KEY + UNTYPED_KEY = btrfsprim.UNTYPED_KEY + UUID_RECEIVED_SUBVOL_KEY = btrfsprim.UUID_RECEIVED_SUBVOL_KEY + UUID_SUBVOL_KEY = btrfsprim.UUID_SUBVOL_KEY + XATTR_ITEM_KEY = btrfsprim.XATTR_ITEM_KEY ) var keytype2gotype = map[Type]reflect.Type{ @@ -72,8 +72,8 @@ var keytype2gotype = map[Type]reflect.Type{ UUID_SUBVOL_KEY: reflect.TypeOf(UUIDMap{}), XATTR_ITEM_KEY: reflect.TypeOf(DirEntry{}), } -var untypedObjID2gotype = map[internal.ObjID]reflect.Type{ - internal.FREE_SPACE_OBJECTID: reflect.TypeOf(FreeSpaceHeader{}), +var untypedObjID2gotype = map[btrfsprim.ObjID]reflect.Type{ + btrfsprim.FREE_SPACE_OBJECTID: reflect.TypeOf(FreeSpaceHeader{}), } func (BlockGroup) isItem() {} diff --git a/lib/btrfs/btrfsitem/items_test.go b/lib/btrfs/btrfsitem/items_test.go index aba8ca2..46f2feb 100644 --- a/lib/btrfs/btrfsitem/items_test.go +++ b/lib/btrfs/btrfsitem/items_test.go @@ -11,12 +11,12 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" ) func FuzzRoundTrip(f *testing.F) { - keySize := binstruct.StaticSize(internal.Key{}) + keySize := binstruct.StaticSize(btrfsprim.Key{}) sumtypeSize := binstruct.StaticSize(btrfssum.CSumType(0)) f.Add(make([]byte, 256)) @@ -31,7 +31,7 @@ func FuzzRoundTrip(f *testing.F) { // key - var key internal.Key + var key btrfsprim.Key n, err := binstruct.Unmarshal(keyInDat, &key) require.NoError(t, err, "binstruct.Unmarshal(dat, &key)") require.Equal(t, keySize, n, "binstruct.Unmarshal(dat, &key)") diff --git a/lib/btrfs/internal/itemtype.go b/lib/btrfs/btrfsprim/itemtype.go index 9ba4a23..89cff21 100644 --- a/lib/btrfs/internal/itemtype.go +++ b/lib/btrfs/btrfsprim/itemtype.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -package internal +package btrfsprim import "fmt" diff --git a/lib/btrfs/internal/misc.go b/lib/btrfs/btrfsprim/misc.go index 3bc5402..0ebbe19 100644 --- a/lib/btrfs/internal/misc.go +++ b/lib/btrfs/btrfsprim/misc.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package internal +package btrfsprim import ( "fmt" diff --git a/lib/btrfs/internal/objid.go b/lib/btrfs/btrfsprim/objid.go index fa9eb4d..17a0eeb 100644 --- a/lib/btrfs/internal/objid.go +++ b/lib/btrfs/btrfsprim/objid.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package internal +package btrfsprim import ( "fmt" diff --git a/lib/btrfs/internal/uuid.go b/lib/btrfs/btrfsprim/uuid.go index 96807b6..4e3fd6b 100644 --- a/lib/btrfs/internal/uuid.go +++ b/lib/btrfs/btrfsprim/uuid.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package internal +package btrfsprim import ( "encoding" diff --git a/lib/btrfs/internal/uuid_test.go b/lib/btrfs/btrfsprim/uuid_test.go index dfc3688..9fff760 100644 --- a/lib/btrfs/internal/uuid_test.go +++ b/lib/btrfs/btrfsprim/uuid_test.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package internal_test +package btrfsprim_test import ( "fmt" @@ -10,18 +10,18 @@ import ( "github.com/stretchr/testify/assert" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) func TestParseUUID(t *testing.T) { t.Parallel() type TestCase struct { Input string - OutputVal internal.UUID + OutputVal btrfsprim.UUID OutputErr string } testcases := map[string]TestCase{ - "basic": {Input: "a0dd94ed-e60c-42e8-8632-64e8d4765a43", OutputVal: internal.UUID{0xa0, 0xdd, 0x94, 0xed, 0xe6, 0x0c, 0x42, 0xe8, 0x86, 0x32, 0x64, 0xe8, 0xd4, 0x76, 0x5a, 0x43}}, + "basic": {Input: "a0dd94ed-e60c-42e8-8632-64e8d4765a43", OutputVal: btrfsprim.UUID{0xa0, 0xdd, 0x94, 0xed, 0xe6, 0x0c, 0x42, 0xe8, 0x86, 0x32, 0x64, 0xe8, 0xd4, 0x76, 0x5a, 0x43}}, "too-long": {Input: "a0dd94ed-e60c-42e8-8632-64e8d4765a43a", OutputErr: `too long to be a UUID: "a0dd94ed-e60c-42e8-8632-64e8d4765a43"|"a"`}, "bad char": {Input: "a0dd94ej-e60c-42e8-8632-64e8d4765a43a", OutputErr: `illegal byte in UUID: "a0dd94e"|"j"|"-e60c-42e8-8632-64e8d4765a43a"`}, } @@ -29,7 +29,7 @@ func TestParseUUID(t *testing.T) { tc := tc t.Run(tcName, func(t *testing.T) { t.Parallel() - val, err := internal.ParseUUID(tc.Input) + val, err := btrfsprim.ParseUUID(tc.Input) assert.Equal(t, tc.OutputVal, val) if tc.OutputErr == "" { assert.NoError(t, err) @@ -43,18 +43,18 @@ func TestParseUUID(t *testing.T) { func TestUUIDFormat(t *testing.T) { t.Parallel() type TestCase struct { - InputUUID internal.UUID + InputUUID btrfsprim.UUID InputFmt string Output string } - uuid := internal.MustParseUUID("a0dd94ed-e60c-42e8-8632-64e8d4765a43") + uuid := btrfsprim.MustParseUUID("a0dd94ed-e60c-42e8-8632-64e8d4765a43") testcases := map[string]TestCase{ "s": {InputUUID: uuid, InputFmt: "%s", Output: "a0dd94ed-e60c-42e8-8632-64e8d4765a43"}, "x": {InputUUID: uuid, InputFmt: "%x", Output: "a0dd94ede60c42e8863264e8d4765a43"}, "X": {InputUUID: uuid, InputFmt: "%X", Output: "A0DD94EDE60C42E8863264E8D4765A43"}, "v": {InputUUID: uuid, InputFmt: "%v", Output: "a0dd94ed-e60c-42e8-8632-64e8d4765a43"}, "40s": {InputUUID: uuid, InputFmt: "|% 40s", Output: "| a0dd94ed-e60c-42e8-8632-64e8d4765a43"}, - "#115v": {InputUUID: uuid, InputFmt: "|%#115v", Output: "| internal.UUID{0xa0, 0xdd, 0x94, 0xed, 0xe6, 0xc, 0x42, 0xe8, 0x86, 0x32, 0x64, 0xe8, 0xd4, 0x76, 0x5a, 0x43}"}, + "#115v": {InputUUID: uuid, InputFmt: "|%#115v", Output: "| btrfsprim.UUID{0xa0, 0xdd, 0x94, 0xed, 0xe6, 0xc, 0x42, 0xe8, 0x86, 0x32, 0x64, 0xe8, 0xd4, 0x76, 0x5a, 0x43}"}, } for tcName, tc := range testcases { tc := tc diff --git a/lib/btrfs/btree_ops.go b/lib/btrfs/btrfstree/ops.go index b590aa7..83c08c4 100644 --- a/lib/btrfs/btree_ops.go +++ b/lib/btrfs/btrfstree/ops.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package btrfs +package btrfstree import ( "context" @@ -14,6 +14,7 @@ import ( "github.com/datawire/dlib/derror" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" "git.lukeshu.com/btrfs-progs-ng/lib/diskio" "git.lukeshu.com/btrfs-progs-ng/lib/slices" @@ -35,30 +36,24 @@ type Trees interface { // 002 (read node) // 003 .Node() (or .BadNode()) // for item in node.items: - // if internal: + // if btrfsprim: // 004 .PreKeyPointer() // 005 (recurse) // 006 .PostKeyPointer() // else: // 004 .Item() (or .BadItem()) // 007 .PostNode() - TreeWalk(ctx context.Context, treeID ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) + TreeWalk(ctx context.Context, treeID btrfsprim.ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) - TreeLookup(treeID ObjID, key Key) (Item, error) - TreeSearch(treeID ObjID, fn func(key Key, size uint32) int) (Item, error) // size is math.MaxUint32 for key-pointers + TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (Item, error) + TreeSearch(treeID btrfsprim.ObjID, fn func(key btrfsprim.Key, size uint32) int) (Item, error) // size is math.MaxUint32 for key-pointers // If some items are able to be read, but there is an error reading the // full set, then it might return *both* a list of items and an error. // // If no such item is found, an error that is io/fs.ErrNotExist is // returned. - TreeSearchAll(treeID ObjID, fn func(key Key, size uint32) int) ([]Item, error) // size is math.MaxUint32 for key-pointers - - // For bootstrapping purposes. - Superblock() (*Superblock, error) - - // For reading raw data extants pointed at by tree items. - ReadAt(p []byte, off btrfsvol.LogicalAddr) (int, error) + TreeSearchAll(treeID btrfsprim.ObjID, fn func(key btrfsprim.Key, size uint32) int) ([]Item, error) // size is math.MaxUint32 for key-pointers } type TreeWalkHandler struct { @@ -72,7 +67,7 @@ type TreeWalkHandler struct { Node func(TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node]) error BadNode func(TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) error PostNode func(TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node]) error - // Callbacks for items on internal nodes + // Callbacks for items on btrfsprim nodes PreKeyPointer func(TreePath, KeyPointer) error PostKeyPointer func(TreePath, KeyPointer) error // Callbacks for items on leaf nodes @@ -91,9 +86,22 @@ func (e *TreeError) Error() string { return fmt.Sprintf("%v: %v", e.Path, e.Err) } +type NodeSource interface { + Superblock() (*Superblock, error) + ReadNode(TreePath) (*diskio.Ref[btrfsvol.LogicalAddr, Node], error) +} + +type TreesImpl struct { + NodeSource +} + // TreeWalk implements the 'Trees' interface. -func (fs *FS) TreeWalk(ctx context.Context, treeID ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) { - rootInfo, err := LookupTreeRoot(fs, treeID) +func (fs TreesImpl) TreeWalk(ctx context.Context, treeID btrfsprim.ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) { + sb, err := fs.Superblock() + if err != nil { + errHandle(&TreeError{Path: TreePath{{FromTree: treeID}}, Err: err}) + } + rootInfo, err := LookupTreeRoot(fs, *sb, treeID) if err != nil { errHandle(&TreeError{Path: TreePath{{FromTree: treeID}}, Err: err}) return @@ -103,7 +111,7 @@ func (fs *FS) TreeWalk(ctx context.Context, treeID ObjID, errHandle func(*TreeEr // TreeWalk is a utility function to help with implementing the 'Trees' // interface. -func (fs *FS) RawTreeWalk(ctx context.Context, rootInfo TreeRoot, errHandle func(*TreeError), cbs TreeWalkHandler) { +func (fs TreesImpl) RawTreeWalk(ctx context.Context, rootInfo TreeRoot, errHandle func(*TreeError), cbs TreeWalkHandler) { path := TreePath{{ FromTree: rootInfo.TreeID, FromGeneration: rootInfo.Generation, @@ -114,7 +122,7 @@ func (fs *FS) RawTreeWalk(ctx context.Context, rootInfo TreeRoot, errHandle func fs.treeWalk(ctx, path, errHandle, cbs) } -func (fs *FS) treeWalk(ctx context.Context, path TreePath, errHandle func(*TreeError), cbs TreeWalkHandler) { +func (fs TreesImpl) treeWalk(ctx context.Context, path TreePath, errHandle func(*TreeError), cbs TreeWalkHandler) { if ctx.Err() != nil { return } @@ -225,7 +233,7 @@ func (fs *FS) treeWalk(ctx context.Context, path TreePath, errHandle func(*TreeE } } -func (fs *FS) treeSearch(treeRoot TreeRoot, fn func(Key, uint32) int) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) { +func (fs TreesImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key, uint32) int) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) { path := TreePath{{ FromTree: treeRoot.TreeID, FromGeneration: treeRoot.Generation, @@ -243,7 +251,7 @@ func (fs *FS) treeSearch(treeRoot TreeRoot, fn func(Key, uint32) int) (TreePath, } if node.Data.Head.Level > 0 { - // internal node + // btrfsprim node // Search for the right-most node.Data.BodyInternal item for which // `fn(item.Key) >= 0`. @@ -295,7 +303,7 @@ func (fs *FS) treeSearch(treeRoot TreeRoot, fn func(Key, uint32) int) (TreePath, } } -func (fs *FS) prev(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) { +func (fs TreesImpl) prev(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) { var err error path = path.DeepCopy() @@ -351,7 +359,7 @@ func (fs *FS) prev(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) return path, node, nil } -func (fs *FS) next(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) { +func (fs TreesImpl) next(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) { var err error path = path.DeepCopy() @@ -423,8 +431,12 @@ func (fs *FS) next(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) } // TreeSearch implements the 'Trees' interface. -func (fs *FS) TreeSearch(treeID ObjID, fn func(Key, uint32) int) (Item, error) { - rootInfo, err := LookupTreeRoot(fs, treeID) +func (fs TreesImpl) TreeSearch(treeID btrfsprim.ObjID, fn func(btrfsprim.Key, uint32) int) (Item, error) { + sb, err := fs.Superblock() + if err != nil { + return Item{}, err + } + rootInfo, err := LookupTreeRoot(fs, *sb, treeID) if err != nil { return Item{}, err } @@ -436,14 +448,14 @@ func (fs *FS) TreeSearch(treeID ObjID, fn func(Key, uint32) int) (Item, error) { } // KeySearch returns a comparator suitable to be passed to TreeSearch. -func KeySearch(fn func(Key) int) func(Key, uint32) int { - return func(key Key, _ uint32) int { +func KeySearch(fn func(btrfsprim.Key) int) func(btrfsprim.Key, uint32) int { + return func(key btrfsprim.Key, _ uint32) int { return fn(key) } } // TreeLookup implements the 'Trees' interface. -func (fs *FS) TreeLookup(treeID ObjID, key Key) (Item, error) { +func (fs TreesImpl) TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (Item, error) { item, err := fs.TreeSearch(treeID, KeySearch(key.Cmp)) if err != nil { err = fmt.Errorf("item with key=%v: %w", key, err) @@ -452,8 +464,12 @@ func (fs *FS) TreeLookup(treeID ObjID, key Key) (Item, error) { } // TreeSearchAll implements the 'Trees' interface. -func (fs *FS) TreeSearchAll(treeID ObjID, fn func(Key, uint32) int) ([]Item, error) { - rootInfo, err := LookupTreeRoot(fs, treeID) +func (fs TreesImpl) TreeSearchAll(treeID btrfsprim.ObjID, fn func(btrfsprim.Key, uint32) int) ([]Item, error) { + sb, err := fs.Superblock() + if err != nil { + return nil, err + } + rootInfo, err := LookupTreeRoot(fs, *sb, treeID) if err != nil { return nil, err } diff --git a/lib/btrfs/btree_path.go b/lib/btrfs/btrfstree/path.go index 0124aea..99461a4 100644 --- a/lib/btrfs/btree_path.go +++ b/lib/btrfs/btrfstree/path.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package btrfs +package btrfstree import ( "fmt" @@ -10,6 +10,7 @@ import ( "strings" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" ) @@ -64,11 +65,11 @@ type TreePath []TreePathElem type TreePathElem struct { // FromTree is the owning tree ID of the parent node; or the // well-known tree ID if this is the root. - FromTree ObjID + FromTree btrfsprim.ObjID // FromGeneration is the generation of the parent node the // parent node; or generation stored in the superblock if this // is the root. - FromGeneration Generation + FromGeneration btrfsprim.Generation // FromItemIdx is the index of this KeyPointer in the parent // Node; or -1 if this is the root and there is no KeyPointer. FromItemIdx int diff --git a/lib/btrfs/btree_util.go b/lib/btrfs/btrfstree/root.go index 2076114..41aac69 100644 --- a/lib/btrfs/btree_util.go +++ b/lib/btrfs/btrfstree/root.go @@ -2,54 +2,51 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package btrfs +package btrfstree import ( "fmt" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" ) // A TreeRoot is more-or-less a btrfsitem.Root, but simpler; returned by // LookupTreeRoot. type TreeRoot struct { - TreeID ObjID + TreeID btrfsprim.ObjID RootNode btrfsvol.LogicalAddr Level uint8 - Generation Generation + Generation btrfsprim.Generation } // LookupTreeRoot is a utility function to help with implementing the 'Trees' // interface. -func LookupTreeRoot(fs Trees, treeID ObjID) (*TreeRoot, error) { - sb, err := fs.Superblock() - if err != nil { - return nil, err - } +func LookupTreeRoot(fs Trees, sb Superblock, treeID btrfsprim.ObjID) (*TreeRoot, error) { switch treeID { - case ROOT_TREE_OBJECTID: + case btrfsprim.ROOT_TREE_OBJECTID: return &TreeRoot{ TreeID: treeID, RootNode: sb.RootTree, Level: sb.RootLevel, Generation: sb.Generation, // XXX: same generation as LOG_TREE? }, nil - case CHUNK_TREE_OBJECTID: + case btrfsprim.CHUNK_TREE_OBJECTID: return &TreeRoot{ TreeID: treeID, RootNode: sb.ChunkTree, Level: sb.ChunkLevel, Generation: sb.ChunkRootGeneration, }, nil - case TREE_LOG_OBJECTID: + case btrfsprim.TREE_LOG_OBJECTID: return &TreeRoot{ TreeID: treeID, RootNode: sb.LogTree, Level: sb.LogLevel, Generation: sb.Generation, // XXX: same generation as ROOT_TREE? }, nil - case BLOCK_GROUP_TREE_OBJECTID: + case btrfsprim.BLOCK_GROUP_TREE_OBJECTID: return &TreeRoot{ TreeID: treeID, RootNode: sb.BlockGroupRoot, @@ -57,11 +54,11 @@ func LookupTreeRoot(fs Trees, treeID ObjID) (*TreeRoot, error) { Generation: sb.BlockGroupRootGeneration, }, nil default: - rootItem, err := fs.TreeSearch(ROOT_TREE_OBJECTID, func(key Key, _ uint32) int { + rootItem, err := fs.TreeSearch(btrfsprim.ROOT_TREE_OBJECTID, func(key btrfsprim.Key, _ uint32) int { if key.ObjectID == treeID && key.ItemType == btrfsitem.ROOT_ITEM_KEY { return 0 } - return Key{ + return btrfsprim.Key{ ObjectID: treeID, ItemType: btrfsitem.ROOT_ITEM_KEY, Offset: 0, diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 index a96f559..a96f559 100644 --- a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 +++ b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca index d5c153f..d5c153f 100644 --- a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca +++ b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 index 6a2309e..6a2309e 100644 --- a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 +++ b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 index 50b960e..50b960e 100644 --- a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 +++ b/lib/btrfs/btrfstree/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 diff --git a/lib/btrfs/types_node.go b/lib/btrfs/btrfstree/types_node.go index 7d66f60..aecdf9c 100644 --- a/lib/btrfs/types_node.go +++ b/lib/btrfs/btrfstree/types_node.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package btrfs +package btrfstree import ( "encoding/binary" @@ -11,6 +11,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" "git.lukeshu.com/btrfs-progs-ng/lib/containers" @@ -74,7 +75,7 @@ type Node struct { // The node's body (which one of these is present depends on // the node's type, as specified in the header) - BodyInternal []KeyPointer // for internal nodes + BodyInternal []KeyPointer // for btrfsprim nodes BodyLeaf []Item // for leave nodes Padding []byte @@ -82,15 +83,15 @@ type Node struct { type NodeHeader struct { Checksum btrfssum.CSum `bin:"off=0x0, siz=0x20"` - MetadataUUID UUID `bin:"off=0x20, siz=0x10"` + MetadataUUID btrfsprim.UUID `bin:"off=0x20, siz=0x10"` Addr btrfsvol.LogicalAddr `bin:"off=0x30, siz=0x8"` // Logical address of this node Flags NodeFlags `bin:"off=0x38, siz=0x7"` BackrefRev BackrefRev `bin:"off=0x3f, siz=0x1"` - ChunkTreeUUID UUID `bin:"off=0x40, siz=0x10"` - Generation Generation `bin:"off=0x50, siz=0x8"` - Owner ObjID `bin:"off=0x58, siz=0x8"` // The ID of the tree that contains this node + ChunkTreeUUID btrfsprim.UUID `bin:"off=0x40, siz=0x10"` + Generation btrfsprim.Generation `bin:"off=0x50, siz=0x8"` + Owner btrfsprim.ObjID `bin:"off=0x58, siz=0x8"` // The ID of the tree that contains this node NumItems uint32 `bin:"off=0x60, siz=0x4"` // [ignored-when-writing] - Level uint8 `bin:"off=0x64, siz=0x1"` // 0 for leaf nodes, >=1 for internal nodes + Level uint8 `bin:"off=0x64, siz=0x1"` // 0 for leaf nodes, >=1 for btrfsprim nodes binstruct.End `bin:"off=0x65"` } @@ -105,29 +106,29 @@ func (node Node) MaxItems() uint32 { } } -func (node Node) MinItem() (Key, bool) { +func (node Node) MinItem() (btrfsprim.Key, bool) { if node.Head.Level > 0 { if len(node.BodyInternal) == 0 { - return Key{}, false + return btrfsprim.Key{}, false } return node.BodyInternal[0].Key, true } else { if len(node.BodyLeaf) == 0 { - return Key{}, false + return btrfsprim.Key{}, false } return node.BodyLeaf[0].Key, true } } -func (node Node) MaxItem() (Key, bool) { +func (node Node) MaxItem() (btrfsprim.Key, bool) { if node.Head.Level > 0 { if len(node.BodyInternal) == 0 { - return Key{}, false + return btrfsprim.Key{}, false } return node.BodyInternal[len(node.BodyInternal)-1].Key, true } else { if len(node.BodyLeaf) == 0 { - return Key{}, false + return btrfsprim.Key{}, false } return node.BodyLeaf[len(node.BodyLeaf)-1].Key, true } @@ -175,7 +176,7 @@ func (node *Node) UnmarshalBinary(nodeBuf []byte) (int, error) { _n, err := node.unmarshalInternal(nodeBuf[n:]) n += _n if err != nil { - return n, fmt.Errorf("internal: %w", err) + return n, fmt.Errorf("btrfsprim: %w", err) } } else { _n, err := node.unmarshalLeaf(nodeBuf[n:]) @@ -230,12 +231,12 @@ func (node Node) MarshalBinary() ([]byte, error) { return buf, nil } -// Node: "internal" //////////////////////////////////////////////////////////////////////////////// +// Node: "btrfsprim" //////////////////////////////////////////////////////////////////////////////// type KeyPointer struct { - Key Key `bin:"off=0x0, siz=0x11"` + Key btrfsprim.Key `bin:"off=0x0, siz=0x11"` BlockPtr btrfsvol.LogicalAddr `bin:"off=0x11, siz=0x8"` - Generation Generation `bin:"off=0x19, siz=0x8"` + Generation btrfsprim.Generation `bin:"off=0x19, siz=0x8"` binstruct.End `bin:"off=0x21"` } @@ -277,15 +278,15 @@ func (node *Node) marshalInternalTo(bodyBuf []byte) error { // Node: "leaf" //////////////////////////////////////////////////////////////////////////////////// type Item struct { - Key Key + Key btrfsprim.Key BodySize uint32 // [ignored-when-writing] Body btrfsitem.Item } type ItemHeader struct { - Key Key `bin:"off=0x0, siz=0x11"` - DataOffset uint32 `bin:"off=0x11, siz=0x4"` // [ignored-when-writing] relative to the end of the header (0x65) - DataSize uint32 `bin:"off=0x15, siz=0x4"` // [ignored-when-writing] + Key btrfsprim.Key `bin:"off=0x0, siz=0x11"` + DataOffset uint32 `bin:"off=0x11, siz=0x4"` // [ignored-when-writing] relative to the end of the header (0x65) + DataSize uint32 `bin:"off=0x15, siz=0x4"` // [ignored-when-writing] binstruct.End `bin:"off=0x19"` } @@ -384,8 +385,8 @@ type NodeExpectations struct { LAddr containers.Optional[btrfsvol.LogicalAddr] // Things knowable from the parent. Level containers.Optional[uint8] - MaxGeneration containers.Optional[Generation] - Owner []ObjID + MaxGeneration containers.Optional[btrfsprim.Generation] + Owner []btrfsprim.ObjID } func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp NodeExpectations) (*diskio.Ref[Addr, Node], error) { diff --git a/lib/btrfs/types_node_test.go b/lib/btrfs/btrfstree/types_node_test.go index 2748c38..040b90c 100644 --- a/lib/btrfs/types_node_test.go +++ b/lib/btrfs/btrfstree/types_node_test.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package btrfs_test +package btrfstree_test import ( "testing" @@ -10,14 +10,14 @@ import ( "github.com/stretchr/testify/require" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree" ) func FuzzRoundTripNode(f *testing.F) { f.Fuzz(func(t *testing.T, inDat []byte) { t.Logf("dat=(%d)%q", len(inDat), inDat) - node := btrfs.Node{ + node := btrfstree.Node{ ChecksumType: btrfssum.TYPE_CRC32, } n, err := binstruct.Unmarshal(inDat, &node) diff --git a/lib/btrfs/types_superblock.go b/lib/btrfs/btrfstree/types_superblock.go index 68c5d56..9258f9a 100644 --- a/lib/btrfs/types_superblock.go +++ b/lib/btrfs/btrfstree/types_superblock.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: GPL-2.0-or-later -package btrfs +package btrfstree import ( "fmt" @@ -10,6 +10,7 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" @@ -17,21 +18,21 @@ import ( type Superblock struct { Checksum btrfssum.CSum `bin:"off=0x0, siz=0x20"` // Checksum of everything past this field (from 0x20 to 0x1000) - FSUUID UUID `bin:"off=0x20, siz=0x10"` // FS UUID + FSUUID btrfsprim.UUID `bin:"off=0x20, siz=0x10"` // FS UUID Self btrfsvol.PhysicalAddr `bin:"off=0x30, siz=0x8"` // physical address of this block (different for mirrors) Flags uint64 `bin:"off=0x38, siz=0x8"` // flags Magic [8]byte `bin:"off=0x40, siz=0x8"` // magic ('_BHRfS_M') - Generation Generation `bin:"off=0x48, siz=0x8"` + Generation btrfsprim.Generation `bin:"off=0x48, siz=0x8"` RootTree btrfsvol.LogicalAddr `bin:"off=0x50, siz=0x8"` // logical address of the root tree root ChunkTree btrfsvol.LogicalAddr `bin:"off=0x58, siz=0x8"` // logical address of the chunk tree root LogTree btrfsvol.LogicalAddr `bin:"off=0x60, siz=0x8"` // logical address of the log tree root - LogRootTransID uint64 `bin:"off=0x68, siz=0x8"` // log_root_transid - TotalBytes uint64 `bin:"off=0x70, siz=0x8"` // total_bytes - BytesUsed uint64 `bin:"off=0x78, siz=0x8"` // bytes_used - RootDirObjectID ObjID `bin:"off=0x80, siz=0x8"` // root_dir_objectid (usually 6) - NumDevices uint64 `bin:"off=0x88, siz=0x8"` // num_devices + LogRootTransID uint64 `bin:"off=0x68, siz=0x8"` // log_root_transid + TotalBytes uint64 `bin:"off=0x70, siz=0x8"` // total_bytes + BytesUsed uint64 `bin:"off=0x78, siz=0x8"` // bytes_used + RootDirObjectID btrfsprim.ObjID `bin:"off=0x80, siz=0x8"` // root_dir_objectid (usually 6) + NumDevices uint64 `bin:"off=0x88, siz=0x8"` // num_devices SectorSize uint32 `bin:"off=0x90, siz=0x4"` NodeSize uint32 `bin:"off=0x94, siz=0x4"` @@ -39,30 +40,30 @@ type Superblock struct { StripeSize uint32 `bin:"off=0x9c, siz=0x4"` SysChunkArraySize uint32 `bin:"off=0xa0, siz=0x4"` - ChunkRootGeneration Generation `bin:"off=0xa4, siz=0x8"` - CompatFlags uint64 `bin:"off=0xac, siz=0x8"` // compat_flags - CompatROFlags uint64 `bin:"off=0xb4, siz=0x8"` // compat_ro_flags - only implementations that support the flags can write to the filesystem - IncompatFlags IncompatFlags `bin:"off=0xbc, siz=0x8"` // incompat_flags - only implementations that support the flags can use the filesystem - ChecksumType btrfssum.CSumType `bin:"off=0xc4, siz=0x2"` + ChunkRootGeneration btrfsprim.Generation `bin:"off=0xa4, siz=0x8"` + CompatFlags uint64 `bin:"off=0xac, siz=0x8"` // compat_flags + CompatROFlags uint64 `bin:"off=0xb4, siz=0x8"` // compat_ro_flags - only implementations that support the flags can write to the filesystem + IncompatFlags IncompatFlags `bin:"off=0xbc, siz=0x8"` // incompat_flags - only implementations that support the flags can use the filesystem + ChecksumType btrfssum.CSumType `bin:"off=0xc4, siz=0x2"` RootLevel uint8 `bin:"off=0xc6, siz=0x1"` // root_level ChunkLevel uint8 `bin:"off=0xc7, siz=0x1"` // chunk_root_level LogLevel uint8 `bin:"off=0xc8, siz=0x1"` // log_root_level - DevItem btrfsitem.Dev `bin:"off=0xc9, siz=0x62"` // DEV_ITEM data for this device - Label [0x100]byte `bin:"off=0x12b, siz=0x100"` // label (may not contain '/' or '\\') - CacheGeneration Generation `bin:"off=0x22b, siz=0x8"` - UUIDTreeGeneration Generation `bin:"off=0x233, siz=0x8"` + DevItem btrfsitem.Dev `bin:"off=0xc9, siz=0x62"` // DEV_ITEM data for this device + Label [0x100]byte `bin:"off=0x12b, siz=0x100"` // label (may not contain '/' or '\\') + CacheGeneration btrfsprim.Generation `bin:"off=0x22b, siz=0x8"` + UUIDTreeGeneration btrfsprim.Generation `bin:"off=0x233, siz=0x8"` // FeatureIncompatMetadataUUID - MetadataUUID UUID `bin:"off=0x23b, siz=0x10"` + MetadataUUID btrfsprim.UUID `bin:"off=0x23b, siz=0x10"` // FeatureIncompatExtentTreeV2 NumGlobalRoots uint64 `bin:"off=0x24b, siz=0x8"` // FeatureIncompatExtentTreeV2 BlockGroupRoot btrfsvol.LogicalAddr `bin:"off=0x253, siz=0x8"` - BlockGroupRootGeneration Generation `bin:"off=0x25b, siz=0x8"` + BlockGroupRootGeneration btrfsprim.Generation `bin:"off=0x25b, siz=0x8"` BlockGroupRootLevel uint8 `bin:"off=0x263, siz=0x1"` Reserved [199]byte `bin:"off=0x264, siz=0xc7"` // future expansion @@ -106,7 +107,7 @@ func (a Superblock) Equal(b Superblock) bool { return reflect.DeepEqual(a, b) } -func (sb Superblock) EffectiveMetadataUUID() UUID { +func (sb Superblock) EffectiveMetadataUUID() btrfsprim.UUID { if !sb.IncompatFlags.Has(FeatureIncompatMetadataUUID) { return sb.FSUUID } @@ -114,7 +115,7 @@ func (sb Superblock) EffectiveMetadataUUID() UUID { } type SysChunk struct { - Key Key + Key btrfsprim.Key Chunk btrfsitem.Chunk } @@ -160,23 +161,23 @@ func (sb Superblock) ParseSysChunkArray() ([]SysChunk, error) { } type RootBackup struct { - TreeRoot ObjID `bin:"off=0x0, siz=0x8"` - TreeRootGen Generation `bin:"off=0x8, siz=0x8"` + TreeRoot btrfsprim.ObjID `bin:"off=0x0, siz=0x8"` + TreeRootGen btrfsprim.Generation `bin:"off=0x8, siz=0x8"` - ChunkRoot ObjID `bin:"off=0x10, siz=0x8"` - ChunkRootGen Generation `bin:"off=0x18, siz=0x8"` + ChunkRoot btrfsprim.ObjID `bin:"off=0x10, siz=0x8"` + ChunkRootGen btrfsprim.Generation `bin:"off=0x18, siz=0x8"` - ExtentRoot ObjID `bin:"off=0x20, siz=0x8"` - ExtentRootGen Generation `bin:"off=0x28, siz=0x8"` + ExtentRoot btrfsprim.ObjID `bin:"off=0x20, siz=0x8"` + ExtentRootGen btrfsprim.Generation `bin:"off=0x28, siz=0x8"` - FSRoot ObjID `bin:"off=0x30, siz=0x8"` - FSRootGen Generation `bin:"off=0x38, siz=0x8"` + FSRoot btrfsprim.ObjID `bin:"off=0x30, siz=0x8"` + FSRootGen btrfsprim.Generation `bin:"off=0x38, siz=0x8"` - DevRoot ObjID `bin:"off=0x40, siz=0x8"` - DevRootGen Generation `bin:"off=0x48, siz=0x8"` + DevRoot btrfsprim.ObjID `bin:"off=0x40, siz=0x8"` + DevRootGen btrfsprim.Generation `bin:"off=0x48, siz=0x8"` - ChecksumRoot ObjID `bin:"off=0x50, siz=0x8"` - ChecksumRootGen Generation `bin:"off=0x58, siz=0x8"` + ChecksumRoot btrfsprim.ObjID `bin:"off=0x50, siz=0x8"` + ChecksumRootGen btrfsprim.Generation `bin:"off=0x58, siz=0x8"` TotalBytes uint64 `bin:"off=0x60, siz=0x8"` BytesUsed uint64 `bin:"off=0x68, siz=0x8"` diff --git a/lib/btrfs/io1_pv.go b/lib/btrfs/io1_pv.go index df31671..0e7cd9c 100644 --- a/lib/btrfs/io1_pv.go +++ b/lib/btrfs/io1_pv.go @@ -8,6 +8,7 @@ import ( "fmt" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" "git.lukeshu.com/btrfs-progs-ng/lib/diskio" ) @@ -15,8 +16,8 @@ import ( type Device struct { diskio.File[btrfsvol.PhysicalAddr] - cacheSuperblocks []*diskio.Ref[btrfsvol.PhysicalAddr, Superblock] - cacheSuperblock *Superblock + cacheSuperblocks []*diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock] + cacheSuperblock *btrfstree.Superblock } var _ diskio.File[btrfsvol.PhysicalAddr] = (*Device)(nil) @@ -27,18 +28,18 @@ var SuperblockAddrs = []btrfsvol.PhysicalAddr{ 0x40_0000_0000, // 256GiB } -func (dev *Device) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, Superblock], error) { +func (dev *Device) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock], error) { if dev.cacheSuperblocks != nil { return dev.cacheSuperblocks, nil } - superblockSize := btrfsvol.PhysicalAddr(binstruct.StaticSize(Superblock{})) + superblockSize := btrfsvol.PhysicalAddr(binstruct.StaticSize(btrfstree.Superblock{})) sz := dev.Size() - var ret []*diskio.Ref[btrfsvol.PhysicalAddr, Superblock] + var ret []*diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock] for i, addr := range SuperblockAddrs { if addr+superblockSize <= sz { - superblock := &diskio.Ref[btrfsvol.PhysicalAddr, Superblock]{ + superblock := &diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock]{ File: dev, Addr: addr, } @@ -55,7 +56,7 @@ func (dev *Device) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, Superbloc return ret, nil } -func (dev *Device) Superblock() (*Superblock, error) { +func (dev *Device) Superblock() (*btrfstree.Superblock, error) { if dev.cacheSuperblock != nil { return dev.cacheSuperblock, nil } diff --git a/lib/btrfs/io2_lv.go b/lib/btrfs/io2_lv.go index 7fa003e..5580285 100644 --- a/lib/btrfs/io2_lv.go +++ b/lib/btrfs/io2_lv.go @@ -13,6 +13,8 @@ import ( "github.com/datawire/dlib/dlog" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" "git.lukeshu.com/btrfs-progs-ng/lib/diskio" ) @@ -22,12 +24,12 @@ type FS struct { // implementing special things like fsck. LV btrfsvol.LogicalVolume[*Device] - cacheSuperblocks []*diskio.Ref[btrfsvol.PhysicalAddr, Superblock] - cacheSuperblock *Superblock + cacheSuperblocks []*diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock] + cacheSuperblock *btrfstree.Superblock - cacheObjID2UUID map[ObjID]UUID - cacheUUID2ObjID map[UUID]ObjID - cacheTreeParent map[ObjID]UUID + cacheObjID2UUID map[btrfsprim.ObjID]btrfsprim.UUID + cacheUUID2ObjID map[btrfsprim.UUID]btrfsprim.ObjID + cacheTreeParent map[btrfsprim.ObjID]btrfsprim.UUID } var _ diskio.File[btrfsvol.LogicalAddr] = (*FS)(nil) @@ -72,11 +74,11 @@ func (fs *FS) WriteAt(p []byte, off btrfsvol.LogicalAddr) (int, error) { return fs.LV.WriteAt(p, off) } -func (fs *FS) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, Superblock], error) { +func (fs *FS) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock], error) { if fs.cacheSuperblocks != nil { return fs.cacheSuperblocks, nil } - var ret []*diskio.Ref[btrfsvol.PhysicalAddr, Superblock] + var ret []*diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock] devs := fs.LV.PhysicalVolumes() if len(devs) == 0 { return nil, fmt.Errorf("no devices") @@ -92,7 +94,7 @@ func (fs *FS) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, Superblock], e return ret, nil } -func (fs *FS) Superblock() (*Superblock, error) { +func (fs *FS) Superblock() (*btrfstree.Superblock, error) { if fs.cacheSuperblock != nil { return fs.cacheSuperblock, nil } @@ -147,7 +149,7 @@ func (fs *FS) ReInit(ctx context.Context) error { return nil } -func (fs *FS) initDev(ctx context.Context, sb Superblock) error { +func (fs *FS) initDev(ctx context.Context, sb btrfstree.Superblock) error { syschunks, err := sb.ParseSysChunkArray() if err != nil { return err @@ -160,12 +162,12 @@ func (fs *FS) initDev(ctx context.Context, sb Superblock) error { } } var errs derror.MultiError - fs.TreeWalk(ctx, CHUNK_TREE_OBJECTID, - func(err *TreeError) { + fs.TreeWalk(ctx, btrfsprim.CHUNK_TREE_OBJECTID, + func(err *btrfstree.TreeError) { errs = append(errs, err) }, - TreeWalkHandler{ - Item: func(_ TreePath, item Item) error { + btrfstree.TreeWalkHandler{ + Item: func(_ btrfstree.TreePath, item btrfstree.Item) error { if item.Key.ItemType != btrfsitem.CHUNK_ITEM_KEY { return nil } diff --git a/lib/btrfs/io3_btree.go b/lib/btrfs/io3_btree.go index 1851508..9c4dd67 100644 --- a/lib/btrfs/io3_btree.go +++ b/lib/btrfs/io3_btree.go @@ -9,24 +9,39 @@ import ( "fmt" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" "git.lukeshu.com/btrfs-progs-ng/lib/containers" "git.lukeshu.com/btrfs-progs-ng/lib/diskio" ) -var _ Trees = (*FS)(nil) +func (fs *FS) TreeWalk(ctx context.Context, treeID btrfsprim.ObjID, errHandle func(*btrfstree.TreeError), cbs btrfstree.TreeWalkHandler) { + btrfstree.TreesImpl{NodeSource: fs}.TreeWalk(ctx, treeID, errHandle, cbs) +} +func (fs *FS) TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (btrfstree.Item, error) { + return btrfstree.TreesImpl{NodeSource: fs}.TreeLookup(treeID, key) +} +func (fs *FS) TreeSearch(treeID btrfsprim.ObjID, fn func(key btrfsprim.Key, size uint32) int) (btrfstree.Item, error) { + return btrfstree.TreesImpl{NodeSource: fs}.TreeSearch(treeID, fn) +} +func (fs *FS) TreeSearchAll(treeID btrfsprim.ObjID, fn func(key btrfsprim.Key, size uint32) int) ([]btrfstree.Item, error) { + return btrfstree.TreesImpl{NodeSource: fs}.TreeSearchAll(treeID, fn) +} + +var _ btrfstree.Trees = (*FS)(nil) func (fs *FS) populateTreeUUIDs(ctx context.Context) { if fs.cacheObjID2UUID == nil || fs.cacheUUID2ObjID == nil || fs.cacheTreeParent == nil { - fs.cacheObjID2UUID = make(map[ObjID]UUID) - fs.cacheUUID2ObjID = make(map[UUID]ObjID) - fs.cacheTreeParent = make(map[ObjID]UUID) - fs.TreeWalk(ctx, ROOT_TREE_OBJECTID, - func(err *TreeError) { + fs.cacheObjID2UUID = make(map[btrfsprim.ObjID]btrfsprim.UUID) + fs.cacheUUID2ObjID = make(map[btrfsprim.UUID]btrfsprim.ObjID) + fs.cacheTreeParent = make(map[btrfsprim.ObjID]btrfsprim.UUID) + fs.TreeWalk(ctx, btrfsprim.ROOT_TREE_OBJECTID, + func(err *btrfstree.TreeError) { // do nothing }, - TreeWalkHandler{ - Item: func(_ TreePath, item Item) error { + btrfstree.TreeWalkHandler{ + Item: func(_ btrfstree.TreePath, item btrfstree.Item) error { itemBody, ok := item.Body.(btrfsitem.Root) if !ok { return nil @@ -41,22 +56,22 @@ func (fs *FS) populateTreeUUIDs(ctx context.Context) { } } -func (fs *FS) ReadNode(path TreePath) (*diskio.Ref[btrfsvol.LogicalAddr, Node], error) { +func (fs *FS) ReadNode(path btrfstree.TreePath) (*diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node], error) { sb, err := fs.Superblock() if err != nil { return nil, fmt.Errorf("btrfs.FS.ReadNode: %w", err) } - potentialOwners := []ObjID{ + potentialOwners := []btrfsprim.ObjID{ path.Node(-1).FromTree, } - if potentialOwners[0] >= FIRST_FREE_OBJECTID { + if potentialOwners[0] >= btrfsprim.FIRST_FREE_OBJECTID { ctx := context.TODO() fs.populateTreeUUIDs(ctx) - for potentialOwners[len(potentialOwners)-1] >= FIRST_FREE_OBJECTID { + for potentialOwners[len(potentialOwners)-1] >= btrfsprim.FIRST_FREE_OBJECTID { objID := potentialOwners[len(potentialOwners)-1] parentUUID := fs.cacheTreeParent[objID] - if parentUUID == (UUID{}) { + if parentUUID == (btrfsprim.UUID{}) { break } parentObjID, ok := fs.cacheUUID2ObjID[parentUUID] @@ -67,10 +82,10 @@ func (fs *FS) ReadNode(path TreePath) (*diskio.Ref[btrfsvol.LogicalAddr, Node], } } - return ReadNode[btrfsvol.LogicalAddr](fs, *sb, path.Node(-1).ToNodeAddr, NodeExpectations{ + return btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, path.Node(-1).ToNodeAddr, btrfstree.NodeExpectations{ LAddr: containers.Optional[btrfsvol.LogicalAddr]{OK: true, Val: path.Node(-1).ToNodeAddr}, Level: containers.Optional[uint8]{OK: true, Val: path.Node(-1).ToNodeLevel}, - MaxGeneration: containers.Optional[Generation]{OK: true, Val: path.Node(-1).FromGeneration}, + MaxGeneration: containers.Optional[btrfsprim.Generation]{OK: true, Val: path.Node(-1).FromGeneration}, Owner: potentialOwners, }) } diff --git a/lib/btrfs/io4_fs.go b/lib/btrfs/io4_fs.go index 65a7562..7bfcc00 100644 --- a/lib/btrfs/io4_fs.go +++ b/lib/btrfs/io4_fs.go @@ -15,6 +15,8 @@ import ( "github.com/datawire/dlib/derror" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" "git.lukeshu.com/btrfs-progs-ng/lib/containers" "git.lukeshu.com/btrfs-progs-ng/lib/maps" @@ -22,7 +24,7 @@ import ( ) type BareInode struct { - Inode ObjID + Inode btrfsprim.ObjID InodeItem *btrfsitem.Inode Errs derror.MultiError } @@ -30,11 +32,11 @@ type BareInode struct { type FullInode struct { BareInode XAttrs map[string]string - OtherItems []Item + OtherItems []btrfstree.Item } type InodeRef struct { - Inode ObjID + Inode btrfsprim.ObjID btrfsitem.InodeRef } @@ -58,22 +60,26 @@ type File struct { } type Subvolume struct { - FS Trees - TreeID ObjID + FS interface { + btrfstree.Trees + Superblock() (*btrfstree.Superblock, error) + ReadAt(p []byte, off btrfsvol.LogicalAddr) (int, error) + } + TreeID btrfsprim.ObjID rootOnce sync.Once rootVal btrfsitem.Root rootErr error - bareInodeCache containers.LRUCache[ObjID, *BareInode] - fullInodeCache containers.LRUCache[ObjID, *FullInode] - dirCache containers.LRUCache[ObjID, *Dir] - fileCache containers.LRUCache[ObjID, *File] + bareInodeCache containers.LRUCache[btrfsprim.ObjID, *BareInode] + fullInodeCache containers.LRUCache[btrfsprim.ObjID, *FullInode] + dirCache containers.LRUCache[btrfsprim.ObjID, *Dir] + fileCache containers.LRUCache[btrfsprim.ObjID, *File] } func (sv *Subvolume) init() { sv.rootOnce.Do(func() { - root, err := sv.FS.TreeLookup(ROOT_TREE_OBJECTID, Key{ + root, err := sv.FS.TreeLookup(btrfsprim.ROOT_TREE_OBJECTID, btrfsprim.Key{ ObjectID: sv.TreeID, ItemType: btrfsitem.ROOT_ITEM_KEY, Offset: 0, @@ -93,17 +99,17 @@ func (sv *Subvolume) init() { }) } -func (sv *Subvolume) GetRootInode() (ObjID, error) { +func (sv *Subvolume) GetRootInode() (btrfsprim.ObjID, error) { sv.init() return sv.rootVal.RootDirID, sv.rootErr } -func (sv *Subvolume) LoadBareInode(inode ObjID) (*BareInode, error) { +func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) { val := sv.bareInodeCache.GetOrElse(inode, func() (val *BareInode) { val = &BareInode{ Inode: inode, } - item, err := sv.FS.TreeLookup(sv.TreeID, Key{ + item, err := sv.FS.TreeLookup(sv.TreeID, btrfsprim.Key{ ObjectID: inode, ItemType: btrfsitem.INODE_ITEM_KEY, Offset: 0, @@ -128,7 +134,7 @@ func (sv *Subvolume) LoadBareInode(inode ObjID) (*BareInode, error) { return val, nil } -func (sv *Subvolume) LoadFullInode(inode ObjID) (*FullInode, error) { +func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) { val := sv.fullInodeCache.GetOrElse(inode, func() (val *FullInode) { val = &FullInode{ BareInode: BareInode{ @@ -136,7 +142,7 @@ func (sv *Subvolume) LoadFullInode(inode ObjID) (*FullInode, error) { }, XAttrs: make(map[string]string), } - items, err := sv.FS.TreeSearchAll(sv.TreeID, func(key Key, _ uint32) int { + items, err := sv.FS.TreeSearchAll(sv.TreeID, func(key btrfsprim.Key, _ uint32) int { return containers.NativeCmp(inode, key.ObjectID) }) if err != nil { @@ -171,7 +177,7 @@ func (sv *Subvolume) LoadFullInode(inode ObjID) (*FullInode, error) { return val, nil } -func (sv *Subvolume) LoadDir(inode ObjID) (*Dir, error) { +func (sv *Subvolume) LoadDir(inode btrfsprim.ObjID) (*Dir, error) { val := sv.dirCache.GetOrElse(inode, func() (val *Dir) { val = new(Dir) fullInode, err := sv.LoadFullInode(inode) @@ -203,7 +209,7 @@ func (ret *Dir) populate() { continue } ref := InodeRef{ - Inode: ObjID(item.Key.Offset), + Inode: btrfsprim.ObjID(item.Key.Offset), InodeRef: body[0], } if ret.DotDot != nil { @@ -288,7 +294,7 @@ func (dir *Dir) AbsPath() (string, error) { return filepath.Join(parentName, string(dir.DotDot.Name)), nil } -func (sv *Subvolume) LoadFile(inode ObjID) (*File, error) { +func (sv *Subvolume) LoadFile(inode btrfsprim.ObjID) (*File, error) { val := sv.fileCache.GetOrElse(inode, func() (val *File) { val = new(File) fullInode, err := sv.LoadFullInode(inode) |