From 27401b6ea459921a6152ab1744da1618358465f4 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 10 Jul 2022 13:18:30 -0600 Subject: Rename the module, mv pkg lib --- lib/btrfs/btrfsitem/item_blockgroup.go | 16 +++ lib/btrfs/btrfsitem/item_chunk.go | 90 +++++++++++++++ lib/btrfs/btrfsitem/item_dev.go | 33 ++++++ lib/btrfs/btrfsitem/item_devextent.go | 32 ++++++ lib/btrfs/btrfsitem/item_dir.go | 115 +++++++++++++++++++ lib/btrfs/btrfsitem/item_empty.go | 9 ++ lib/btrfs/btrfsitem/item_extent.go | 165 ++++++++++++++++++++++++++++ lib/btrfs/btrfsitem/item_extentcsum.go | 39 +++++++ lib/btrfs/btrfsitem/item_extentdataref.go | 14 +++ lib/btrfs/btrfsitem/item_fileextent.go | 137 +++++++++++++++++++++++ lib/btrfs/btrfsitem/item_freespacebitmap.go | 12 ++ lib/btrfs/btrfsitem/item_freespaceinfo.go | 11 ++ lib/btrfs/btrfsitem/item_inode.go | 64 +++++++++++ lib/btrfs/btrfsitem/item_inoderef.go | 35 ++++++ lib/btrfs/btrfsitem/item_metadata.go | 44 ++++++++ lib/btrfs/btrfsitem/item_persistent.go | 19 ++++ lib/btrfs/btrfsitem/item_root.go | 51 +++++++++ lib/btrfs/btrfsitem/item_rootref.go | 34 ++++++ lib/btrfs/btrfsitem/item_shareddataref.go | 10 ++ lib/btrfs/btrfsitem/item_untyped.go | 14 +++ lib/btrfs/btrfsitem/item_uuid.go | 16 +++ lib/btrfs/btrfsitem/items.go | 77 +++++++++++++ lib/btrfs/btrfsitem/items.txt | 29 +++++ lib/btrfs/btrfsitem/items_gen.go | 97 ++++++++++++++++ 24 files changed, 1163 insertions(+) create mode 100644 lib/btrfs/btrfsitem/item_blockgroup.go create mode 100644 lib/btrfs/btrfsitem/item_chunk.go create mode 100644 lib/btrfs/btrfsitem/item_dev.go create mode 100644 lib/btrfs/btrfsitem/item_devextent.go create mode 100644 lib/btrfs/btrfsitem/item_dir.go create mode 100644 lib/btrfs/btrfsitem/item_empty.go create mode 100644 lib/btrfs/btrfsitem/item_extent.go create mode 100644 lib/btrfs/btrfsitem/item_extentcsum.go create mode 100644 lib/btrfs/btrfsitem/item_extentdataref.go create mode 100644 lib/btrfs/btrfsitem/item_fileextent.go create mode 100644 lib/btrfs/btrfsitem/item_freespacebitmap.go create mode 100644 lib/btrfs/btrfsitem/item_freespaceinfo.go create mode 100644 lib/btrfs/btrfsitem/item_inode.go create mode 100644 lib/btrfs/btrfsitem/item_inoderef.go create mode 100644 lib/btrfs/btrfsitem/item_metadata.go create mode 100644 lib/btrfs/btrfsitem/item_persistent.go create mode 100644 lib/btrfs/btrfsitem/item_root.go create mode 100644 lib/btrfs/btrfsitem/item_rootref.go create mode 100644 lib/btrfs/btrfsitem/item_shareddataref.go create mode 100644 lib/btrfs/btrfsitem/item_untyped.go create mode 100644 lib/btrfs/btrfsitem/item_uuid.go create mode 100644 lib/btrfs/btrfsitem/items.go create mode 100644 lib/btrfs/btrfsitem/items.txt create mode 100644 lib/btrfs/btrfsitem/items_gen.go (limited to 'lib/btrfs/btrfsitem') diff --git a/lib/btrfs/btrfsitem/item_blockgroup.go b/lib/btrfs/btrfsitem/item_blockgroup.go new file mode 100644 index 0000000..71d960d --- /dev/null +++ b/lib/btrfs/btrfsitem/item_blockgroup.go @@ -0,0 +1,16 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "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 + 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 new file mode 100644 index 0000000..9256651 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_chunk.go @@ -0,0 +1,90 @@ +package btrfsitem + +import ( + "fmt" + + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "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/util" +) + +// Maps logical address to physical. +// +// key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID +// key.offset = logical_addr +type Chunk struct { // CHUNK_ITEM=228 + Head ChunkHeader + Stripes []ChunkStripe +} + +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) + StripeLen uint64 `bin:"off=0x10, siz=0x8"` // ??? + Type btrfsvol.BlockGroupFlags `bin:"off=0x18, siz=0x8"` + IOOptimalAlign uint32 `bin:"off=0x20, siz=0x4"` + IOOptimalWidth uint32 `bin:"off=0x24, siz=0x4"` + IOMinSize uint32 `bin:"off=0x28, siz=0x4"` // sector size + NumStripes uint16 `bin:"off=0x2c, siz=0x2"` // [ignored-when-writing] + SubStripes uint16 `bin:"off=0x2e, siz=0x2"` // ??? + binstruct.End `bin:"off=0x30"` +} + +type ChunkStripe struct { + 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, + SizeLocked: true, + Flags: &chunk.Head.Type, + }) + } + return ret +} + +func (chunk *Chunk) UnmarshalBinary(dat []byte) (int, error) { + n, err := binstruct.Unmarshal(dat, &chunk.Head) + if err != nil { + return n, err + } + chunk.Stripes = nil + for i := 0; i < int(chunk.Head.NumStripes); i++ { + var stripe ChunkStripe + _n, err := binstruct.Unmarshal(dat[n:], &stripe) + n += _n + if err != nil { + return n, fmt.Errorf("%T.UnmarshalBinary: %w", *chunk, err) + } + chunk.Stripes = append(chunk.Stripes, stripe) + } + return n, nil +} + +func (chunk Chunk) MarshalBinary() ([]byte, error) { + chunk.Head.NumStripes = uint16(len(chunk.Stripes)) + ret, err := binstruct.Marshal(chunk.Head) + if err != nil { + return ret, err + } + for _, stripe := range chunk.Stripes { + _ret, err := binstruct.Marshal(stripe) + ret = append(ret, _ret...) + if err != nil { + return ret, fmt.Errorf("%T.MarshalBinary: %w", chunk, err) + } + } + return ret, nil +} diff --git a/lib/btrfs/btrfsitem/item_dev.go b/lib/btrfs/btrfsitem/item_dev.go new file mode 100644 index 0000000..d3fe582 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_dev.go @@ -0,0 +1,33 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "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/util" +) + +// key.objectid = BTRFS_DEV_ITEMS_OBJECTID +// key.offset = device_id (starting at 1) +type Dev struct { // DEV_ITEM=216 + DevID btrfsvol.DeviceID `bin:"off=0x0, siz=0x8"` + + NumBytes uint64 `bin:"off=0x8, siz=0x8"` + NumBytesUsed uint64 `bin:"off=0x10, siz=0x8"` + + IOOptimalAlign uint32 `bin:"off=0x18, siz=0x4"` + 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"` + + DevUUID util.UUID `bin:"off=0x42, siz=0x10"` + FSUUID util.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 new file mode 100644 index 0000000..c346d85 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_devextent.go @@ -0,0 +1,32 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "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/util" +) + +// 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"` + ChunkOffset btrfsvol.LogicalAddr `bin:"off=16, siz=8"` + Length btrfsvol.AddrDelta `bin:"off=24, siz=8"` + 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, + SizeLocked: true, + Flags: nil, + } +} diff --git a/lib/btrfs/btrfsitem/item_dir.go b/lib/btrfs/btrfsitem/item_dir.go new file mode 100644 index 0000000..57f6d6d --- /dev/null +++ b/lib/btrfs/btrfsitem/item_dir.go @@ -0,0 +1,115 @@ +package btrfsitem + +import ( + "fmt" + "hash/crc32" + + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" +) + +// key.objectid = inode of directory containing this entry +// key.offset = +// for DIR_ITEM and XATTR_ITEM = NameHash(name) +// for DIR_INDEX = index id in the directory (starting at 2, because "." and "..") +type DirEntries []DirEntry // DIR_ITEM=84 DIR_INDEX=96 XATTR_ITEM=24 + +func NameHash(dat []byte) uint64 { + return uint64(^crc32.Update(1, crc32.MakeTable(crc32.Castagnoli), dat)) +} + +func (o *DirEntries) UnmarshalBinary(dat []byte) (int, error) { + *o = nil + n := 0 + for n < len(dat) { + var ref DirEntry + _n, err := binstruct.Unmarshal(dat, &ref) + n += _n + if err != nil { + return n, err + } + *o = append(*o, ref) + } + return n, nil +} + +func (o DirEntries) MarshalBinary() ([]byte, error) { + var ret []byte + for _, ref := range o { + bs, err := binstruct.Marshal(ref) + ret = append(ret, bs...) + if err != nil { + return ret, err + } + } + return ret, nil +} + +type DirEntry struct { + 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"` + binstruct.End `bin:"off=0x1e"` + Data []byte `bin:"-"` + Name []byte `bin:"-"` +} + +func (o *DirEntry) UnmarshalBinary(dat []byte) (int, error) { + n, err := binstruct.UnmarshalWithoutInterface(dat, o) + if err != nil { + return n, err + } + o.Data = dat[n : n+int(o.DataLen)] + n += int(o.DataLen) + o.Name = dat[n : n+int(o.NameLen)] + n += int(o.NameLen) + return n, nil +} + +func (o DirEntry) MarshalBinary() ([]byte, error) { + o.DataLen = uint16(len(o.Data)) + o.NameLen = uint16(len(o.Name)) + dat, err := binstruct.MarshalWithoutInterface(o) + if err != nil { + return dat, err + } + dat = append(dat, o.Data...) + dat = append(dat, o.Name...) + return dat, nil +} + +type FileType uint8 + +const ( + FT_UNKNOWN = FileType(0) + FT_REG_FILE = FileType(1) + FT_DIR = FileType(2) + FT_CHRDEV = FileType(3) + FT_BLKDEV = FileType(4) + FT_FIFO = FileType(5) + FT_SOCK = FileType(6) + FT_SYMLINK = FileType(7) + FT_XATTR = FileType(8) + + FT_MAX = FileType(9) +) + +func (ft FileType) String() string { + names := map[FileType]string{ + FT_UNKNOWN: "UNKNOWN", + FT_REG_FILE: "FILE", // XXX + FT_DIR: "DIR", + FT_CHRDEV: "CHRDEV", + FT_BLKDEV: "BLKDEV", + FT_FIFO: "FIFO", + FT_SOCK: "SOCK", + FT_SYMLINK: "SYMLINK", + FT_XATTR: "XATTR", + } + if name, ok := names[ft]; ok { + return name + } + return fmt.Sprintf("DIR_ITEM.%d", uint8(ft)) +} diff --git a/lib/btrfs/btrfsitem/item_empty.go b/lib/btrfs/btrfsitem/item_empty.go new file mode 100644 index 0000000..209b2fc --- /dev/null +++ b/lib/btrfs/btrfsitem/item_empty.go @@ -0,0 +1,9 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" +) + +type Empty struct { // ORPHAN_ITEM=48 TREE_BLOCK_REF=176 SHARED_BLOCK_REF=182 FREE_SPACE_EXTENT=199 QGROUP_RELATION=246 + binstruct.End `bin:"off=0"` +} diff --git a/lib/btrfs/btrfsitem/item_extent.go b/lib/btrfs/btrfsitem/item_extent.go new file mode 100644 index 0000000..9a9ea55 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_extent.go @@ -0,0 +1,165 @@ +package btrfsitem + +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/util" +) + +type Extent struct { // EXTENT_ITEM=168 + Head ExtentHeader + Info TreeBlockInfo // only if .Head.Flags.Has(EXTENT_FLAG_TREE_BLOCK) + Refs []ExtentInlineRef +} + +func (o *Extent) UnmarshalBinary(dat []byte) (int, error) { + n, err := binstruct.Unmarshal(dat, &o.Head) + if err != nil { + return n, err + } + if o.Head.Flags.Has(EXTENT_FLAG_TREE_BLOCK) { + _n, err := binstruct.Unmarshal(dat[n:], &o.Info) + n += _n + if err != nil { + return n, err + } + } + o.Refs = nil + for n < len(dat) { + var ref ExtentInlineRef + _n, err := binstruct.Unmarshal(dat[n:], &ref) + n += _n + o.Refs = append(o.Refs, ref) + if err != nil { + return n, err + } + } + return n, nil +} + +func (o Extent) MarshalBinary() ([]byte, error) { + dat, err := binstruct.Marshal(o.Head) + if err != nil { + return dat, err + } + if o.Head.Flags.Has(EXTENT_FLAG_TREE_BLOCK) { + bs, err := binstruct.Marshal(o.Info) + dat = append(dat, bs...) + if err != nil { + return dat, err + } + } + for _, ref := range o.Refs { + bs, err := binstruct.Marshal(ref) + dat = append(dat, bs...) + if err != nil { + return dat, err + } + } + return dat, nil +} + +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"` + binstruct.End `bin:"off=24"` +} + +type TreeBlockInfo struct { + Key internal.Key `bin:"off=0, siz=0x11"` + Level uint8 `bin:"off=0x11, siz=0x8"` + binstruct.End `bin:"off=0x19"` +} + +type ExtentFlags uint64 + +const ( + EXTENT_FLAG_DATA = ExtentFlags(1 << iota) + EXTENT_FLAG_TREE_BLOCK +) + +var extentFlagNames = []string{ + "DATA", + "TREE_BLOCK", +} + +func (f ExtentFlags) Has(req ExtentFlags) bool { return f&req == req } +func (f ExtentFlags) String() string { return util.BitfieldString(f, extentFlagNames, util.HexNone) } + +type ExtentInlineRef struct { + Type Type // only 4 valid values: {TREE,SHARED}_BLOCK_REF_KEY, {EXTENT,SHARED}_DATA_REF_KEY + Offset uint64 // only when Type != EXTENT_DATA_REF_KEY + Body Item // only when Type == *_DATA_REF_KEY +} + +func (o *ExtentInlineRef) UnmarshalBinary(dat []byte) (int, error) { + o.Type = Type(dat[0]) + n := 1 + switch o.Type { + case TREE_BLOCK_REF_KEY, SHARED_BLOCK_REF_KEY: + _n, err := binstruct.Unmarshal(dat[n:], &o.Offset) + n += _n + if err != nil { + return n, err + } + case EXTENT_DATA_REF_KEY: + var dref ExtentDataRef + _n, err := binstruct.Unmarshal(dat[n:], &dref) + n += _n + o.Body = dref + if err != nil { + return n, err + } + case SHARED_DATA_REF_KEY: + _n, err := binstruct.Unmarshal(dat[n:], &o.Offset) + n += _n + if err != nil { + return n, err + } + var sref SharedDataRef + _n, err = binstruct.Unmarshal(dat[n:], &sref) + n += _n + o.Body = sref + if err != nil { + return n, err + } + default: + return n, fmt.Errorf("btrfsitem.ExtentInlineRef.UnmarshalBinary: unexpected item type %v", o.Type) + } + return n, nil +} + +func (o ExtentInlineRef) MarshalBinary() ([]byte, error) { + dat := []byte{byte(o.Type)} + switch o.Type { + case TREE_BLOCK_REF_KEY, SHARED_BLOCK_REF_KEY: + _dat, err := binstruct.Marshal(o.Offset) + dat = append(dat, _dat...) + if err != nil { + return dat, err + } + case EXTENT_DATA_REF_KEY: + _dat, err := binstruct.Marshal(o.Body) + dat = append(dat, _dat...) + if err != nil { + return dat, err + } + case SHARED_DATA_REF_KEY: + _dat, err := binstruct.Marshal(o.Offset) + dat = append(dat, _dat...) + if err != nil { + return dat, err + } + _dat, err = binstruct.Marshal(o.Body) + dat = append(dat, _dat...) + if err != nil { + return dat, err + } + default: + return dat, fmt.Errorf("btrfsitem.ExtentInlineRef.MarshalBinary: unexpected item type %v", o.Type) + } + return dat, nil +} diff --git a/lib/btrfs/btrfsitem/item_extentcsum.go b/lib/btrfs/btrfsitem/item_extentcsum.go new file mode 100644 index 0000000..b27dbde --- /dev/null +++ b/lib/btrfs/btrfsitem/item_extentcsum.go @@ -0,0 +1,39 @@ +package btrfsitem + +import ( + "fmt" + + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" +) + +// key.objectid = BTRFS_EXTENT_CSUM_OBJECTID +// key.offset = laddr of checksummed region +type ExtentCSum struct { // EXTENT_CSUM=128 + ChecksumSize int + // Checksum of each sector starting at key.offset + Sums []btrfssum.CSum +} + +func (o *ExtentCSum) UnmarshalBinary(dat []byte) (int, error) { + if o.ChecksumSize == 0 { + return 0, fmt.Errorf("btrfs.ExtentCSum.UnmarshalBinary: .ChecksumSize must be set") + } + for len(dat) >= o.ChecksumSize { + var csum btrfssum.CSum + copy(csum[:], dat[:o.ChecksumSize]) + dat = dat[o.ChecksumSize:] + o.Sums = append(o.Sums, csum) + } + return len(o.Sums) * o.ChecksumSize, nil +} + +func (o ExtentCSum) MarshalBinary() ([]byte, error) { + if o.ChecksumSize == 0 { + return nil, fmt.Errorf("btrfs.ExtentCSum.MarshalBinary: .ChecksumSize must be set") + } + var dat []byte + for _, csum := range o.Sums { + dat = append(dat, csum[:o.ChecksumSize]...) + } + return dat, nil +} diff --git a/lib/btrfs/btrfsitem/item_extentdataref.go b/lib/btrfs/btrfsitem/item_extentdataref.go new file mode 100644 index 0000000..aab5426 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_extentdataref.go @@ -0,0 +1,14 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" +) + +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"` + binstruct.End `bin:"off=28"` +} diff --git a/lib/btrfs/btrfsitem/item_fileextent.go b/lib/btrfs/btrfsitem/item_fileextent.go new file mode 100644 index 0000000..2f3ac2b --- /dev/null +++ b/lib/btrfs/btrfsitem/item_fileextent.go @@ -0,0 +1,137 @@ +package btrfsitem + +import ( + "fmt" + + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "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 + + // 32 bits describing the data encoding + Compression CompressionType `bin:"off=0x10, siz=0x1"` + Encryption uint8 `bin:"off=0x11, siz=0x1"` + OtherEncoding uint16 `bin:"off=0x12, siz=0x2"` // reserved for later use + + Type FileExtentType `bin:"off=0x14, siz=0x1"` // inline data or real extent + + binstruct.End `bin:"off=0x15"` + + // only one of these, depending on .Type + BodyInline []byte `bin:"-"` // .Type == FILE_EXTENT_INLINE + BodyExtent struct { // .Type == FILE_EXTENT_REG or FILE_EXTENT_PREALLOC + // Position and size of extent within the device + DiskByteNr btrfsvol.LogicalAddr `bin:"off=0x0, siz=0x8"` + DiskNumBytes btrfsvol.AddrDelta `bin:"off=0x8, siz=0x8"` + + // Position of data within the extent + Offset btrfsvol.AddrDelta `bin:"off=0x10, siz=0x8"` + + // Decompressed/unencrypted size + NumBytes int64 `bin:"off=0x18, siz=0x8"` + + binstruct.End `bin:"off=0x20"` + } `bin:"-"` +} + +func (o *FileExtent) UnmarshalBinary(dat []byte) (int, error) { + n, err := binstruct.UnmarshalWithoutInterface(dat, o) + if err != nil { + return n, err + } + switch o.Type { + case FILE_EXTENT_INLINE: + o.BodyInline = dat[n:] + n += len(o.BodyInline) + case FILE_EXTENT_REG, FILE_EXTENT_PREALLOC: + _n, err := binstruct.Unmarshal(dat[n:], &o.BodyExtent) + n += _n + if err != nil { + return n, err + } + default: + return n, fmt.Errorf("unknown file extent type %v", o.Type) + } + return n, nil +} + +func (o FileExtent) MarshalBinary() ([]byte, error) { + dat, err := binstruct.MarshalWithoutInterface(o) + if err != nil { + return dat, err + } + switch o.Type { + case FILE_EXTENT_INLINE: + dat = append(dat, o.BodyInline...) + case FILE_EXTENT_REG, FILE_EXTENT_PREALLOC: + bs, err := binstruct.Marshal(o.BodyExtent) + dat = append(dat, bs...) + if err != nil { + return dat, err + } + default: + return dat, fmt.Errorf("unknown file extent type %v", o.Type) + } + return dat, nil +} + +type FileExtentType uint8 + +const ( + FILE_EXTENT_INLINE = FileExtentType(iota) + FILE_EXTENT_REG + FILE_EXTENT_PREALLOC +) + +func (o FileExtent) Size() (int64, error) { + switch o.Type { + case FILE_EXTENT_INLINE: + return int64(len(o.BodyInline)), nil + case FILE_EXTENT_REG, FILE_EXTENT_PREALLOC: + return o.BodyExtent.NumBytes, nil + default: + return 0, fmt.Errorf("unknown file extent type %v", o.Type) + } +} + +func (fet FileExtentType) String() string { + names := map[FileExtentType]string{ + FILE_EXTENT_INLINE: "inline", + FILE_EXTENT_REG: "regular", + FILE_EXTENT_PREALLOC: "prealloc", + } + name, ok := names[fet] + if !ok { + name = "unknown" + } + return fmt.Sprintf("%d (%s)", fet, name) +} + +type CompressionType uint8 + +const ( + COMPRESS_NONE = CompressionType(iota) + COMPRESS_ZLIB + COMPRESS_LZO + COMPRESS_ZSTD +) + +func (ct CompressionType) String() string { + names := map[CompressionType]string{ + COMPRESS_NONE: "none", + COMPRESS_ZLIB: "zlib", + COMPRESS_LZO: "lzo", + COMPRESS_ZSTD: "zstd", + } + name, ok := names[ct] + if !ok { + name = "unknown" + } + return fmt.Sprintf("%d (%s)", ct, name) +} diff --git a/lib/btrfs/btrfsitem/item_freespacebitmap.go b/lib/btrfs/btrfsitem/item_freespacebitmap.go new file mode 100644 index 0000000..6158eb0 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_freespacebitmap.go @@ -0,0 +1,12 @@ +package btrfsitem + +type FreeSpaceBitmap []byte // FREE_SPACE_BITMAP=200 + +func (o *FreeSpaceBitmap) UnmarshalBinary(dat []byte) (int, error) { + *o = dat + return len(dat), nil +} + +func (o FreeSpaceBitmap) MarshalBinary() ([]byte, error) { + return []byte(o), nil +} diff --git a/lib/btrfs/btrfsitem/item_freespaceinfo.go b/lib/btrfs/btrfsitem/item_freespaceinfo.go new file mode 100644 index 0000000..89f555e --- /dev/null +++ b/lib/btrfs/btrfsitem/item_freespaceinfo.go @@ -0,0 +1,11 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" +) + +type FreeSpaceInfo struct { // FREE_SPACE_INFO=198 + ExtentCount int32 `bin:"off=0, siz=4"` + Flags uint32 `bin:"off=4, siz=4"` + binstruct.End `bin:"off=8"` +} diff --git a/lib/btrfs/btrfsitem/item_inode.go b/lib/btrfs/btrfsitem/item_inode.go new file mode 100644 index 0000000..9b1b91b --- /dev/null +++ b/lib/btrfs/btrfsitem/item_inode.go @@ -0,0 +1,64 @@ +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/linux" + "git.lukeshu.com/btrfs-progs-ng/lib/util" +) + +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"` + 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 linux.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"?) + binstruct.End `bin:"off=0xa0"` +} + +type InodeFlags uint64 + +const ( + INODE_NODATASUM = InodeFlags(1 << iota) + INODE_NODATACOW + INODE_READONLY + INODE_NOCOMPRESS + INODE_PREALLOC + INODE_SYNC + INODE_IMMUTABLE + INODE_APPEND + INODE_NODUMP + INODE_NOATIME + INODE_DIRSYNC + INODE_COMPRESS +) + +var inodeFlagNames = []string{ + "NODATASUM", + "NODATACOW", + "READONLY", + "NOCOMPRESS", + "PREALLOC", + "SYNC", + "IMMUTABLE", + "APPEND", + "NODUMP", + "NOATIME", + "DIRSYNC", + "COMPRESS", +} + +func (f InodeFlags) Has(req InodeFlags) bool { return f&req == req } +func (f InodeFlags) String() string { return util.BitfieldString(f, inodeFlagNames, util.HexLower) } diff --git a/lib/btrfs/btrfsitem/item_inoderef.go b/lib/btrfs/btrfsitem/item_inoderef.go new file mode 100644 index 0000000..80d70e1 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_inoderef.go @@ -0,0 +1,35 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" +) + +// key.objectid = inode number of the file +// key.offset = inode number of the parent file +type InodeRef struct { // INODE_REF=12 + Index int64 `bin:"off=0x0, siz=0x8"` + NameLen uint16 `bin:"off=0x8, siz=0x2"` // [ignored-when-writing] + binstruct.End `bin:"off=0xa"` + Name []byte `bin:"-"` +} + +func (o *InodeRef) UnmarshalBinary(dat []byte) (int, error) { + n, err := binstruct.UnmarshalWithoutInterface(dat, o) + if err != nil { + return n, err + } + dat = dat[n:] + o.Name = dat[:o.NameLen] + n += int(o.NameLen) + return n, nil +} + +func (o InodeRef) MarshalBinary() ([]byte, error) { + o.NameLen = uint16(len(o.Name)) + dat, err := binstruct.MarshalWithoutInterface(o) + if err != nil { + return dat, err + } + dat = append(dat, o.Name...) + return dat, nil +} diff --git a/lib/btrfs/btrfsitem/item_metadata.go b/lib/btrfs/btrfsitem/item_metadata.go new file mode 100644 index 0000000..d51a340 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_metadata.go @@ -0,0 +1,44 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" +) + +// Metadata is like Extent, but doesn't have .Info. +type Metadata struct { // METADATA_ITEM=169 + Head ExtentHeader + Refs []ExtentInlineRef +} + +func (o *Metadata) UnmarshalBinary(dat []byte) (int, error) { + n, err := binstruct.Unmarshal(dat, &o.Head) + if err != nil { + return n, err + } + o.Refs = nil + for n < len(dat) { + var ref ExtentInlineRef + _n, err := binstruct.Unmarshal(dat[n:], &ref) + n += _n + o.Refs = append(o.Refs, ref) + if err != nil { + return n, err + } + } + return n, nil +} + +func (o Metadata) MarshalBinary() ([]byte, error) { + dat, err := binstruct.Marshal(o.Head) + if err != nil { + return dat, err + } + for _, ref := range o.Refs { + bs, err := binstruct.Marshal(ref) + dat = append(dat, bs...) + if err != nil { + return dat, err + } + } + return dat, nil +} diff --git a/lib/btrfs/btrfsitem/item_persistent.go b/lib/btrfs/btrfsitem/item_persistent.go new file mode 100644 index 0000000..cbbae76 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_persistent.go @@ -0,0 +1,19 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" +) + +const ( + DEV_STAT_WRITE_ERRS = iota + DEV_STAT_READ_ERRS + DEV_STAT_FLUSH_ERRS + DEV_STAT_CORRUPTION_ERRS + DEV_STAT_GENERATION_ERRS + DEV_STAT_VALUES_MAX +) + +type DevStats struct { // PERSISTENT_ITEM=249 + Values [DEV_STAT_VALUES_MAX]int64 `bin:"off=0, siz=40"` + binstruct.End `bin:"off=40"` +} diff --git a/lib/btrfs/btrfsitem/item_root.go b/lib/btrfs/btrfsitem/item_root.go new file mode 100644 index 0000000..ff9311f --- /dev/null +++ b/lib/btrfs/btrfsitem/item_root.go @@ -0,0 +1,51 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "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/util" +) + +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"` + 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"` + DropLevel uint8 `bin:"off=0x0ed, siz=0x01"` + Level uint8 `bin:"off=0x0ee, siz=0x01"` + GenerationV2 internal.Generation `bin:"off=0x0ef, siz=0x08"` + UUID util.UUID `bin:"off=0x0f7, siz=0x10"` + ParentUUID util.UUID `bin:"off=0x107, siz=0x10"` + ReceivedUUID util.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"` + Reserved [7]int64 `bin:"off=0x17f, siz=0x38"` + binstruct.End `bin:"off=0x1b7"` +} + +type RootFlags uint64 + +const ( + ROOT_SUBVOL_RDONLY = RootFlags(1 << iota) +) + +var rootFlagNames = []string{ + "SUBVOL_RDONLY", +} + +func (f RootFlags) Has(req RootFlags) bool { return f&req == req } +func (f RootFlags) String() string { return util.BitfieldString(f, rootFlagNames, util.HexLower) } diff --git a/lib/btrfs/btrfsitem/item_rootref.go b/lib/btrfs/btrfsitem/item_rootref.go new file mode 100644 index 0000000..c851474 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_rootref.go @@ -0,0 +1,34 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" +) + +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] + binstruct.End `bin:"off=0x12"` + Name []byte `bin:"-"` +} + +func (o *RootRef) UnmarshalBinary(dat []byte) (int, error) { + n, err := binstruct.UnmarshalWithoutInterface(dat, o) + if err != nil { + return n, err + } + o.Name = dat[n : n+int(o.NameLen)] + n += int(o.NameLen) + return n, nil +} + +func (o RootRef) MarshalBinary() ([]byte, error) { + o.NameLen = uint16(len(o.Name)) + dat, err := binstruct.MarshalWithoutInterface(o) + if err != nil { + return dat, err + } + dat = append(dat, o.Name...) + return dat, nil +} diff --git a/lib/btrfs/btrfsitem/item_shareddataref.go b/lib/btrfs/btrfsitem/item_shareddataref.go new file mode 100644 index 0000000..63897aa --- /dev/null +++ b/lib/btrfs/btrfsitem/item_shareddataref.go @@ -0,0 +1,10 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" +) + +type SharedDataRef struct { // SHARED_DATA_REF=184 + Count int32 `bin:"off=0, siz=4"` + binstruct.End `bin:"off=4"` +} diff --git a/lib/btrfs/btrfsitem/item_untyped.go b/lib/btrfs/btrfsitem/item_untyped.go new file mode 100644 index 0000000..71a9af4 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_untyped.go @@ -0,0 +1,14 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" +) + +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"` + binstruct.End `bin:"off=0x29"` +} diff --git a/lib/btrfs/btrfsitem/item_uuid.go b/lib/btrfs/btrfsitem/item_uuid.go new file mode 100644 index 0000000..6c7d4f0 --- /dev/null +++ b/lib/btrfs/btrfsitem/item_uuid.go @@ -0,0 +1,16 @@ +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" +) + +// The Key for this item is a UUID, and the item is a subvolume IDs +// that that UUID maps to. +// +// 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"` + binstruct.End `bin:"off=8"` +} diff --git a/lib/btrfs/btrfsitem/items.go b/lib/btrfs/btrfsitem/items.go new file mode 100644 index 0000000..33ff390 --- /dev/null +++ b/lib/btrfs/btrfsitem/items.go @@ -0,0 +1,77 @@ +package btrfsitem + +import ( + "fmt" + "reflect" + + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" +) + +type Type = internal.ItemType + +type Item interface { + isItem() +} + +type Error struct { + Dat []byte + Err error +} + +func (Error) isItem() {} + +func (o Error) MarshalBinary() ([]byte, error) { + return o.Dat, nil +} + +func (o *Error) UnmarshalBinary(dat []byte) (int, error) { + o.Dat = dat + return len(dat), nil +} + +// Rather than returning a separate error value, return an Error item. +func UnmarshalItem(key internal.Key, csumType btrfssum.CSumType, dat []byte) Item { + var gotyp reflect.Type + if key.ItemType == UNTYPED_KEY { + var ok bool + gotyp, ok = untypedObjID2gotype[key.ObjectID] + if !ok { + return Error{ + Dat: dat, + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v, ObjectID:%v}, dat): unknown object ID for untyped item", + key.ItemType, key.ObjectID), + } + } + } else { + var ok bool + gotyp, ok = keytype2gotype[key.ItemType] + if !ok { + return Error{ + Dat: dat, + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): unknown item type", key.ItemType), + } + } + } + retPtr := reflect.New(gotyp) + if csums, ok := retPtr.Interface().(*ExtentCSum); ok { + csums.ChecksumSize = csumType.Size() + } + n, err := binstruct.Unmarshal(dat, retPtr.Interface()) + if err != nil { + return Error{ + Dat: dat, + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): %w", key.ItemType, err), + } + + } + if n < len(dat) { + return Error{ + Dat: dat, + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): left over data: got %v bytes but only consumed %v", + key.ItemType, len(dat), n), + } + } + return retPtr.Elem().Interface().(Item) +} diff --git a/lib/btrfs/btrfsitem/items.txt b/lib/btrfs/btrfsitem/items.txt new file mode 100644 index 0000000..7898775 --- /dev/null +++ b/lib/btrfs/btrfsitem/items.txt @@ -0,0 +1,29 @@ +BLOCK_GROUP_ITEM=192 BlockGroup +CHUNK_ITEM=228 Chunk +DEV_EXTENT=204 DevExtent +DEV_ITEM=216 Dev +DIR_INDEX=96 DirEntries +DIR_ITEM=84 DirEntries +EXTENT_CSUM=128 ExtentCSum +EXTENT_DATA=108 FileExtent +EXTENT_DATA_REF=178 ExtentDataRef +EXTENT_ITEM=168 Extent +FREE_SPACE_BITMAP=200 FreeSpaceBitmap +FREE_SPACE_EXTENT=199 Empty +FREE_SPACE_INFO=198 FreeSpaceInfo +INODE_ITEM=1 Inode +INODE_REF=12 InodeRef +METADATA_ITEM=169 Metadata +ORPHAN_ITEM=48 Empty +PERSISTENT_ITEM=249 DevStats +QGROUP_RELATION=246 Empty +ROOT_BACKREF=144 RootRef +ROOT_ITEM=132 Root +ROOT_REF=156 RootRef +SHARED_BLOCK_REF=182 Empty +SHARED_DATA_REF=184 SharedDataRef +TREE_BLOCK_REF=176 Empty +UNTYPED=0:FREE_SPACE_OBJECTID FreeSpaceHeader +UUID_RECEIVED_SUBVOL=252 UUIDMap +UUID_SUBVOL=251 UUIDMap +XATTR_ITEM=24 DirEntries diff --git a/lib/btrfs/btrfsitem/items_gen.go b/lib/btrfs/btrfsitem/items_gen.go new file mode 100644 index 0000000..3b84d60 --- /dev/null +++ b/lib/btrfs/btrfsitem/items_gen.go @@ -0,0 +1,97 @@ +// Code generated by Make. DO NOT EDIT. + +package btrfsitem + +import ( + "reflect" + + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" +) + +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 +) + +var keytype2gotype = map[Type]reflect.Type{ + BLOCK_GROUP_ITEM_KEY: reflect.TypeOf(BlockGroup{}), + CHUNK_ITEM_KEY: reflect.TypeOf(Chunk{}), + DEV_EXTENT_KEY: reflect.TypeOf(DevExtent{}), + DEV_ITEM_KEY: reflect.TypeOf(Dev{}), + DIR_INDEX_KEY: reflect.TypeOf(DirEntries{}), + DIR_ITEM_KEY: reflect.TypeOf(DirEntries{}), + EXTENT_CSUM_KEY: reflect.TypeOf(ExtentCSum{}), + EXTENT_DATA_KEY: reflect.TypeOf(FileExtent{}), + EXTENT_DATA_REF_KEY: reflect.TypeOf(ExtentDataRef{}), + EXTENT_ITEM_KEY: reflect.TypeOf(Extent{}), + FREE_SPACE_BITMAP_KEY: reflect.TypeOf(FreeSpaceBitmap{}), + FREE_SPACE_EXTENT_KEY: reflect.TypeOf(Empty{}), + FREE_SPACE_INFO_KEY: reflect.TypeOf(FreeSpaceInfo{}), + INODE_ITEM_KEY: reflect.TypeOf(Inode{}), + INODE_REF_KEY: reflect.TypeOf(InodeRef{}), + METADATA_ITEM_KEY: reflect.TypeOf(Metadata{}), + ORPHAN_ITEM_KEY: reflect.TypeOf(Empty{}), + PERSISTENT_ITEM_KEY: reflect.TypeOf(DevStats{}), + QGROUP_RELATION_KEY: reflect.TypeOf(Empty{}), + ROOT_BACKREF_KEY: reflect.TypeOf(RootRef{}), + ROOT_ITEM_KEY: reflect.TypeOf(Root{}), + ROOT_REF_KEY: reflect.TypeOf(RootRef{}), + SHARED_BLOCK_REF_KEY: reflect.TypeOf(Empty{}), + SHARED_DATA_REF_KEY: reflect.TypeOf(SharedDataRef{}), + TREE_BLOCK_REF_KEY: reflect.TypeOf(Empty{}), + UUID_RECEIVED_SUBVOL_KEY: reflect.TypeOf(UUIDMap{}), + UUID_SUBVOL_KEY: reflect.TypeOf(UUIDMap{}), + XATTR_ITEM_KEY: reflect.TypeOf(DirEntries{}), +} +var untypedObjID2gotype = map[internal.ObjID]reflect.Type{ + internal.FREE_SPACE_OBJECTID: reflect.TypeOf(FreeSpaceHeader{}), +} + +func (BlockGroup) isItem() {} +func (Chunk) isItem() {} +func (Dev) isItem() {} +func (DevExtent) isItem() {} +func (DevStats) isItem() {} +func (DirEntries) isItem() {} +func (Empty) isItem() {} +func (Extent) isItem() {} +func (ExtentCSum) isItem() {} +func (ExtentDataRef) isItem() {} +func (FileExtent) isItem() {} +func (FreeSpaceBitmap) isItem() {} +func (FreeSpaceHeader) isItem() {} +func (FreeSpaceInfo) isItem() {} +func (Inode) isItem() {} +func (InodeRef) isItem() {} +func (Metadata) isItem() {} +func (Root) isItem() {} +func (RootRef) isItem() {} +func (SharedDataRef) isItem() {} +func (UUIDMap) isItem() {} -- cgit v1.2.3-2-g168b