summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-03-29 17:11:27 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2023-03-30 00:11:57 -0600
commit7f1391d48d63a5f8780dddc41817eaa9df3ce880 (patch)
tree976590735a86c09059e3eb22cf65e0d851d4ce08
parent755ac780df4f653879cb376d27cad7ff8e8d7b0f (diff)
tree-wide: Funnel all btrfstree.ReadNode[btrfsvol.LogicalAddr]() calls through btrfstree.NodeSource.ReadNode()
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/scan.go4
-rw-r--r--cmd/btrfs-rec/inspect_lstrees.go3
-rw-r--r--lib/btrfs/btrfstree/btree.go3
-rw-r--r--lib/btrfs/btrfstree/btree_forrest.go5
-rw-r--r--lib/btrfs/btrfstree/btree_tree.go12
-rw-r--r--lib/btrfs/btrfstree/readnode.go24
-rw-r--r--lib/btrfs/io3_btree.go10
-rw-r--r--lib/btrfsutil/graph.go5
-rw-r--r--lib/btrfsutil/old_rebuilt_forrest.go7
-rw-r--r--lib/btrfsutil/rebuilt_forrest.go5
-rw-r--r--lib/btrfsutil/rebuilt_readitem.go2
11 files changed, 42 insertions, 38 deletions
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/scan.go b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
index 3339270..86d3741 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go
@@ -71,7 +71,7 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, nodeList []btrfsvol.LogicalA
if err := ctx.Err(); err != nil {
return ScanDevicesResult{}, err
}
- node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, laddr, btrfstree.NodeExpectations{
+ node, err := fs.ReadNode(ctx, laddr, btrfstree.NodeExpectations{
LAddr: containers.OptionalValue(laddr),
})
if err != nil {
@@ -93,7 +93,7 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, nodeList []btrfsvol.LogicalA
dlog.Info(ctx, "... done reading node data")
ctx = dlog.WithField(ctx, "btrfs.inspect.rebuild-trees.read.substep", "check")
- if err := ret.Graph.FinalCheck(ctx, fs, *sb); err != nil {
+ if err := ret.Graph.FinalCheck(ctx, fs); err != nil {
return ScanDevicesResult{}, err
}
diff --git a/cmd/btrfs-rec/inspect_lstrees.go b/cmd/btrfs-rec/inspect_lstrees.go
index 1449a21..9639a2e 100644
--- a/cmd/btrfs-rec/inspect_lstrees.go
+++ b/cmd/btrfs-rec/inspect_lstrees.go
@@ -101,13 +101,12 @@ func init() {
treeErrCnt = 0
treeItemCnt = make(map[btrfsitem.Type]int)
textui.Fprintf(os.Stdout, "lost+found\n")
- sb, _ := fs.Superblock()
for _, laddr := range nodeList {
if visitedNodes.Has(laddr) {
continue
}
visitedNodes.Insert(laddr)
- node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, laddr, btrfstree.NodeExpectations{
+ node, err := fs.ReadNode(ctx, laddr, btrfstree.NodeExpectations{
LAddr: containers.OptionalValue(laddr),
})
if err != nil {
diff --git a/lib/btrfs/btrfstree/btree.go b/lib/btrfs/btrfstree/btree.go
index bc1bac2..dde485a 100644
--- a/lib/btrfs/btrfstree/btree.go
+++ b/lib/btrfs/btrfstree/btree.go
@@ -11,6 +11,7 @@ import (
"fmt"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
)
type TreeSearcher interface {
@@ -96,5 +97,5 @@ func (e *TreeError) Error() string {
type NodeSource interface {
Superblock() (*Superblock, error)
- ReadNode(Path) (*Node, error)
+ ReadNode(ctx context.Context, addr btrfsvol.LogicalAddr, exp NodeExpectations) (*Node, error)
}
diff --git a/lib/btrfs/btrfstree/btree_forrest.go b/lib/btrfs/btrfstree/btree_forrest.go
index b017888..b04bfc0 100644
--- a/lib/btrfs/btrfstree/btree_forrest.go
+++ b/lib/btrfs/btrfstree/btree_forrest.go
@@ -83,7 +83,10 @@ func LookupTreeRoot(_ context.Context, fs TreeOperator, sb Superblock, treeID bt
}
type TreeOperatorImpl struct {
- NodeSource NodeSource
+ NodeSource interface {
+ NodeSource
+ NodeFile
+ }
}
func (fs TreeOperatorImpl) RawTree(ctx context.Context, treeID btrfsprim.ObjID) (*RawTree, error) {
diff --git a/lib/btrfs/btrfstree/btree_tree.go b/lib/btrfs/btrfstree/btree_tree.go
index 89b4c52..a6311f9 100644
--- a/lib/btrfs/btrfstree/btree_tree.go
+++ b/lib/btrfs/btrfstree/btree_tree.go
@@ -22,6 +22,9 @@ type RawTree struct {
}
func (tree *RawTree) TreeWalk(ctx context.Context, cbs TreeWalkHandler) {
+ if tree.RootNode == 0 {
+ return
+ }
path := Path{{
FromTree: tree.ID,
FromItemSlot: -1,
@@ -37,12 +40,13 @@ func (tree *RawTree) walk(ctx context.Context, path Path, cbs TreeWalkHandler) {
if ctx.Err() != nil {
return
}
- if path.Node(-1).ToNodeAddr == 0 {
- return
- }
// 001
- node, err := tree.Forrest.NodeSource.ReadNode(path)
+ nodeAddr, nodeExp, ok := path.NodeExpectations(tree.Forrest.NodeSource)
+ if !ok {
+ return
+ }
+ node, err := tree.Forrest.NodeSource.ReadNode(ctx, nodeAddr, nodeExp)
defer node.Free()
if ctx.Err() != nil {
return
diff --git a/lib/btrfs/btrfstree/readnode.go b/lib/btrfs/btrfstree/readnode.go
index ac82c62..a4ccf10 100644
--- a/lib/btrfs/btrfstree/readnode.go
+++ b/lib/btrfs/btrfstree/readnode.go
@@ -14,8 +14,7 @@ import (
)
type NodeFile interface {
- diskio.File[btrfsvol.LogicalAddr]
- Superblock() (*Superblock, error)
+ diskio.ReaderAt[btrfsvol.LogicalAddr]
// ParentTree, given a tree ID, returns that tree's parent
// tree, if it has one.
@@ -29,15 +28,14 @@ type NodeFile interface {
ParentTree(btrfsprim.ObjID) (btrfsprim.ObjID, btrfsprim.Generation, bool)
}
-// FSReadNode is a utility function to help with implementing the
-// 'NodeSource' interface.
-func FSReadNode(
- fs NodeFile,
- path Path,
-) (*Node, error) {
- sb, err := fs.Superblock()
- if err != nil {
- return nil, fmt.Errorf("btrfs.FS.ReadNode: %w", err)
+// NodeExpectations returns the address to read and the expectations
+// to have when reading the node pointed to by this Path.
+//
+// `ok` is false if the path is empty or if this Path points to an
+// item rather than a node.
+func (path Path) NodeExpectations(fs NodeFile) (_ btrfsvol.LogicalAddr, _ NodeExpectations, ok bool) {
+ if path.Node(-1).ToNodeAddr == 0 && path.Node(-1).ToNodeGeneration == 0 && path.Node(-1).ToNodeLevel == 0 {
+ return 0, NodeExpectations{}, false
}
checkOwner := func(owner btrfsprim.ObjID, gen btrfsprim.Generation) error {
@@ -70,12 +68,12 @@ func FSReadNode(
}
}
- return ReadNode[btrfsvol.LogicalAddr](fs, *sb, path.Node(-1).ToNodeAddr, NodeExpectations{
+ return path.Node(-1).ToNodeAddr, NodeExpectations{
LAddr: containers.OptionalValue(path.Node(-1).ToNodeAddr),
Level: containers.OptionalValue(path.Node(-1).ToNodeLevel),
Generation: containers.OptionalValue(path.Node(-1).ToNodeGeneration),
Owner: checkOwner,
MinItem: containers.OptionalValue(path.Node(-1).ToKey),
MaxItem: containers.OptionalValue(path.Node(-1).ToMaxKey),
- })
+ }, true
}
diff --git a/lib/btrfs/io3_btree.go b/lib/btrfs/io3_btree.go
index f1436fb..bb68d7d 100644
--- a/lib/btrfs/io3_btree.go
+++ b/lib/btrfs/io3_btree.go
@@ -6,10 +6,12 @@ package btrfs
import (
"context"
+ "fmt"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
)
// This file is ordered from low-level to high-level.
@@ -79,8 +81,12 @@ var _ btrfstree.NodeFile = (*FS)(nil)
// btrfstree.NodeSource ////////////////////////////////////////////////////////
// ReadNode implements btrfstree.NodeSource.
-func (fs *FS) ReadNode(path btrfstree.Path) (*btrfstree.Node, error) {
- return btrfstree.FSReadNode(fs, path)
+func (fs *FS) ReadNode(_ context.Context, addr btrfsvol.LogicalAddr, exp btrfstree.NodeExpectations) (*btrfstree.Node, error) {
+ sb, err := fs.Superblock()
+ if err != nil {
+ return nil, fmt.Errorf("btrfs.FS.ReadNode: %w", err)
+ }
+ return btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, *sb, addr, exp)
}
var _ btrfstree.NodeSource = (*FS)(nil)
diff --git a/lib/btrfsutil/graph.go b/lib/btrfsutil/graph.go
index 39e1cf2..4148f89 100644
--- a/lib/btrfsutil/graph.go
+++ b/lib/btrfsutil/graph.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"
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
"git.lukeshu.com/btrfs-progs-ng/lib/slices"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
@@ -199,7 +198,7 @@ func (g Graph) InsertNode(node *btrfstree.Node) {
}
}
-func (g Graph) FinalCheck(ctx context.Context, fs diskio.File[btrfsvol.LogicalAddr], sb btrfstree.Superblock) error {
+func (g Graph) FinalCheck(ctx context.Context, fs btrfstree.NodeSource) error {
var stats textui.Portion[int]
dlog.Info(ctx, "Checking keypointers for dead-ends...")
@@ -208,7 +207,7 @@ func (g Graph) FinalCheck(ctx context.Context, fs diskio.File[btrfsvol.LogicalAd
progressWriter.Set(stats)
for laddr := range g.EdgesTo {
if _, ok := g.Nodes[laddr]; !ok {
- _, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](fs, sb, laddr, btrfstree.NodeExpectations{
+ _, err := fs.ReadNode(ctx, laddr, btrfstree.NodeExpectations{
LAddr: containers.OptionalValue(laddr),
})
if err == nil {
diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go
index 5b99892..24faf79 100644
--- a/lib/btrfsutil/old_rebuilt_forrest.go
+++ b/lib/btrfsutil/old_rebuilt_forrest.go
@@ -231,12 +231,7 @@ func (tree oldRebuiltTree) addErrs(fn func(btrfsprim.Key, uint32) int, err error
}
func (bt *OldRebuiltForrest) readNode(nodeInfo nodeInfo) *btrfstree.Node {
- sb, err := bt.inner.Superblock()
- if err != nil {
- panic(fmt.Errorf("should not happen: i/o error: %w", err))
- }
-
- node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](bt.inner, *sb, nodeInfo.LAddr, btrfstree.NodeExpectations{
+ node, err := bt.inner.ReadNode(bt.ctx, nodeInfo.LAddr, btrfstree.NodeExpectations{
LAddr: containers.OptionalValue(nodeInfo.LAddr),
Level: containers.OptionalValue(nodeInfo.Level),
Generation: containers.OptionalValue(nodeInfo.Generation),
diff --git a/lib/btrfsutil/rebuilt_forrest.go b/lib/btrfsutil/rebuilt_forrest.go
index 811e1ac..4f7a24b 100644
--- a/lib/btrfsutil/rebuilt_forrest.go
+++ b/lib/btrfsutil/rebuilt_forrest.go
@@ -15,7 +15,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/slices"
"git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
@@ -130,7 +129,7 @@ func (cb noopRebuiltForrestCallbacks) LookupUUID(ctx context.Context, uuid btrfs
// NewRebuiltForrest().
type RebuiltForrest struct {
// static
- file diskio.File[btrfsvol.LogicalAddr]
+ file btrfstree.NodeSource
sb btrfstree.Superblock
graph Graph
cb RebuiltForrestCallbacks
@@ -148,7 +147,7 @@ type RebuiltForrest struct {
// NewRebuiltForrest returns a new RebuiltForrest instance. The
// RebuiltForrestCallbacks may be nil.
-func NewRebuiltForrest(file diskio.File[btrfsvol.LogicalAddr], sb btrfstree.Superblock, graph Graph, cb RebuiltForrestCallbacks) *RebuiltForrest {
+func NewRebuiltForrest(file btrfstree.NodeSource, sb btrfstree.Superblock, graph Graph, cb RebuiltForrestCallbacks) *RebuiltForrest {
ret := &RebuiltForrest{
file: file,
sb: sb,
diff --git a/lib/btrfsutil/rebuilt_readitem.go b/lib/btrfsutil/rebuilt_readitem.go
index d3a2253..2520593 100644
--- a/lib/btrfsutil/rebuilt_readitem.go
+++ b/lib/btrfsutil/rebuilt_readitem.go
@@ -34,7 +34,7 @@ func (ts *RebuiltForrest) readNode(ctx context.Context, laddr btrfsvol.LogicalAd
panic(fmt.Errorf("should not happen: node@%v is not mentioned in the in-memory graph", laddr))
}
- node, err := btrfstree.ReadNode[btrfsvol.LogicalAddr](ts.file, ts.sb, laddr, btrfstree.NodeExpectations{
+ node, err := ts.file.ReadNode(ctx, laddr, btrfstree.NodeExpectations{
LAddr: containers.OptionalValue(laddr),
Level: containers.OptionalValue(graphInfo.Level),
Generation: containers.OptionalValue(graphInfo.Generation),