summaryrefslogtreecommitdiff
path: root/lib/btrfs/btrfsprim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfs/btrfsprim')
-rw-r--r--lib/btrfs/btrfsprim/itemtype.go7
-rw-r--r--lib/btrfs/btrfsprim/key.go101
-rw-r--r--lib/btrfs/btrfsprim/key_test.go59
-rw-r--r--lib/btrfs/btrfsprim/misc.go71
-rw-r--r--lib/btrfs/btrfsprim/objid.go3
5 files changed, 169 insertions, 72 deletions
diff --git a/lib/btrfs/btrfsprim/itemtype.go b/lib/btrfs/btrfsprim/itemtype.go
index f33179a..682fecd 100644
--- a/lib/btrfs/btrfsprim/itemtype.go
+++ b/lib/btrfs/btrfsprim/itemtype.go
@@ -2,7 +2,10 @@
package btrfsprim
-import "fmt"
+import (
+ "fmt"
+ "math"
+)
type ItemType uint8
@@ -39,6 +42,8 @@ const (
UUID_RECEIVED_SUBVOL_KEY ItemType = 252
UUID_SUBVOL_KEY ItemType = 251
XATTR_ITEM_KEY ItemType = 24
+
+ MAX_KEY ItemType = math.MaxUint8
)
func (t ItemType) String() string {
diff --git a/lib/btrfs/btrfsprim/key.go b/lib/btrfs/btrfsprim/key.go
new file mode 100644
index 0000000..b07cc8c
--- /dev/null
+++ b/lib/btrfs/btrfsprim/key.go
@@ -0,0 +1,101 @@
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package btrfsprim
+
+import (
+ "fmt"
+ "math"
+
+ "git.lukeshu.com/btrfs-progs-ng/lib/binstruct"
+ "git.lukeshu.com/btrfs-progs-ng/lib/containers"
+)
+
+type Key struct {
+ ObjectID ObjID `bin:"off=0x0, siz=0x8"` // Each tree has its own set of Object IDs.
+ ItemType ItemType `bin:"off=0x8, siz=0x1"`
+ Offset uint64 `bin:"off=0x9, siz=0x8"` // The meaning depends on the item type.
+ binstruct.End `bin:"off=0x11"`
+}
+
+const MaxOffset uint64 = math.MaxUint64
+
+// mimics print-tree.c:btrfs_print_key()
+func (key Key) Format(tree ObjID) string {
+ switch tree {
+ case UUID_TREE_OBJECTID:
+ return fmt.Sprintf("(%v %v %#08x)",
+ key.ObjectID.Format(tree),
+ key.ItemType,
+ key.Offset)
+ case ROOT_TREE_OBJECTID, QUOTA_TREE_OBJECTID:
+ return fmt.Sprintf("(%v %v %v)",
+ key.ObjectID.Format(tree),
+ key.ItemType,
+ ObjID(key.Offset).Format(tree))
+ default:
+ if key.Offset == math.MaxUint64 {
+ return fmt.Sprintf("(%v %v -1)",
+ key.ObjectID.Format(tree),
+ key.ItemType)
+ } else {
+ return fmt.Sprintf("(%v %v %v)",
+ key.ObjectID.Format(tree),
+ key.ItemType,
+ key.Offset)
+ }
+ }
+}
+
+func (key Key) String() string {
+ return key.Format(0)
+}
+
+var MaxKey = Key{
+ ObjectID: math.MaxUint64,
+ ItemType: math.MaxUint8,
+ Offset: math.MaxUint64,
+}
+
+func (key Key) Mm() Key {
+ switch {
+ case key.Offset > 0:
+ key.Offset--
+ case key.ItemType > 0:
+ key.ItemType--
+ key.Offset = MaxOffset
+ case key.ObjectID > 0:
+ key.ObjectID--
+ key.ItemType = MAX_KEY
+ key.Offset = MaxOffset
+ }
+ return key
+}
+
+func (key Key) Pp() Key {
+ switch {
+ case key.Offset < MaxOffset:
+ key.Offset++
+ case key.ItemType < MAX_KEY:
+ key.ItemType++
+ key.Offset = 0
+ case key.ObjectID < MAX_OBJECTID:
+ key.ObjectID++
+ key.ItemType = 0
+ key.Offset = 0
+ }
+ return key
+}
+
+func (a Key) Compare(b Key) int {
+ if d := containers.NativeCompare(a.ObjectID, b.ObjectID); d != 0 {
+ return d
+ }
+ if d := containers.NativeCompare(a.ItemType, b.ItemType); d != 0 {
+ return d
+ }
+ return containers.NativeCompare(a.Offset, b.Offset)
+}
+
+var _ containers.Ordered[Key] = Key{}
diff --git a/lib/btrfs/btrfsprim/key_test.go b/lib/btrfs/btrfsprim/key_test.go
new file mode 100644
index 0000000..6274b43
--- /dev/null
+++ b/lib/btrfs/btrfsprim/key_test.go
@@ -0,0 +1,59 @@
+// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package btrfsprim
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func k(objID ObjID, typ ItemType, offset uint64) Key {
+ return Key{
+ ObjectID: objID,
+ ItemType: typ,
+ Offset: offset,
+ }
+}
+
+func eq(t *testing.T, act, exp Key) {
+ t.Helper()
+ assert.Equal(t, exp, act)
+}
+
+func ppEq(t *testing.T, in, exp Key) {
+ t.Helper()
+ eq(t, in.Pp(), exp)
+ if in != MaxKey {
+ eq(t, exp.Mm(), in)
+ }
+}
+
+func mmEq(t *testing.T, in, exp Key) {
+ t.Helper()
+ eq(t, in.Mm(), exp)
+ if in != (Key{}) {
+ eq(t, exp.Pp(), in)
+ }
+}
+
+func TestKey(t *testing.T) {
+ t.Parallel()
+
+ eq(t, MaxKey, k(18446744073709551615, 255, 18446744073709551615))
+
+ // pp
+ ppEq(t, k(0, 0, 0), k(0, 0, 1))
+ ppEq(t, k(0, 0, 18446744073709551615), k(0, 1, 0))
+ ppEq(t, k(0, 255, 0), k(0, 255, 1))
+ ppEq(t, k(0, 255, 18446744073709551615), k(1, 0, 0))
+ ppEq(t, MaxKey, k(18446744073709551615, 255, 18446744073709551615))
+
+ // mm
+ mmEq(t, MaxKey, k(18446744073709551615, 255, 18446744073709551614))
+ mmEq(t, k(18446744073709551615, 255, 0), k(18446744073709551615, 254, 18446744073709551615))
+ mmEq(t, k(18446744073709551615, 0, 0), k(18446744073709551614, 255, 18446744073709551615))
+ mmEq(t, k(0, 0, 0), k(0, 0, 0))
+}
diff --git a/lib/btrfs/btrfsprim/misc.go b/lib/btrfs/btrfsprim/misc.go
index ca2e313..38290d6 100644
--- a/lib/btrfs/btrfsprim/misc.go
+++ b/lib/btrfs/btrfsprim/misc.go
@@ -5,84 +5,13 @@
package btrfsprim
import (
- "fmt"
- "math"
"time"
"git.lukeshu.com/btrfs-progs-ng/lib/binstruct"
- "git.lukeshu.com/btrfs-progs-ng/lib/containers"
)
type Generation uint64
-type Key struct {
- ObjectID ObjID `bin:"off=0x0, siz=0x8"` // Each tree has its own set of Object IDs.
- ItemType ItemType `bin:"off=0x8, siz=0x1"`
- Offset uint64 `bin:"off=0x9, siz=0x8"` // The meaning depends on the item type.
- binstruct.End `bin:"off=0x11"`
-}
-
-// mimics print-tree.c:btrfs_print_key()
-func (key Key) Format(tree ObjID) string {
- switch tree {
- case UUID_TREE_OBJECTID:
- return fmt.Sprintf("(%v %v %#08x)",
- key.ObjectID.Format(tree),
- key.ItemType,
- key.Offset)
- case ROOT_TREE_OBJECTID, QUOTA_TREE_OBJECTID:
- return fmt.Sprintf("(%v %v %v)",
- key.ObjectID.Format(tree),
- key.ItemType,
- ObjID(key.Offset).Format(tree))
- default:
- if key.Offset == math.MaxUint64 {
- return fmt.Sprintf("(%v %v -1)",
- key.ObjectID.Format(tree),
- key.ItemType)
- } else {
- return fmt.Sprintf("(%v %v %v)",
- key.ObjectID.Format(tree),
- key.ItemType,
- key.Offset)
- }
- }
-}
-
-func (key Key) String() string {
- return key.Format(0)
-}
-
-var MaxKey = Key{
- ObjectID: math.MaxUint64,
- ItemType: math.MaxUint8,
- Offset: math.MaxUint64,
-}
-
-func (key Key) Mm() Key {
- switch {
- case key.Offset > 0:
- key.Offset--
- case key.ItemType > 0:
- key.ItemType--
- case key.ObjectID > 0:
- key.ObjectID--
- }
- return key
-}
-
-func (a Key) Compare(b Key) int {
- if d := containers.NativeCompare(a.ObjectID, b.ObjectID); d != 0 {
- return d
- }
- if d := containers.NativeCompare(a.ItemType, b.ItemType); d != 0 {
- return d
- }
- return containers.NativeCompare(a.Offset, b.Offset)
-}
-
-var _ containers.Ordered[Key] = Key{}
-
type Time struct {
Sec int64 `bin:"off=0x0, siz=0x8"` // Number of seconds since 1970-01-01T00:00:00Z.
NSec uint32 `bin:"off=0x8, siz=0x4"` // Number of nanoseconds since the beginning of the second.
diff --git a/lib/btrfs/btrfsprim/objid.go b/lib/btrfs/btrfsprim/objid.go
index 1aea030..f364957 100644
--- a/lib/btrfs/btrfsprim/objid.go
+++ b/lib/btrfs/btrfsprim/objid.go
@@ -6,6 +6,7 @@ package btrfsprim
import (
"fmt"
+ "math"
)
type ObjID uint64
@@ -52,6 +53,8 @@ const (
// ???
EMPTY_SUBVOL_DIR_OBJECTID ObjID = 2
+
+ MAX_OBJECTID ObjID = math.MaxUint64
)
var (