summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-03-16 09:17:35 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2023-03-17 18:38:44 -0400
commit1bc243ca607c22e232017b0f1b4badcde288a9b3 (patch)
tree7273d158c1184d2c582a15fc36af695eb1a20943
parent0f85e72d1331b49b52925d6cc5ad083a0376104c (diff)
btrfstree: Have ReadNode return a *Node rather than a *diskio.Ref[Addr, Node]
... and take a ReaderAt instead of a diskio.File.
-rw-r--r--cmd/btrfs-rec/inspect/dumptrees/print_tree.go9
-rw-r--r--cmd/btrfs-rec/inspect/rebuildmappings/scan.go25
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/scan.go10
-rw-r--r--cmd/btrfs-rec/inspect_lstrees.go7
-rw-r--r--lib/btrfs/btrfstree/btree.go10
-rw-r--r--lib/btrfs/btrfstree/btree_tree.go184
-rw-r--r--lib/btrfs/btrfstree/readnode.go4
-rw-r--r--lib/btrfs/btrfstree/types_node.go80
-rw-r--r--lib/btrfs/io3_btree.go4
-rw-r--r--lib/btrfs/io4_fs.go3
-rw-r--r--lib/btrfsutil/graph.go32
-rw-r--r--lib/btrfsutil/listnodes.go5
-rw-r--r--lib/btrfsutil/old_rebuilt_forrest.go37
-rw-r--r--lib/btrfsutil/rebuilt_readitem.go28
-rw-r--r--lib/btrfsutil/scan.go9
-rw-r--r--lib/btrfsutil/skinny_paths.go24
-rw-r--r--lib/diskio/file_iface.go8
17 files changed, 228 insertions, 251 deletions
diff --git a/cmd/btrfs-rec/inspect/dumptrees/print_tree.go b/cmd/btrfs-rec/inspect/dumptrees/print_tree.go
index a8c2adf..9572f3a 100644
--- a/cmd/btrfs-rec/inspect/dumptrees/print_tree.go
+++ b/cmd/btrfs-rec/inspect/dumptrees/print_tree.go
@@ -19,7 +19,6 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum"
"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"
"git.lukeshu.com/btrfs-progs-ng/lib/slices"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
@@ -100,9 +99,9 @@ var nodeHeaderSize = binstruct.StaticSize(btrfstree.NodeHeader{})
func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfsprim.ObjID) {
var itemOffset uint32
handlers := btrfstree.TreeWalkHandler{
- Node: func(path btrfstree.TreePath, nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error {
- printHeaderInfo(out, nodeRef.Data)
- itemOffset = nodeRef.Data.Size - uint32(nodeHeaderSize)
+ Node: func(path btrfstree.TreePath, node *btrfstree.Node) error {
+ printHeaderInfo(out, node)
+ itemOffset = node.Size - uint32(nodeHeaderSize)
return nil
},
PreKeyPointer: func(path btrfstree.TreePath, item btrfstree.KeyPointer) error {
@@ -375,7 +374,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri
}
// printHeaderInfo mimics btrfs-progs kernel-shared/print-tree.c:print_header_info()
-func printHeaderInfo(out io.Writer, node btrfstree.Node) {
+func printHeaderInfo(out io.Writer, node *btrfstree.Node) {
var typename string
if node.Head.Level > 0 { // interior node
typename = "node"
diff --git a/cmd/btrfs-rec/inspect/rebuildmappings/scan.go b/cmd/btrfs-rec/inspect/rebuildmappings/scan.go
index b88f01c..e23314e 100644
--- a/cmd/btrfs-rec/inspect/rebuildmappings/scan.go
+++ b/cmd/btrfs-rec/inspect/rebuildmappings/scan.go
@@ -19,7 +19,6 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfsutil"
"git.lukeshu.com/btrfs-progs-ng/lib/containers"
- "git.lukeshu.com/btrfs-progs-ng/lib/diskio"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
@@ -121,22 +120,22 @@ func (scanner *deviceScanner) ScanSector(_ context.Context, dev *btrfs.Device, p
return nil
}
-func (scanner *deviceScanner) ScanNode(ctx context.Context, nodeRef *diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Node]) error {
- scanner.result.FoundNodes[nodeRef.Data.Head.Addr] = append(scanner.result.FoundNodes[nodeRef.Data.Head.Addr], nodeRef.Addr)
- for i, item := range nodeRef.Data.BodyLeaf {
+func (scanner *deviceScanner) ScanNode(ctx context.Context, addr btrfsvol.PhysicalAddr, node *btrfstree.Node) error {
+ scanner.result.FoundNodes[node.Head.Addr] = append(scanner.result.FoundNodes[node.Head.Addr], addr)
+ for i, item := range node.BodyLeaf {
switch item.Key.ItemType {
case btrfsitem.CHUNK_ITEM_KEY:
switch itemBody := item.Body.(type) {
case *btrfsitem.Chunk:
dlog.Tracef(ctx, "node@%v: item %v: found chunk",
- nodeRef.Addr, i)
+ addr, i)
scanner.result.FoundChunks = append(scanner.result.FoundChunks, btrfstree.SysChunk{
Key: item.Key,
Chunk: *itemBody,
})
case *btrfsitem.Error:
dlog.Errorf(ctx, "node@%v: item %v: error: malformed CHUNK_ITEM: %v",
- nodeRef.Addr, i, itemBody.Err)
+ addr, i, itemBody.Err)
default:
panic(fmt.Errorf("should not happen: CHUNK_ITEM has unexpected item type: %T", itemBody))
}
@@ -144,14 +143,14 @@ func (scanner *deviceScanner) ScanNode(ctx context.Context, nodeRef *diskio.Ref[
switch itemBody := item.Body.(type) {
case *btrfsitem.BlockGroup:
dlog.Tracef(ctx, "node@%v: item %v: found block group",
- nodeRef.Addr, i)
+ addr, i)
scanner.result.FoundBlockGroups = append(scanner.result.FoundBlockGroups, SysBlockGroup{
Key: item.Key,
BG: *itemBody,
})
case *btrfsitem.Error:
dlog.Errorf(ctx, "node@%v: item %v: error: malformed BLOCK_GROUP_ITEM: %v",
- nodeRef.Addr, i, itemBody.Err)
+ addr, i, itemBody.Err)
default:
panic(fmt.Errorf("should not happen: BLOCK_GROUP_ITEM has unexpected item type: %T", itemBody))
}
@@ -159,14 +158,14 @@ func (scanner *deviceScanner) ScanNode(ctx context.Context, nodeRef *diskio.Ref[
switch itemBody := item.Body.(type) {
case *btrfsitem.DevExtent:
dlog.Tracef(ctx, "node@%v: item %v: found dev extent",
- nodeRef.Addr, i)
+ addr, i)
scanner.result.FoundDevExtents = append(scanner.result.FoundDevExtents, SysDevExtent{
Key: item.Key,
DevExt: *itemBody,
})
case *btrfsitem.Error:
dlog.Errorf(ctx, "node@%v: item %v: error: malformed DEV_EXTENT: %v",
- nodeRef.Addr, i, itemBody.Err)
+ addr, i, itemBody.Err)
default:
panic(fmt.Errorf("should not happen: DEV_EXTENT has unexpected item type: %T", itemBody))
}
@@ -174,14 +173,14 @@ func (scanner *deviceScanner) ScanNode(ctx context.Context, nodeRef *diskio.Ref[
switch itemBody := item.Body.(type) {
case *btrfsitem.ExtentCSum:
dlog.Tracef(ctx, "node@%v: item %v: found csums",
- nodeRef.Addr, i)
+ addr, i)
scanner.result.FoundExtentCSums = append(scanner.result.FoundExtentCSums, SysExtentCSum{
- Generation: nodeRef.Data.Head.Generation,
+ Generation: node.Head.Generation,
Sums: *itemBody,
})
case *btrfsitem.Error:
dlog.Errorf(ctx, "node@%v: item %v: error: malformed is EXTENT_CSUM: %v",
- nodeRef.Addr, i, itemBody.Err)
+ addr, i, itemBody.Err)
default:
panic(fmt.Errorf("should not happen: EXTENT_CSUM has unexpected item type: %T", itemBody))
}
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/scan.go b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
index ba56c5b..4bc09ad 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
@@ -41,18 +41,18 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, nodeList []btrfsvol.LogicalA
if err := ctx.Err(); err != nil {
return btrfstree.Superblock{}, btrfsutil.Graph{}, nil, err
}
- nodeRef, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, laddr, btrfstree.NodeExpectations{
+ node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, laddr, btrfstree.NodeExpectations{
LAddr: containers.Optional[btrfsvol.LogicalAddr]{OK: true, Val: laddr},
})
if err != nil {
- btrfstree.FreeNodeRef(nodeRef)
+ node.Free()
return btrfstree.Superblock{}, btrfsutil.Graph{}, nil, err
}
- nodeGraph.InsertNode(nodeRef)
- keyIO.InsertNode(nodeRef)
+ nodeGraph.InsertNode(node)
+ keyIO.InsertNode(node)
- btrfstree.FreeNodeRef(nodeRef)
+ node.Free()
stats.N++
progressWriter.Set(stats)
diff --git a/cmd/btrfs-rec/inspect_lstrees.go b/cmd/btrfs-rec/inspect_lstrees.go
index 05c3a57..70f4f51 100644
--- a/cmd/btrfs-rec/inspect_lstrees.go
+++ b/cmd/btrfs-rec/inspect_lstrees.go
@@ -19,7 +19,6 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfsutil"
"git.lukeshu.com/btrfs-progs-ng/lib/containers"
- "git.lukeshu.com/btrfs-progs-ng/lib/diskio"
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
"git.lukeshu.com/btrfs-progs-ng/lib/slices"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
@@ -76,8 +75,8 @@ func init() {
treeErrCnt++
},
TreeWalkHandler: btrfstree.TreeWalkHandler{
- Node: func(_ btrfstree.TreePath, ref *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error {
- visitedNodes.Insert(ref.Addr)
+ Node: func(path btrfstree.TreePath, node *btrfstree.Node) error {
+ visitedNodes.Insert(path.Node(-1).ToNodeAddr)
return nil
},
Item: func(_ btrfstree.TreePath, item btrfstree.Item) error {
@@ -113,7 +112,7 @@ func init() {
treeErrCnt++
continue
}
- for _, item := range node.Data.BodyLeaf {
+ for _, item := range node.BodyLeaf {
typ := item.Key.ItemType
treeItemCnt[typ]++
}
diff --git a/lib/btrfs/btrfstree/btree.go b/lib/btrfs/btrfstree/btree.go
index 89d4f9d..c71aad5 100644
--- a/lib/btrfs/btrfstree/btree.go
+++ b/lib/btrfs/btrfstree/btree.go
@@ -11,8 +11,6 @@ import (
"fmt"
"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"
)
type TreeSearcher interface {
@@ -72,9 +70,9 @@ type TreeWalkHandler struct {
// or BadNode return io/fs.SkipDir then key pointers and items
// within the node are not processed.
PreNode func(TreePath) error
- 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
+ Node func(TreePath, *Node) error
+ BadNode func(TreePath, *Node, error) error
+ PostNode func(TreePath, *Node) error
// Callbacks for items on interior nodes
PreKeyPointer func(TreePath, KeyPointer) error
PostKeyPointer func(TreePath, KeyPointer) error
@@ -96,5 +94,5 @@ func (e *TreeError) Error() string {
type NodeSource interface {
Superblock() (*Superblock, error)
- ReadNode(TreePath) (*diskio.Ref[btrfsvol.LogicalAddr, Node], error)
+ ReadNode(TreePath) (*Node, error)
}
diff --git a/lib/btrfs/btrfstree/btree_tree.go b/lib/btrfs/btrfstree/btree_tree.go
index 1e3c789..7561314 100644
--- a/lib/btrfs/btrfstree/btree_tree.go
+++ b/lib/btrfs/btrfstree/btree_tree.go
@@ -15,8 +15,6 @@ import (
"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"
)
@@ -72,7 +70,7 @@ func (fs TreeOperatorImpl) treeWalk(ctx context.Context, path TreePath, errHandl
}
}
node, err := fs.ReadNode(path)
- defer FreeNodeRef(node)
+ defer node.Free()
if ctx.Err() != nil {
return
}
@@ -97,17 +95,17 @@ func (fs TreeOperatorImpl) treeWalk(ctx context.Context, path TreePath, errHandl
return
}
if node != nil {
- for i, item := range node.Data.BodyInterior {
+ for i, item := range node.BodyInterior {
toMaxKey := path.Node(-1).ToMaxKey
- if i+1 < len(node.Data.BodyInterior) {
- toMaxKey = node.Data.BodyInterior[i+1].Key.Mm()
+ if i+1 < len(node.BodyInterior) {
+ toMaxKey = node.BodyInterior[i+1].Key.Mm()
}
itemPath := append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: i,
ToNodeAddr: item.BlockPtr,
ToNodeGeneration: item.Generation,
- ToNodeLevel: node.Data.Head.Level - 1,
+ ToNodeLevel: node.Head.Level - 1,
ToKey: item.Key,
ToMaxKey: toMaxKey,
})
@@ -129,9 +127,9 @@ func (fs TreeOperatorImpl) treeWalk(ctx context.Context, path TreePath, errHandl
}
}
}
- for i, item := range node.Data.BodyLeaf {
+ for i, item := range node.BodyLeaf {
itemPath := append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: i,
ToKey: item.Key,
ToMaxKey: item.Key,
@@ -169,7 +167,7 @@ func (fs TreeOperatorImpl) treeWalk(ctx context.Context, path TreePath, errHandl
}
}
-func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key, uint32) int) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) {
+func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key, uint32) int) (TreePath, *Node, error) {
path := TreePath{{
FromTree: treeRoot.TreeID,
FromItemSlot: -1,
@@ -184,15 +182,15 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
}
node, err := fs.ReadNode(path)
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
switch {
- case node.Data.Head.Level > 0:
+ case node.Head.Level > 0:
// interior node
- // Search for the right-most node.Data.BodyInterior item for which
+ // Search for the right-most node.BodyInterior item for which
// `fn(item.Key) >= 0`.
//
// + + + + 0 - - - -
@@ -200,31 +198,31 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
// There may or may not be a value that returns '0'.
//
// i.e. find the highest value that isn't too high.
- lastGood, ok := slices.SearchHighest(node.Data.BodyInterior, func(kp KeyPointer) int {
+ lastGood, ok := slices.SearchHighest(node.BodyInterior, func(kp KeyPointer) int {
return slices.Min(fn(kp.Key, math.MaxUint32), 0) // don't return >0; a key can't be "too low"
})
if !ok {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, ErrNoItem
}
toMaxKey := path.Node(-1).ToMaxKey
- if lastGood+1 < len(node.Data.BodyInterior) {
- toMaxKey = node.Data.BodyInterior[lastGood+1].Key.Mm()
+ if lastGood+1 < len(node.BodyInterior) {
+ toMaxKey = node.BodyInterior[lastGood+1].Key.Mm()
}
path = append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: lastGood,
- ToNodeAddr: node.Data.BodyInterior[lastGood].BlockPtr,
- ToNodeGeneration: node.Data.BodyInterior[lastGood].Generation,
- ToNodeLevel: node.Data.Head.Level - 1,
- ToKey: node.Data.BodyInterior[lastGood].Key,
+ ToNodeAddr: node.BodyInterior[lastGood].BlockPtr,
+ ToNodeGeneration: node.BodyInterior[lastGood].Generation,
+ ToNodeLevel: node.Head.Level - 1,
+ ToKey: node.BodyInterior[lastGood].Key,
ToMaxKey: toMaxKey,
})
- FreeNodeRef(node)
+ node.Free()
default:
// leaf node
- // Search for a member of node.Data.BodyLeaf for which
+ // Search for a member of node.BodyLeaf for which
// `fn(item.Head.Key) == 0`.
//
// + + + + 0 - - - -
@@ -234,25 +232,25 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
// is returned.
//
// Implement this search as a binary search.
- slot, ok := slices.Search(node.Data.BodyLeaf, func(item Item) int {
+ slot, ok := slices.Search(node.BodyLeaf, func(item Item) int {
return fn(item.Key, item.BodySize)
})
if !ok {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, ErrNoItem
}
path = append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: slot,
- ToKey: node.Data.BodyLeaf[slot].Key,
- ToMaxKey: node.Data.BodyLeaf[slot].Key,
+ ToKey: node.BodyLeaf[slot].Key,
+ ToMaxKey: node.BodyLeaf[slot].Key,
})
return path, node, nil
}
}
}
-func (fs TreeOperatorImpl) prev(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) {
+func (fs TreeOperatorImpl) prev(path TreePath, node *Node) (TreePath, *Node, error) {
var err error
path = path.DeepCopy()
@@ -266,139 +264,139 @@ func (fs TreeOperatorImpl) prev(path TreePath, node *diskio.Ref[btrfsvol.Logical
// go left
path.Node(-1).FromItemSlot--
if path.Node(-1).ToNodeAddr != 0 {
- if node.Addr != path.Node(-2).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-2).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path.Parent())
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
- path.Node(-1).ToNodeAddr = node.Data.BodyInterior[path.Node(-1).FromItemSlot].BlockPtr
+ path.Node(-1).ToNodeAddr = node.BodyInterior[path.Node(-1).FromItemSlot].BlockPtr
}
}
// go down
for path.Node(-1).ToNodeAddr != 0 {
- if node.Addr != path.Node(-1).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-1).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path)
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
}
- if node.Data.Head.Level > 0 {
+ if node.Head.Level > 0 {
path = append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
- FromItemSlot: len(node.Data.BodyInterior) - 1,
- ToNodeAddr: node.Data.BodyInterior[len(node.Data.BodyInterior)-1].BlockPtr,
- ToNodeGeneration: node.Data.BodyInterior[len(node.Data.BodyInterior)-1].Generation,
- ToNodeLevel: node.Data.Head.Level - 1,
- ToKey: node.Data.BodyInterior[len(node.Data.BodyInterior)-1].Key,
+ FromTree: node.Head.Owner,
+ FromItemSlot: len(node.BodyInterior) - 1,
+ ToNodeAddr: node.BodyInterior[len(node.BodyInterior)-1].BlockPtr,
+ ToNodeGeneration: node.BodyInterior[len(node.BodyInterior)-1].Generation,
+ ToNodeLevel: node.Head.Level - 1,
+ ToKey: node.BodyInterior[len(node.BodyInterior)-1].Key,
ToMaxKey: path.Node(-1).ToMaxKey,
})
} else {
path = append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
- FromItemSlot: len(node.Data.BodyLeaf) - 1,
- ToKey: node.Data.BodyLeaf[len(node.Data.BodyLeaf)-1].Key,
- ToMaxKey: node.Data.BodyLeaf[len(node.Data.BodyLeaf)-1].Key,
+ FromTree: node.Head.Owner,
+ FromItemSlot: len(node.BodyLeaf) - 1,
+ ToKey: node.BodyLeaf[len(node.BodyLeaf)-1].Key,
+ ToMaxKey: node.BodyLeaf[len(node.BodyLeaf)-1].Key,
})
}
}
// return
- if node.Addr != path.Node(-2).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-2).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path.Parent())
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
}
return path, node, nil
}
-func (fs TreeOperatorImpl) next(path TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, Node]) (TreePath, *diskio.Ref[btrfsvol.LogicalAddr, Node], error) {
+func (fs TreeOperatorImpl) next(path TreePath, node *Node) (TreePath, *Node, error) {
var err error
path = path.DeepCopy()
// go up
- if node.Addr != path.Node(-2).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-2).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path.Parent())
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
- path.Node(-2).ToNodeLevel = node.Data.Head.Level
+ path.Node(-2).ToNodeLevel = node.Head.Level
}
- for path.Node(-1).FromItemSlot+1 >= int(node.Data.Head.NumItems) {
+ for path.Node(-1).FromItemSlot+1 >= int(node.Head.NumItems) {
path = path.Parent()
if len(path) == 1 {
return nil, nil, nil
}
- if node.Addr != path.Node(-2).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-2).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path.Parent())
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
- path.Node(-2).ToNodeLevel = node.Data.Head.Level
+ path.Node(-2).ToNodeLevel = node.Head.Level
}
}
// go right
path.Node(-1).FromItemSlot++
if path.Node(-1).ToNodeAddr != 0 {
- if node.Addr != path.Node(-2).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-2).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path.Parent())
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
- path.Node(-1).ToNodeAddr = node.Data.BodyInterior[path.Node(-1).FromItemSlot].BlockPtr
+ path.Node(-1).ToNodeAddr = node.BodyInterior[path.Node(-1).FromItemSlot].BlockPtr
}
}
// go down
for path.Node(-1).ToNodeAddr != 0 {
- if node.Addr != path.Node(-1).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-1).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path)
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
- path.Node(-1).ToNodeLevel = node.Data.Head.Level
+ path.Node(-1).ToNodeLevel = node.Head.Level
}
- if node.Data.Head.Level > 0 {
+ if node.Head.Level > 0 {
toMaxKey := path.Node(-1).ToMaxKey
- if len(node.Data.BodyInterior) > 1 {
- toMaxKey = node.Data.BodyInterior[1].Key.Mm()
+ if len(node.BodyInterior) > 1 {
+ toMaxKey = node.BodyInterior[1].Key.Mm()
}
path = append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: 0,
- ToNodeAddr: node.Data.BodyInterior[0].BlockPtr,
- ToNodeGeneration: node.Data.BodyInterior[0].Generation,
- ToNodeLevel: node.Data.Head.Level - 1,
- ToKey: node.Data.BodyInterior[0].Key,
+ ToNodeAddr: node.BodyInterior[0].BlockPtr,
+ ToNodeGeneration: node.BodyInterior[0].Generation,
+ ToNodeLevel: node.Head.Level - 1,
+ ToKey: node.BodyInterior[0].Key,
ToMaxKey: toMaxKey,
})
} else {
path = append(path, TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: 0,
- ToKey: node.Data.BodyInterior[0].Key,
- ToMaxKey: node.Data.BodyInterior[0].Key,
+ ToKey: node.BodyInterior[0].Key,
+ ToMaxKey: node.BodyInterior[0].Key,
})
}
}
// return
- if node.Addr != path.Node(-2).ToNodeAddr {
- FreeNodeRef(node)
+ if node.Head.Addr != path.Node(-2).ToNodeAddr {
+ node.Free()
node, err = fs.ReadNode(path.Parent())
if err != nil {
- FreeNodeRef(node)
+ node.Free()
return nil, nil, err
}
}
@@ -419,9 +417,9 @@ func (fs TreeOperatorImpl) TreeSearch(treeID btrfsprim.ObjID, searcher TreeSearc
if err != nil {
return Item{}, fmt.Errorf("item with %s: %w", searcher, err)
}
- item := node.Data.BodyLeaf[path.Node(-1).FromItemSlot]
+ item := node.BodyLeaf[path.Node(-1).FromItemSlot]
item.Body = item.Body.CloneItem()
- FreeNodeRef(node)
+ node.Free()
return item, nil
}
@@ -444,7 +442,7 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, searcher TreeSe
if err != nil {
return nil, fmt.Errorf("items with %s: %w", searcher, err)
}
- middleItem := middleNode.Data.BodyLeaf[middlePath.Node(-1).FromItemSlot]
+ middleItem := middleNode.BodyLeaf[middlePath.Node(-1).FromItemSlot]
ret := []Item{middleItem}
var errs derror.MultiError
@@ -458,7 +456,7 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, searcher TreeSe
if len(prevPath) == 0 {
break
}
- prevItem := prevNode.Data.BodyLeaf[prevPath.Node(-1).FromItemSlot]
+ prevItem := prevNode.BodyLeaf[prevPath.Node(-1).FromItemSlot]
if searcher.Search(prevItem.Key, prevItem.BodySize) != 0 {
break
}
@@ -467,11 +465,11 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, searcher TreeSe
ret = append(ret, item)
}
slices.Reverse(ret)
- if prevNode.Addr != middlePath.Node(-1).ToNodeAddr {
- FreeNodeRef(prevNode)
+ if prevNode.Head.Addr != middlePath.Node(-1).ToNodeAddr {
+ prevNode.Free()
middleNode, err = fs.ReadNode(middlePath)
if err != nil {
- FreeNodeRef(middleNode)
+ middleNode.Free()
return nil, fmt.Errorf("items with %s: %w", searcher, err)
}
}
@@ -485,7 +483,7 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, searcher TreeSe
if len(nextPath) == 0 {
break
}
- nextItem := nextNode.Data.BodyLeaf[nextPath.Node(-1).FromItemSlot]
+ nextItem := nextNode.BodyLeaf[nextPath.Node(-1).FromItemSlot]
if searcher.Search(nextItem.Key, nextItem.BodySize) != 0 {
break
}
@@ -493,7 +491,7 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, searcher TreeSe
item.Body = item.Body.CloneItem()
ret = append(ret, item)
}
- FreeNodeRef(nextNode)
+ nextNode.Free()
if errs != nil {
err = errs
}
diff --git a/lib/btrfs/btrfstree/readnode.go b/lib/btrfs/btrfstree/readnode.go
index 4ccc17b..1c242ac 100644
--- a/lib/btrfs/btrfstree/readnode.go
+++ b/lib/btrfs/btrfstree/readnode.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -34,7 +34,7 @@ type NodeFile interface {
func FSReadNode(
fs NodeFile,
path TreePath,
-) (*diskio.Ref[btrfsvol.LogicalAddr, Node], error) {
+) (*Node, error) {
sb, err := fs.Superblock()
if err != nil {
return nil, fmt.Errorf("btrfs.FS.ReadNode: %w", err)
diff --git a/lib/btrfs/btrfstree/types_node.go b/lib/btrfs/btrfstree/types_node.go
index 8295ccb..2147f5b 100644
--- a/lib/btrfs/btrfstree/types_node.go
+++ b/lib/btrfs/btrfstree/types_node.go
@@ -8,7 +8,6 @@ import (
"encoding/binary"
"errors"
"fmt"
- "unsafe"
"git.lukeshu.com/go/typedsync"
"github.com/datawire/dlib/derror"
@@ -308,12 +307,16 @@ type ItemHeader struct {
var itemPool containers.SlicePool[Item]
func (node *Node) Free() {
+ if node == nil {
+ return
+ }
for i := range node.BodyLeaf {
node.BodyLeaf[i].Body.Free()
node.BodyLeaf[i] = Item{}
}
itemPool.Put(node.BodyLeaf)
*node = Node{}
+ nodePool.Put(node)
}
func (node *Node) unmarshalLeaf(bodyBuf []byte) (int, error) {
@@ -440,32 +443,19 @@ func (e *IOError) Unwrap() error { return e.Err }
var bytePool containers.SlicePool[byte]
-var nodePool = typedsync.Pool[*diskio.Ref[int64, Node]]{
- New: func() *diskio.Ref[int64, Node] {
- return new(diskio.Ref[int64, Node])
+var nodePool = typedsync.Pool[*Node]{
+ New: func() *Node {
+ return new(Node)
},
}
-func FreeNodeRef[Addr ~int64](ref *diskio.Ref[Addr, Node]) {
- if ref == nil {
- return
- }
- ref.Data.Free()
- nodePool.Put((*diskio.Ref[int64, Node])(unsafe.Pointer(ref))) //nolint:gosec // I know it's unsafe.
-}
-
-func newNodeRef[Addr ~int64]() *diskio.Ref[Addr, Node] {
- ret, _ := nodePool.Get()
- return (*diskio.Ref[Addr, Node])(unsafe.Pointer(ret)) //nolint:gosec // I know it's unsafe.
-}
-
// ReadNode reads a node from the given file.
//
// It is possible that both a non-nil diskio.Ref and an error are
// returned. The error returned (if non-nil) is always of type
// *NodeError[Addr]. Notable errors that may be inside of the
// NodeError are ErrNotANode and *IOError.
-func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp NodeExpectations) (*diskio.Ref[Addr, Node], error) {
+func ReadNode[Addr ~int64](fs diskio.ReaderAt[Addr], sb Superblock, addr Addr, exp NodeExpectations) (*Node, error) {
if int(sb.NodeSize) < nodeHeaderSize {
return nil, &NodeError[Addr]{
Op: "btrfstree.ReadNode", NodeAddr: addr,
@@ -481,16 +471,10 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N
// parse (early)
- nodeRef := newNodeRef[Addr]()
- *nodeRef = diskio.Ref[Addr, Node]{
- File: fs,
- Addr: addr,
- Data: Node{
- Size: sb.NodeSize,
- ChecksumType: sb.ChecksumType,
- },
- }
- if _, err := binstruct.Unmarshal(nodeBuf, &nodeRef.Data.Head); err != nil {
+ node, _ := nodePool.Get()
+ node.Size = sb.NodeSize
+ node.ChecksumType = sb.ChecksumType
+ if _, err := binstruct.Unmarshal(nodeBuf, &node.Head); err != nil {
// If there are enough bytes there (and we checked
// that above), then it shouldn't be possible for this
// unmarshal to fail.
@@ -499,20 +483,20 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N
// sanity checking (that prevents the main parse)
- if nodeRef.Data.Head.MetadataUUID != sb.EffectiveMetadataUUID() {
+ if node.Head.MetadataUUID != sb.EffectiveMetadataUUID() {
bytePool.Put(nodeBuf)
- return nodeRef, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: ErrNotANode}
+ return node, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: ErrNotANode}
}
- stored := nodeRef.Data.Head.Checksum
- calced, err := nodeRef.Data.ChecksumType.Sum(nodeBuf[csumSize:])
+ stored := node.Head.Checksum
+ calced, err := node.ChecksumType.Sum(nodeBuf[csumSize:])
if err != nil {
bytePool.Put(nodeBuf)
- return nodeRef, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: err}
+ return node, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: err}
}
if stored != calced {
bytePool.Put(nodeBuf)
- return nodeRef, &NodeError[Addr]{
+ return node, &NodeError[Addr]{
Op: "btrfstree.ReadNode", NodeAddr: addr,
Err: fmt.Errorf("looks like a node but is corrupt: checksum mismatch: stored=%v calculated=%v",
stored, calced),
@@ -530,9 +514,9 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N
// garbage data that is was never a valid node, so parsing it
// isn't useful.
- if _, err := binstruct.Unmarshal(nodeBuf, &nodeRef.Data); err != nil {
+ if _, err := binstruct.Unmarshal(nodeBuf, node); err != nil {
bytePool.Put(nodeBuf)
- return nodeRef, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: err}
+ return node, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: err}
}
bytePool.Put(nodeBuf)
@@ -540,40 +524,40 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N
// sanity checking (that doesn't prevent parsing)
var errs derror.MultiError
- if exp.LAddr.OK && nodeRef.Data.Head.Addr != exp.LAddr.Val {
+ if exp.LAddr.OK && node.Head.Addr != exp.LAddr.Val {
errs = append(errs, fmt.Errorf("read from laddr=%v but claims to be at laddr=%v",
- exp.LAddr.Val, nodeRef.Data.Head.Addr))
+ exp.LAddr.Val, node.Head.Addr))
}
- if exp.Level.OK && nodeRef.Data.Head.Level != exp.Level.Val {
+ if exp.Level.OK && node.Head.Level != exp.Level.Val {
errs = append(errs, fmt.Errorf("expected level=%v but claims to be level=%v",
- exp.Level.Val, nodeRef.Data.Head.Level))
+ exp.Level.Val, node.Head.Level))
}
- if exp.Generation.OK && nodeRef.Data.Head.Generation != exp.Generation.Val {
+ if exp.Generation.OK && node.Head.Generation != exp.Generation.Val {
errs = append(errs, fmt.Errorf("expected generation=%v but claims to be generation=%v",
- exp.Generation.Val, nodeRef.Data.Head.Generation))
+ exp.Generation.Val, node.Head.Generation))
}
if exp.Owner != nil {
- if err := exp.Owner(nodeRef.Data.Head.Owner); err != nil {
+ if err := exp.Owner(node.Head.Owner); err != nil {
errs = append(errs, err)
}
}
- if nodeRef.Data.Head.NumItems == 0 {
+ if node.Head.NumItems == 0 {
errs = append(errs, fmt.Errorf("has no items"))
} else {
- if minItem, _ := nodeRef.Data.MinItem(); exp.MinItem.OK && exp.MinItem.Val.Compare(minItem) > 0 {
+ if minItem, _ := node.MinItem(); exp.MinItem.OK && exp.MinItem.Val.Compare(minItem) > 0 {
errs = append(errs, fmt.Errorf("expected minItem>=%v but node has minItem=%v",
exp.MinItem, minItem))
}
- if maxItem, _ := nodeRef.Data.MaxItem(); exp.MaxItem.OK && exp.MaxItem.Val.Compare(maxItem) < 0 {
+ if maxItem, _ := node.MaxItem(); exp.MaxItem.OK && exp.MaxItem.Val.Compare(maxItem) < 0 {
errs = append(errs, fmt.Errorf("expected maxItem<=%v but node has maxItem=%v",
exp.MaxItem, maxItem))
}
}
if len(errs) > 0 {
- return nodeRef, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: errs}
+ return node, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: errs}
}
// return
- return nodeRef, nil
+ return node, nil
}
diff --git a/lib/btrfs/io3_btree.go b/lib/btrfs/io3_btree.go
index 8d35269..467bbde 100644
--- a/lib/btrfs/io3_btree.go
+++ b/lib/btrfs/io3_btree.go
@@ -10,8 +10,6 @@ import (
"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"
)
// This file is ordered from low-level to high-level.
@@ -19,7 +17,7 @@ import (
// btrfstree.NodeSource ////////////////////////////////////////////////////////
// ReadNode implements btrfstree.NodeSource.
-func (fs *FS) ReadNode(path btrfstree.TreePath) (*diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node], error) {
+func (fs *FS) ReadNode(path btrfstree.TreePath) (*btrfstree.Node, error) {
return btrfstree.FSReadNode(fs, path)
}
diff --git a/lib/btrfs/io4_fs.go b/lib/btrfs/io4_fs.go
index b1a1232..e4511a5 100644
--- a/lib/btrfs/io4_fs.go
+++ b/lib/btrfs/io4_fs.go
@@ -20,6 +20,7 @@ import (
"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"
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
"git.lukeshu.com/btrfs-progs-ng/lib/slices"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
@@ -65,7 +66,7 @@ type Subvolume struct {
FS interface {
btrfstree.TreeOperator
Superblock() (*btrfstree.Superblock, error)
- ReadAt(p []byte, off btrfsvol.LogicalAddr) (int, error)
+ diskio.ReaderAt[btrfsvol.LogicalAddr]
}
TreeID btrfsprim.ObjID
NoChecksums bool
diff --git a/lib/btrfsutil/graph.go b/lib/btrfsutil/graph.go
index 09a17b4..a7c299a 100644
--- a/lib/btrfsutil/graph.go
+++ b/lib/btrfsutil/graph.go
@@ -149,29 +149,29 @@ func NewGraph(sb btrfstree.Superblock) *Graph {
return g
}
-func (g Graph) InsertNode(nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) {
+func (g Graph) InsertNode(node *btrfstree.Node) {
nodeData := GraphNode{
- Level: nodeRef.Data.Head.Level,
- Generation: nodeRef.Data.Head.Generation,
- Owner: nodeRef.Data.Head.Owner,
+ Level: node.Head.Level,
+ Generation: node.Head.Generation,
+ Owner: node.Head.Owner,
}
- if nodeRef.Data.Head.Level == 0 {
+ if node.Head.Level == 0 {
cnt := 0
- for _, item := range nodeRef.Data.BodyLeaf {
+ for _, item := range node.BodyLeaf {
if _, ok := item.Body.(*btrfsitem.Root); ok {
cnt++
}
}
kps := make([]GraphEdge, 0, cnt)
- keys := make([]btrfsprim.Key, len(nodeRef.Data.BodyLeaf))
+ keys := make([]btrfsprim.Key, len(node.BodyLeaf))
nodeData.Items = keys
- g.Nodes[nodeRef.Addr] = nodeData
- for i, item := range nodeRef.Data.BodyLeaf {
+ g.Nodes[node.Head.Addr] = nodeData
+ for i, item := range node.BodyLeaf {
keys[i] = item.Key
if itemBody, ok := item.Body.(*btrfsitem.Root); ok {
kps = append(kps, GraphEdge{
- FromRoot: nodeRef.Addr,
+ FromRoot: node.Head.Addr,
FromItem: i,
FromTree: item.Key.ObjectID,
ToNode: itemBody.ByteNr,
@@ -182,15 +182,15 @@ func (g Graph) InsertNode(nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.No
}
}
} else {
- g.Nodes[nodeRef.Addr] = nodeData
- kps := make([]GraphEdge, len(nodeRef.Data.BodyInterior))
- for i, kp := range nodeRef.Data.BodyInterior {
+ g.Nodes[node.Head.Addr] = nodeData
+ kps := make([]GraphEdge, len(node.BodyInterior))
+ for i, kp := range node.BodyInterior {
kps[i] = GraphEdge{
- FromNode: nodeRef.Addr,
+ FromNode: node.Head.Addr,
FromItem: i,
- FromTree: nodeRef.Data.Head.Owner,
+ FromTree: node.Head.Owner,
ToNode: kp.BlockPtr,
- ToLevel: nodeRef.Data.Head.Level - 1,
+ ToLevel: node.Head.Level - 1,
ToKey: kp.Key,
ToGeneration: kp.Generation,
}
diff --git a/lib/btrfsutil/listnodes.go b/lib/btrfsutil/listnodes.go
index 5505d23..70b647c 100644
--- a/lib/btrfsutil/listnodes.go
+++ b/lib/btrfsutil/listnodes.go
@@ -11,7 +11,6 @@ import (
"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"
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
@@ -44,8 +43,8 @@ func (*nodeScanner) ScanSector(context.Context, *btrfs.Device, btrfsvol.Physical
return nil
}
-func (s *nodeScanner) ScanNode(_ context.Context, nodeRef *diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Node]) error {
- s.nodes.Insert(nodeRef.Data.Head.Addr)
+func (s *nodeScanner) ScanNode(_ context.Context, _ btrfsvol.PhysicalAddr, node *btrfstree.Node) error {
+ s.nodes.Insert(node.Head.Addr)
return nil
}
diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go
index d49f34e..2ec1d83 100644
--- a/lib/btrfsutil/old_rebuilt_forrest.go
+++ b/lib/btrfsutil/old_rebuilt_forrest.go
@@ -17,7 +17,6 @@ import (
"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"
)
type oldRebuiltTree struct {
@@ -226,12 +225,12 @@ func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstr
itemPath := bt.arena.Inflate(indexItem.Value.Path)
node, err := bt.inner.ReadNode(itemPath.Parent())
- defer btrfstree.FreeNodeRef(node)
+ defer node.Free()
if err != nil {
return btrfstree.Item{}, fmt.Errorf("item with %s: %w", searcher, bt.addErrs(tree, searcher.Search, err))
}
- item := node.Data.BodyLeaf[itemPath.Node(-1).FromItemSlot]
+ item := node.BodyLeaf[itemPath.Node(-1).FromItemSlot]
item.Body = item.Body.CloneItem()
// Since we were only asked to return 1 item, it isn't
@@ -259,22 +258,22 @@ func (bt *OldRebuiltForrest) TreeSearchAll(treeID btrfsprim.ObjID, searcher btrf
}
ret := make([]btrfstree.Item, len(indexItems))
- var node *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]
+ var node *btrfstree.Node
for i := range indexItems {
itemPath := bt.arena.Inflate(indexItems[i].Path)
- if node == nil || node.Addr != itemPath.Node(-2).ToNodeAddr {
+ if node == nil || node.Head.Addr != itemPath.Node(-2).ToNodeAddr {
var err error
- btrfstree.FreeNodeRef(node)
+ node.Free()
node, err = bt.inner.ReadNode(itemPath.Parent())
if err != nil {
- btrfstree.FreeNodeRef(node)
+ node.Free()
return nil, fmt.Errorf("items with %s: %w", searcher, bt.addErrs(tree, searcher.Search, err))
}
}
- ret[i] = node.Data.BodyLeaf[itemPath.Node(-1).FromItemSlot]
+ ret[i] = node.BodyLeaf[itemPath.Node(-1).FromItemSlot]
ret[i].Body = ret[i].Body.CloneItem()
}
- btrfstree.FreeNodeRef(node)
+ node.Free()
err := bt.addErrs(tree, searcher.Search, nil)
if err != nil {
@@ -298,7 +297,7 @@ func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjI
if cbs.Item == nil {
return
}
- var node *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]
+ var node *btrfstree.Node
tree.Items.Range(func(indexItem *containers.RBNode[oldRebuiltTreeValue]) bool {
if ctx.Err() != nil {
return false
@@ -307,23 +306,23 @@ func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjI
return false
}
itemPath := bt.arena.Inflate(indexItem.Value.Path)
- if node == nil || node.Addr != itemPath.Node(-2).ToNodeAddr {
+ if node == nil || node.Head.Addr != itemPath.Node(-2).ToNodeAddr {
var err error
- btrfstree.FreeNodeRef(node)
+ node.Free()
node, err = bt.inner.ReadNode(itemPath.Parent())
if err != nil {
- btrfstree.FreeNodeRef(node)
+ node.Free()
errHandle(&btrfstree.TreeError{Path: itemPath, Err: err})
return true
}
}
- item := node.Data.BodyLeaf[itemPath.Node(-1).FromItemSlot]
+ item := node.BodyLeaf[itemPath.Node(-1).FromItemSlot]
if err := cbs.Item(itemPath, item); err != nil {
errHandle(&btrfstree.TreeError{Path: itemPath, Err: err})
}
return true
})
- btrfstree.FreeNodeRef(node)
+ node.Free()
}
func (bt *OldRebuiltForrest) Superblock() (*btrfstree.Superblock, error) {
@@ -343,8 +342,8 @@ func (bt *OldRebuiltForrest) Augment(treeID btrfsprim.ObjID, nodeAddr btrfsvol.L
if tree.RootErr != nil {
return nil, tree.RootErr
}
- nodeRef, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](bt.inner, *sb, nodeAddr, btrfstree.NodeExpectations{})
- defer btrfstree.FreeNodeRef(nodeRef)
+ node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](bt.inner, *sb, nodeAddr, btrfstree.NodeExpectations{})
+ defer node.Free()
if err != nil {
return nil, err
}
@@ -352,8 +351,8 @@ func (bt *OldRebuiltForrest) Augment(treeID btrfsprim.ObjID, nodeAddr btrfsvol.L
bt.rawTreeWalk(btrfstree.TreeRoot{
TreeID: treeID,
RootNode: nodeAddr,
- Level: nodeRef.Data.Head.Level,
- Generation: nodeRef.Data.Head.Generation,
+ Level: node.Head.Level,
+ Generation: node.Head.Generation,
}, tree, &ret)
return ret, nil
}
diff --git a/lib/btrfsutil/rebuilt_readitem.go b/lib/btrfsutil/rebuilt_readitem.go
index 016299c..b1a0656 100644
--- a/lib/btrfsutil/rebuilt_readitem.go
+++ b/lib/btrfsutil/rebuilt_readitem.go
@@ -49,7 +49,7 @@ type KeyIO struct {
Sizes map[ItemPtr]SizeAndErr // EXTENT_CSUM and EXTENT_DATA
mu sync.Mutex
- cache containers.ARCache[btrfsvol.LogicalAddr, *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]]
+ cache containers.ARCache[btrfsvol.LogicalAddr, *btrfstree.Node]
}
func NewKeyIO(file diskio.File[btrfsvol.LogicalAddr], sb btrfstree.Superblock) *KeyIO {
@@ -61,19 +61,19 @@ func NewKeyIO(file diskio.File[btrfsvol.LogicalAddr], sb btrfstree.Superblock) *
Names: make(map[ItemPtr][]byte),
Sizes: make(map[ItemPtr]SizeAndErr),
- cache: containers.ARCache[btrfsvol.LogicalAddr, *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]]{
+ cache: containers.ARCache[btrfsvol.LogicalAddr, *btrfstree.Node]{
MaxLen: textui.Tunable(8),
- OnRemove: func(_ btrfsvol.LogicalAddr, nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) {
- btrfstree.FreeNodeRef(nodeRef)
+ OnRemove: func(_ btrfsvol.LogicalAddr, node *btrfstree.Node) {
+ node.Free()
},
},
}
}
-func (o *KeyIO) InsertNode(nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) {
- for i, item := range nodeRef.Data.BodyLeaf {
+func (o *KeyIO) InsertNode(node *btrfstree.Node) {
+ for i, item := range node.BodyLeaf {
ptr := ItemPtr{
- Node: nodeRef.Addr,
+ Node: node.Head.Addr,
Slot: i,
}
switch itemBody := item.Body.(type) {
@@ -102,12 +102,12 @@ func (o *KeyIO) InsertNode(nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.N
case btrfsprim.INODE_ITEM_KEY:
o.Flags[ptr] = FlagsAndErr{
Err: fmt.Errorf("error decoding item: ptr=%v (tree=%v key=%v): %w",
- ptr, nodeRef.Data.Head.Owner, item.Key, itemBody.Err),
+ ptr, node.Head.Owner, item.Key, itemBody.Err),
}
case btrfsprim.EXTENT_CSUM_KEY, btrfsprim.EXTENT_DATA_KEY:
o.Sizes[ptr] = SizeAndErr{
Err: fmt.Errorf("error decoding item: ptr=%v (tree=%v key=%v): %w",
- ptr, nodeRef.Data.Head.Owner, item.Key, itemBody.Err),
+ ptr, node.Head.Owner, item.Key, itemBody.Err),
}
}
}
@@ -118,7 +118,7 @@ func (o *KeyIO) SetGraph(graph Graph) {
o.graph = graph
}
-func (o *KeyIO) readNode(ctx context.Context, laddr btrfsvol.LogicalAddr) *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node] {
+func (o *KeyIO) readNode(ctx context.Context, laddr btrfsvol.LogicalAddr) *btrfstree.Node {
if cached, ok := o.cache.Load(laddr); ok {
dlog.Tracef(ctx, "cache-hit node@%v", laddr)
return cached
@@ -130,7 +130,7 @@ func (o *KeyIO) readNode(ctx context.Context, laddr btrfsvol.LogicalAddr) *diski
}
dlog.Debugf(ctx, "cache-miss node@%v, reading...", laddr)
- ref, err := btrfstree.ReadNode(o.rawFile, o.sb, laddr, btrfstree.NodeExpectations{
+ node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](o.rawFile, o.sb, laddr, btrfstree.NodeExpectations{
LAddr: containers.Optional[btrfsvol.LogicalAddr]{OK: true, Val: laddr},
Level: containers.Optional[uint8]{OK: true, Val: graphInfo.Level},
Generation: containers.Optional[btrfsprim.Generation]{OK: true, Val: graphInfo.Generation},
@@ -148,9 +148,9 @@ func (o *KeyIO) readNode(ctx context.Context, laddr btrfsvol.LogicalAddr) *diski
panic(fmt.Errorf("should not happen: i/o error: %w", err))
}
- o.cache.Store(laddr, ref)
+ o.cache.Store(laddr, node)
- return ref
+ return node
}
func (o *KeyIO) ReadItem(ctx context.Context, ptr ItemPtr) btrfsitem.Item {
@@ -162,7 +162,7 @@ func (o *KeyIO) ReadItem(ctx context.Context, ptr ItemPtr) btrfsitem.Item {
if ptr.Slot < 0 {
panic(fmt.Errorf("should not happen: btrfsutil.KeyIO.ReadItem called for negative item slot: %v", ptr.Slot))
}
- items := o.readNode(ctx, ptr.Node).Data.BodyLeaf
+ items := o.readNode(ctx, ptr.Node).BodyLeaf
if ptr.Slot >= len(items) {
panic(fmt.Errorf("should not happen: btrfsutil.KeyIO.ReadItem called for out-of-bounds item slot: slot=%v len=%v",
ptr.Slot, len(items)))
diff --git a/lib/btrfsutil/scan.go b/lib/btrfsutil/scan.go
index 97220aa..05b27d5 100644
--- a/lib/btrfsutil/scan.go
+++ b/lib/btrfsutil/scan.go
@@ -19,7 +19,6 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum"
"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"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
@@ -30,7 +29,7 @@ type DeviceScannerFactory[Stats comparable, Result any] func(ctx context.Context
type DeviceScanner[Stats comparable, Result any] interface {
ScanStats() Stats
ScanSector(ctx context.Context, dev *btrfs.Device, paddr btrfsvol.PhysicalAddr) error
- ScanNode(ctx context.Context, nodeRef *diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Node]) error
+ ScanNode(ctx context.Context, addr btrfsvol.PhysicalAddr, node *btrfstree.Node) error
ScanDone(ctx context.Context) (Result, error)
}
@@ -123,19 +122,19 @@ func ScanOneDevice[Stats comparable, Result any](ctx context.Context, dev *btrfs
}
if checkForNode {
- nodeRef, err := btrfstree.ReadNode[btrfsvol.PhysicalAddr](dev, *sb, pos, btrfstree.NodeExpectations{})
+ node, err := btrfstree.ReadNode[btrfsvol.PhysicalAddr](dev, *sb, pos, btrfstree.NodeExpectations{})
if err != nil {
if !errors.Is(err, btrfstree.ErrNotANode) {
dlog.Errorf(ctx, "error: %v", err)
}
} else {
- if err := scanner.ScanNode(ctx, nodeRef); err != nil {
+ if err := scanner.ScanNode(ctx, pos, node); err != nil {
var zero Result
return zero, err
}
minNextNode = pos + btrfsvol.PhysicalAddr(sb.NodeSize)
}
- btrfstree.FreeNodeRef(nodeRef)
+ node.Free()
}
}
diff --git a/lib/btrfsutil/skinny_paths.go b/lib/btrfsutil/skinny_paths.go
index adf539b..1361fff 100644
--- a/lib/btrfsutil/skinny_paths.go
+++ b/lib/btrfsutil/skinny_paths.go
@@ -54,26 +54,26 @@ func (a *SkinnyPathArena) getItem(parent btrfstree.TreePath, itemSlot int) (btrf
return ret, nil
}
- node, err := btrfstree.ReadNode(a.FS, a.SB, parent.Node(-1).ToNodeAddr, btrfstree.NodeExpectations{})
- defer btrfstree.FreeNodeRef(node)
+ node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](a.FS, a.SB, parent.Node(-1).ToNodeAddr, btrfstree.NodeExpectations{})
+ defer node.Free()
if err != nil {
return btrfstree.TreePathElem{}, err
}
- if node.Data.Head.Level > 0 {
- if itemSlot >= len(node.Data.BodyInterior) {
+ if node.Head.Level > 0 {
+ if itemSlot >= len(node.BodyInterior) {
panic("should not happen")
}
- for i, item := range node.Data.BodyInterior {
+ for i, item := range node.BodyInterior {
toMaxKey := parent.Node(-1).ToMaxKey
- if i+1 < len(node.Data.BodyInterior) {
- toMaxKey = node.Data.BodyInterior[i+1].Key.Mm()
+ if i+1 < len(node.BodyInterior) {
+ toMaxKey = node.BodyInterior[i+1].Key.Mm()
}
elem := btrfstree.TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: i,
ToNodeAddr: item.BlockPtr,
ToNodeGeneration: item.Generation,
- ToNodeLevel: node.Data.Head.Level - 1,
+ ToNodeLevel: node.Head.Level - 1,
ToKey: item.Key,
ToMaxKey: toMaxKey,
}
@@ -83,12 +83,12 @@ func (a *SkinnyPathArena) getItem(parent btrfstree.TreePath, itemSlot int) (btrf
}
}
} else {
- if itemSlot >= len(node.Data.BodyLeaf) {
+ if itemSlot >= len(node.BodyLeaf) {
panic("should not happen")
}
- for i, item := range node.Data.BodyLeaf {
+ for i, item := range node.BodyLeaf {
elem := btrfstree.TreePathElem{
- FromTree: node.Data.Head.Owner,
+ FromTree: node.Head.Owner,
FromItemSlot: i,
ToKey: item.Key,
ToMaxKey: item.Key,
diff --git a/lib/diskio/file_iface.go b/lib/diskio/file_iface.go
index d26ffcc..a30ddb0 100644
--- a/lib/diskio/file_iface.go
+++ b/lib/diskio/file_iface.go
@@ -9,11 +9,15 @@ import (
"io"
)
+type ReaderAt[A ~int64] interface {
+ ReadAt(p []byte, off A) (n int, err error)
+}
+
type File[A ~int64] interface {
Name() string
Size() A
- Close() error
- ReadAt(p []byte, off A) (n int, err error)
+ io.Closer
+ ReaderAt[A]
WriteAt(p []byte, off A) (n int, err error)
}