summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-07-02 17:35:46 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-07-02 17:35:46 -0600
commitc8e863f886c8cf2ee60d28254fa94a6d4f6a566d (patch)
tree80c75e111f75079a5c408f4bce5f456b5861d9b5
parentcd46b6b734d833a9e2d83ba92e8f7348e63afe7e (diff)
Properly implement EXTENT_DATA_REF_KEY inside of an inline ref
-rw-r--r--pkg/btrfs/btrfsitem/item_extent.go71
-rw-r--r--pkg/btrfs/btrfsitem/item_extentdataref.go2
-rw-r--r--pkg/btrfsmisc/print_tree.go2
3 files changed, 54 insertions, 21 deletions
diff --git a/pkg/btrfs/btrfsitem/item_extent.go b/pkg/btrfs/btrfsitem/item_extent.go
index 778b67f..ab8a4c6 100644
--- a/pkg/btrfs/btrfsitem/item_extent.go
+++ b/pkg/btrfs/btrfsitem/item_extent.go
@@ -90,43 +90,76 @@ 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 `bin:"off=0, siz=1"`
- Offset uint64 `bin:"off=1, siz=8"`
- binstruct.End `bin:"off=9"`
- Body Item `bin:"-"`
+ 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) {
- n, err := binstruct.UnmarshalWithoutInterface(dat, o)
- if err != nil {
- return n, err
- }
+ o.Type = Type(dat[0])
+ n := 1
switch o.Type {
case TREE_BLOCK_REF_KEY, SHARED_BLOCK_REF_KEY:
- o.Body = Empty{}
+ _n, err := binstruct.Unmarshal(dat[n:], &o.Offset)
+ n += _n
+ if err != nil {
+ return n, err
+ }
case EXTENT_DATA_REF_KEY:
- return n, fmt.Errorf("the C code to do this doesn't make any sense")
+ 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, 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, err := binstruct.MarshalWithoutInterface(o)
- if err != nil {
- return dat, err
- }
- bs, err := binstruct.Marshal(o.Body)
- dat = append(dat, bs...)
- if err != nil {
- return dat, err
+ 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/pkg/btrfs/btrfsitem/item_extentdataref.go b/pkg/btrfs/btrfsitem/item_extentdataref.go
index c898b72..93585be 100644
--- a/pkg/btrfs/btrfsitem/item_extentdataref.go
+++ b/pkg/btrfs/btrfsitem/item_extentdataref.go
@@ -6,7 +6,7 @@ import (
)
type ExtentDataRef struct { // EXTENT_DATA_REF=178
- Root int64 `bin:"off=0, siz=8"`
+ 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"`
diff --git a/pkg/btrfsmisc/print_tree.go b/pkg/btrfsmisc/print_tree.go
index 59ad0f5..3a13504 100644
--- a/pkg/btrfsmisc/print_tree.go
+++ b/pkg/btrfsmisc/print_tree.go
@@ -309,7 +309,7 @@ func printHeaderInfo(node btrfs.Node) {
func printExtentInlineRefs(refs []btrfsitem.ExtentInlineRef) {
for _, ref := range refs {
switch subitem := ref.Body.(type) {
- case btrfsitem.Empty:
+ case nil:
switch ref.Type {
case btrfsitem.TREE_BLOCK_REF_KEY:
fmt.Printf("\t\ttree block backref root %v\n",