From 0d6880131e90b43e03e0878dfc2ea2b6f0f2291e Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 13 Mar 2023 18:49:47 -0600 Subject: btrfstree: Have LookupTreeRoot take a Context --- lib/btrfsutil/graph.go | 14 +++++++------- lib/btrfsutil/old_rebuilt_forrest.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/graph.go b/lib/btrfsutil/graph.go index 35848de..39e1cf2 100644 --- a/lib/btrfsutil/graph.go +++ b/lib/btrfsutil/graph.go @@ -111,8 +111,8 @@ func (g Graph) insertEdge(ptr *GraphEdge) { g.EdgesTo[ptr.ToNode] = append(g.EdgesTo[ptr.ToNode], ptr) } -func (g Graph) insertTreeRoot(sb btrfstree.Superblock, treeID btrfsprim.ObjID) { - treeInfo, err := btrfstree.LookupTreeRoot(nil, sb, treeID) +func (g Graph) insertTreeRoot(ctx context.Context, sb btrfstree.Superblock, treeID btrfsprim.ObjID) { + treeInfo, err := btrfstree.LookupTreeRoot(ctx, nil, sb, treeID) if err != nil { // This shouldn't ever happen for treeIDs that are // mentioned directly in the superblock; which are the @@ -131,7 +131,7 @@ func (g Graph) insertTreeRoot(sb btrfstree.Superblock, treeID btrfsprim.ObjID) { }) } -func NewGraph(sb btrfstree.Superblock) Graph { +func NewGraph(ctx context.Context, sb btrfstree.Superblock) Graph { g := Graph{ Nodes: make(map[btrfsvol.LogicalAddr]GraphNode), BadNodes: make(map[btrfsvol.LogicalAddr]error), @@ -141,10 +141,10 @@ func NewGraph(sb btrfstree.Superblock) Graph { // These 4 trees are mentioned directly in the superblock, so // they are always seen. - g.insertTreeRoot(sb, btrfsprim.ROOT_TREE_OBJECTID) - g.insertTreeRoot(sb, btrfsprim.CHUNK_TREE_OBJECTID) - g.insertTreeRoot(sb, btrfsprim.TREE_LOG_OBJECTID) - g.insertTreeRoot(sb, btrfsprim.BLOCK_GROUP_TREE_OBJECTID) + g.insertTreeRoot(ctx, sb, btrfsprim.ROOT_TREE_OBJECTID) + g.insertTreeRoot(ctx, sb, btrfsprim.CHUNK_TREE_OBJECTID) + g.insertTreeRoot(ctx, sb, btrfsprim.TREE_LOG_OBJECTID) + g.insertTreeRoot(ctx, sb, btrfsprim.BLOCK_GROUP_TREE_OBJECTID) return g } diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index abe3329..8ae7149 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -153,7 +153,7 @@ func (bt *OldRebuiltForrest) rawTreeWalk(treeID btrfsprim.ObjID, cacheEntry *old cacheEntry.RootErr = err return } - root, err := btrfstree.LookupTreeRoot(bt, *sb, treeID) + root, err := btrfstree.LookupTreeRoot(bt.ctx, bt, *sb, treeID) if err != nil { cacheEntry.RootErr = err return -- cgit v1.2.3-2-g168b From c4597bbacc76eb5ddea4d3a2a062353895c90fbe Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 13 Mar 2023 23:58:04 -0600 Subject: btrfstree: TreeRoot: Rename the member from TreeID to just ID --- lib/btrfsutil/old_rebuilt_forrest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index 8ae7149..ace79e9 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -203,7 +203,7 @@ func (bt *OldRebuiltForrest) rawTreeWalk(treeID btrfsprim.ObjID, cacheEntry *old // This is a panic because I'm not really sure what the best way to // handle this is, and so if this happens I want the program to crash // and force me to figure out how to handle it. - panic(fmt.Errorf("dup key=%v in tree=%v", item.Key, root.TreeID)) + panic(fmt.Errorf("dup key=%v in tree=%v", item.Key, treeID)) } cacheEntry.Items.Insert(oldRebuiltTreeValue{ Key: item.Key, -- cgit v1.2.3-2-g168b From 8d3cd03a0339f045ea58878eff6a2c0ced27955e Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 18 Mar 2023 15:18:29 -0400 Subject: btrfsutil: OldRebuiltForrest: Simplify the TreeSearchAll implementation --- lib/btrfsutil/old_rebuilt_forrest.go | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index ace79e9..0887bf9 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -297,35 +297,33 @@ func (bt *OldRebuiltForrest) TreeSearchAll(treeID btrfsprim.ObjID, searcher btrf return nil, tree.RootErr } - var indexItems []oldRebuiltTreeValue + var ret []btrfstree.Item + var node *btrfstree.Node tree.Items.Subrange( func(indexItem oldRebuiltTreeValue) int { return searcher.Search(indexItem.Key, indexItem.ItemSize) }, - func(node *containers.RBNode[oldRebuiltTreeValue]) bool { - indexItems = append(indexItems, node.Value) + func(rbNode *containers.RBNode[oldRebuiltTreeValue]) bool { + if node == nil || node.Head.Addr != rbNode.Value.Node.LAddr { + node.Free() + node = bt.readNode(rbNode.Value.Node) + } + item := node.BodyLeaf[rbNode.Value.Slot] + item.Body = item.Body.CloneItem() + ret = append(ret, item) return true }) - if len(indexItems) == 0 { - return nil, fmt.Errorf("items with %s: %w", searcher, tree.addErrs(searcher.Search, btrfstree.ErrNoItem)) - } - - ret := make([]btrfstree.Item, len(indexItems)) - var node *btrfstree.Node - for i, indexItem := range indexItems { - if node == nil || node.Head.Addr != indexItem.Node.LAddr { - node.Free() - node = bt.readNode(indexItem.Node) - } - ret[i] = node.BodyLeaf[indexItem.Slot] - ret[i].Body = ret[i].Body.CloneItem() - } node.Free() - err := tree.addErrs(searcher.Search, nil) + var err error + if len(ret) == 0 { + err = btrfstree.ErrNoItem + } + err = tree.addErrs(searcher.Search, err) if err != nil { err = fmt.Errorf("items with %s: %w", searcher, err) } + return ret, err } -- cgit v1.2.3-2-g168b From c2d3878332b3e8853257b6ee5712a5a995987387 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 2 Mar 2023 23:33:49 -0700 Subject: btrfsutil: OldRebuiltForrest: Have .RebuiltTree take a Context --- lib/btrfsutil/old_rebuilt_forrest.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index 0887bf9..0d6adc6 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -114,7 +114,7 @@ func NewOldRebuiltForrest(ctx context.Context, inner *btrfs.FS) *OldRebuiltForre } } -func (bt *OldRebuiltForrest) RebuiltTree(treeID btrfsprim.ObjID) oldRebuiltTree { +func (bt *OldRebuiltForrest) RebuiltTree(ctx context.Context, treeID btrfsprim.ObjID) oldRebuiltTree { if treeID == btrfsprim.ROOT_TREE_OBJECTID { bt.rootTreeMu.Lock() defer bt.rootTreeMu.Unlock() @@ -133,9 +133,9 @@ func (bt *OldRebuiltForrest) RebuiltTree(treeID btrfsprim.ObjID) oldRebuiltTree } cacheEntry := newOldRebuiltTree() - dlog.Infof(bt.ctx, "indexing tree %v...", treeID) - bt.rawTreeWalk(treeID, &cacheEntry) - dlog.Infof(bt.ctx, "... done indexing tree %v", treeID) + dlog.Infof(ctx, "indexing tree %v...", treeID) + bt.rawTreeWalk(ctx, treeID, &cacheEntry) + dlog.Infof(ctx, "... done indexing tree %v", treeID) if treeID == btrfsprim.ROOT_TREE_OBJECTID { bt.rootTree = &cacheEntry @@ -147,13 +147,13 @@ func (bt *OldRebuiltForrest) RebuiltTree(treeID btrfsprim.ObjID) oldRebuiltTree func discardOK[T any](x T, _ bool) T { return x } -func (bt *OldRebuiltForrest) rawTreeWalk(treeID btrfsprim.ObjID, cacheEntry *oldRebuiltTree) { +func (bt *OldRebuiltForrest) rawTreeWalk(ctx context.Context, treeID btrfsprim.ObjID, cacheEntry *oldRebuiltTree) { sb, err := bt.inner.Superblock() if err != nil { cacheEntry.RootErr = err return } - root, err := btrfstree.LookupTreeRoot(bt.ctx, bt, *sb, treeID) + root, err := btrfstree.LookupTreeRoot(ctx, bt, *sb, treeID) if err != nil { cacheEntry.RootErr = err return @@ -216,7 +216,7 @@ func (bt *OldRebuiltForrest) rawTreeWalk(treeID btrfsprim.ObjID, cacheEntry *old }, } - btrfstree.TreeOperatorImpl{NodeSource: bt.inner}.RawTreeWalk(bt.ctx, *root, errHandle, cbs) + btrfstree.TreeOperatorImpl{NodeSource: bt.inner}.RawTreeWalk(ctx, *root, errHandle, cbs) } func (bt *OldRebuiltForrest) TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (btrfstree.Item, error) { @@ -268,7 +268,7 @@ func (bt *OldRebuiltForrest) readNode(nodeInfo nodeInfo) *btrfstree.Node { } func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstree.TreeSearcher) (btrfstree.Item, error) { - tree := bt.RebuiltTree(treeID) + tree := bt.RebuiltTree(bt.ctx, treeID) if tree.RootErr != nil { return btrfstree.Item{}, tree.RootErr } @@ -292,7 +292,7 @@ func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstr } func (bt *OldRebuiltForrest) TreeSearchAll(treeID btrfsprim.ObjID, searcher btrfstree.TreeSearcher) ([]btrfstree.Item, error) { - tree := bt.RebuiltTree(treeID) + tree := bt.RebuiltTree(bt.ctx, treeID) if tree.RootErr != nil { return nil, tree.RootErr } @@ -328,7 +328,7 @@ func (bt *OldRebuiltForrest) TreeSearchAll(treeID btrfsprim.ObjID, searcher btrf } func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjID, errHandle func(*btrfstree.TreeError), cbs btrfstree.TreeWalkHandler) { - tree := bt.RebuiltTree(treeID) + tree := bt.RebuiltTree(ctx, treeID) if tree.RootErr != nil { errHandle(&btrfstree.TreeError{ Path: btrfstree.Path{{ -- cgit v1.2.3-2-g168b From ae15854423fd855ced22c9cb6c9ec94c83223d30 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 18 Mar 2023 00:38:16 -0400 Subject: btrfsutil: OldRebuiltForrest: Move .TreeLookup() down within the file --- lib/btrfsutil/old_rebuilt_forrest.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index 0d6adc6..fed3dd4 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -219,10 +219,6 @@ func (bt *OldRebuiltForrest) rawTreeWalk(ctx context.Context, treeID btrfsprim.O btrfstree.TreeOperatorImpl{NodeSource: bt.inner}.RawTreeWalk(ctx, *root, errHandle, cbs) } -func (bt *OldRebuiltForrest) TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (btrfstree.Item, error) { - return bt.TreeSearch(treeID, btrfstree.SearchExactKey(key)) -} - func (tree oldRebuiltTree) addErrs(fn func(btrfsprim.Key, uint32) int, err error) error { var errs derror.MultiError tree.Errors.Subrange( @@ -267,6 +263,10 @@ func (bt *OldRebuiltForrest) readNode(nodeInfo nodeInfo) *btrfstree.Node { return node } +func (bt *OldRebuiltForrest) TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (btrfstree.Item, error) { + return bt.TreeSearch(treeID, btrfstree.SearchExactKey(key)) +} + func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstree.TreeSearcher) (btrfstree.Item, error) { tree := bt.RebuiltTree(bt.ctx, treeID) if tree.RootErr != nil { -- cgit v1.2.3-2-g168b From cbb0ec1c505898bdd7062370351311f8a3da8fd8 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 2 Mar 2023 23:33:49 -0700 Subject: btrfsutil: OldRebuiltForrest: Add some doc comments --- lib/btrfsutil/old_rebuilt_forrest.go | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index fed3dd4..4573e28 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -114,6 +114,8 @@ func NewOldRebuiltForrest(ctx context.Context, inner *btrfs.FS) *OldRebuiltForre } } +// RebuiltTree returns a handle for an individual tree. An error is +// indicated by the ret.RootErr member. func (bt *OldRebuiltForrest) RebuiltTree(ctx context.Context, treeID btrfsprim.ObjID) oldRebuiltTree { if treeID == btrfsprim.ROOT_TREE_OBJECTID { bt.rootTreeMu.Lock() @@ -263,10 +265,12 @@ func (bt *OldRebuiltForrest) readNode(nodeInfo nodeInfo) *btrfstree.Node { return node } +// TreeLookup implements btrfstree.TreeOperator. func (bt *OldRebuiltForrest) TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (btrfstree.Item, error) { return bt.TreeSearch(treeID, btrfstree.SearchExactKey(key)) } +// TreeSearch implements btrfstree.TreeOperator. func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstree.TreeSearcher) (btrfstree.Item, error) { tree := bt.RebuiltTree(bt.ctx, treeID) if tree.RootErr != nil { @@ -291,6 +295,7 @@ func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstr return item, nil } +// TreeSearchAll implements btrfstree.TreeOperator. func (bt *OldRebuiltForrest) TreeSearchAll(treeID btrfsprim.ObjID, searcher btrfstree.TreeSearcher) ([]btrfstree.Item, error) { tree := bt.RebuiltTree(bt.ctx, treeID) if tree.RootErr != nil { @@ -380,10 +385,12 @@ func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjI node.Free() } +// Superblock implements btrfs.ReadableFS. func (bt *OldRebuiltForrest) Superblock() (*btrfstree.Superblock, error) { return bt.inner.Superblock() } +// ReadAt implements diskio.ReaderAt (and btrfs.ReadableFS). func (bt *OldRebuiltForrest) ReadAt(p []byte, off btrfsvol.LogicalAddr) (int, error) { return bt.inner.ReadAt(p, off) } -- cgit v1.2.3-2-g168b From 55f74940d5a4a7ea09c1be9dec0a3fc39e88434c Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 18 Mar 2023 00:49:01 -0400 Subject: btrfsutil: OldRebuiltForrest: Move the implementations of methods to the trees --- lib/btrfsutil/old_rebuilt_forrest.go | 54 ++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index 4573e28..ea9ecdc 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -20,6 +20,10 @@ import ( ) type oldRebuiltTree struct { + forrest *OldRebuiltForrest + + ID btrfsprim.ObjID + RootErr error Items *containers.RBTree[oldRebuiltTreeValue] Errors *containers.IntervalTree[btrfsprim.Key, oldRebuiltTreeError] @@ -135,6 +139,8 @@ func (bt *OldRebuiltForrest) RebuiltTree(ctx context.Context, treeID btrfsprim.O } cacheEntry := newOldRebuiltTree() + cacheEntry.forrest = bt + cacheEntry.ID = treeID dlog.Infof(ctx, "indexing tree %v...", treeID) bt.rawTreeWalk(ctx, treeID, &cacheEntry) dlog.Infof(ctx, "... done indexing tree %v", treeID) @@ -267,12 +273,20 @@ func (bt *OldRebuiltForrest) readNode(nodeInfo nodeInfo) *btrfstree.Node { // TreeLookup implements btrfstree.TreeOperator. func (bt *OldRebuiltForrest) TreeLookup(treeID btrfsprim.ObjID, key btrfsprim.Key) (btrfstree.Item, error) { - return bt.TreeSearch(treeID, btrfstree.SearchExactKey(key)) + return bt.RebuiltTree(bt.ctx, treeID).treeLookup(bt.ctx, key) +} + +func (tree oldRebuiltTree) treeLookup(ctx context.Context, key btrfsprim.Key) (btrfstree.Item, error) { + return tree.treeSearch(ctx, btrfstree.SearchExactKey(key)) } // TreeSearch implements btrfstree.TreeOperator. func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstree.TreeSearcher) (btrfstree.Item, error) { - tree := bt.RebuiltTree(bt.ctx, treeID) + return bt.RebuiltTree(bt.ctx, treeID).treeSearch(bt.ctx, searcher) +} + +// TreeSearch implements btrfstree.Tree. +func (tree oldRebuiltTree) treeSearch(_ context.Context, searcher btrfstree.TreeSearcher) (btrfstree.Item, error) { if tree.RootErr != nil { return btrfstree.Item{}, tree.RootErr } @@ -284,7 +298,7 @@ func (bt *OldRebuiltForrest) TreeSearch(treeID btrfsprim.ObjID, searcher btrfstr return btrfstree.Item{}, fmt.Errorf("item with %s: %w", searcher, tree.addErrs(searcher.Search, btrfstree.ErrNoItem)) } - node := bt.readNode(indexItem.Value.Node) + node := tree.forrest.readNode(indexItem.Value.Node) defer node.Free() item := node.BodyLeaf[indexItem.Value.Slot] @@ -303,33 +317,41 @@ func (bt *OldRebuiltForrest) TreeSearchAll(treeID btrfsprim.ObjID, searcher btrf } var ret []btrfstree.Item + err := tree.treeSubrange(bt.ctx, 1, searcher, func(item btrfstree.Item) bool { + item.Body = item.Body.CloneItem() + ret = append(ret, item) + return true + }) + + return ret, err +} + +func (tree oldRebuiltTree) treeSubrange(_ context.Context, min int, searcher btrfstree.TreeSearcher, handleFn func(btrfstree.Item) bool) error { var node *btrfstree.Node + var cnt int tree.Items.Subrange( func(indexItem oldRebuiltTreeValue) int { return searcher.Search(indexItem.Key, indexItem.ItemSize) }, func(rbNode *containers.RBNode[oldRebuiltTreeValue]) bool { + cnt++ if node == nil || node.Head.Addr != rbNode.Value.Node.LAddr { node.Free() - node = bt.readNode(rbNode.Value.Node) + node = tree.forrest.readNode(rbNode.Value.Node) } - item := node.BodyLeaf[rbNode.Value.Slot] - item.Body = item.Body.CloneItem() - ret = append(ret, item) - return true + return handleFn(node.BodyLeaf[rbNode.Value.Slot]) }) node.Free() var err error - if len(ret) == 0 { + if cnt < min { err = btrfstree.ErrNoItem } err = tree.addErrs(searcher.Search, err) if err != nil { err = fmt.Errorf("items with %s: %w", searcher, err) } - - return ret, err + return err } func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjID, errHandle func(*btrfstree.TreeError), cbs btrfstree.TreeWalkHandler) { @@ -344,6 +366,10 @@ func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjI }) return } + tree.treeWalk(ctx, errHandle, cbs) +} + +func (tree oldRebuiltTree) treeWalk(ctx context.Context, errHandle func(*btrfstree.TreeError), cbs btrfstree.TreeWalkHandler) { if cbs.Item == nil { return } @@ -352,18 +378,18 @@ func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjI if ctx.Err() != nil { return false } - if bt.ctx.Err() != nil { + if tree.forrest.ctx.Err() != nil { return false } if node == nil || node.Head.Addr != indexItem.Value.Node.LAddr { node.Free() - node = bt.readNode(indexItem.Value.Node) + node = tree.forrest.readNode(indexItem.Value.Node) } item := node.BodyLeaf[indexItem.Value.Slot] itemPath := btrfstree.Path{ { - FromTree: treeID, + FromTree: tree.ID, ToNodeAddr: indexItem.Value.Node.LAddr, ToNodeGeneration: indexItem.Value.Node.Generation, ToNodeLevel: indexItem.Value.Node.Level, -- cgit v1.2.3-2-g168b From 62a9588ff563f569469d5cf7b3b594bf109af085 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 2 Mar 2023 16:02:42 -0700 Subject: btrfstree: Move the implementations of methods to be on a separate tree object --- lib/btrfsutil/old_rebuilt_forrest.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index ea9ecdc..c4ba6d3 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -166,6 +166,10 @@ func (bt *OldRebuiltForrest) rawTreeWalk(ctx context.Context, treeID btrfsprim.O cacheEntry.RootErr = err return } + tree := &btrfstree.RawTree{ + Forrest: btrfstree.TreeOperatorImpl{NodeSource: bt.inner}, + TreeRoot: *root, + } errHandle := func(err *btrfstree.TreeError) { if len(err.Path) > 0 && err.Path.Node(-1).ToNodeAddr == 0 { @@ -224,7 +228,7 @@ func (bt *OldRebuiltForrest) rawTreeWalk(ctx context.Context, treeID btrfsprim.O }, } - btrfstree.TreeOperatorImpl{NodeSource: bt.inner}.RawTreeWalk(ctx, *root, errHandle, cbs) + tree.TreeWalk(ctx, errHandle, cbs) } func (tree oldRebuiltTree) addErrs(fn func(btrfsprim.Key, uint32) int, err error) error { -- cgit v1.2.3-2-g168b From b8185f8e741bd81e0d6f6416e46e11f6f7570995 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 2 Mar 2023 16:02:42 -0700 Subject: btrfstree: Fuss with the TreeWalk API --- lib/btrfsutil/old_rebuilt_forrest.go | 63 ++++++++++++++++-------------------- lib/btrfsutil/walk.go | 5 ++- 2 files changed, 29 insertions(+), 39 deletions(-) (limited to 'lib/btrfsutil') diff --git a/lib/btrfsutil/old_rebuilt_forrest.go b/lib/btrfsutil/old_rebuilt_forrest.go index c4ba6d3..bb5ab59 100644 --- a/lib/btrfsutil/old_rebuilt_forrest.go +++ b/lib/btrfsutil/old_rebuilt_forrest.go @@ -13,6 +13,7 @@ import ( "github.com/datawire/dlib/dlog" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" + "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" @@ -171,35 +172,17 @@ func (bt *OldRebuiltForrest) rawTreeWalk(ctx context.Context, treeID btrfsprim.O TreeRoot: *root, } - errHandle := func(err *btrfstree.TreeError) { - if len(err.Path) > 0 && err.Path.Node(-1).ToNodeAddr == 0 { - // This is a panic because on the filesystems I'm working with it more likely - // indicates a bug in my item parser than a problem with the filesystem. - panic(fmt.Errorf("TODO: error parsing item: %w", err)) - } - cacheEntry.Errors.Insert(oldRebuiltTreeError{ - Min: err.Path.Node(-1).ToKey, - Max: err.Path.Node(-1).ToMaxKey, - Err: err.Err, - }) - } - var curNode nodeInfo cbs := btrfstree.TreeWalkHandler{ - BadNode: func(path btrfstree.Path, node *btrfstree.Node, err error) error { - if node != nil { - curNode = nodeInfo{ - LAddr: path.Node(-1).ToNodeAddr, - Level: node.Head.Level, - Generation: node.Head.Generation, - Owner: node.Head.Owner, - MinItem: discardOK(node.MinItem()), - MaxItem: discardOK(node.MaxItem()), - } - } - return err + BadNode: func(path btrfstree.Path, node *btrfstree.Node, err error) bool { + cacheEntry.Errors.Insert(oldRebuiltTreeError{ + Min: path.Node(-1).ToKey, + Max: path.Node(-1).ToMaxKey, + Err: err, + }) + return false }, - Node: func(path btrfstree.Path, node *btrfstree.Node) error { + Node: func(path btrfstree.Path, node *btrfstree.Node) { curNode = nodeInfo{ LAddr: path.Node(-1).ToNodeAddr, Level: node.Head.Level, @@ -208,9 +191,8 @@ func (bt *OldRebuiltForrest) rawTreeWalk(ctx context.Context, treeID btrfsprim.O MinItem: discardOK(node.MinItem()), MaxItem: discardOK(node.MaxItem()), } - return nil }, - Item: func(path btrfstree.Path, item btrfstree.Item) error { + Item: func(path btrfstree.Path, item btrfstree.Item) { if cacheEntry.Items.Search(func(v oldRebuiltTreeValue) int { return item.Key.Compare(v.Key) }) != nil { // This is a panic because I'm not really sure what the best way to // handle this is, and so if this happens I want the program to crash @@ -224,11 +206,11 @@ func (bt *OldRebuiltForrest) rawTreeWalk(ctx context.Context, treeID btrfsprim.O Node: curNode, Slot: path.Node(-1).FromItemSlot, }) - return nil }, } + cbs.BadItem = cbs.Item - tree.TreeWalk(ctx, errHandle, cbs) + tree.TreeWalk(ctx, cbs) } func (tree oldRebuiltTree) addErrs(fn func(btrfsprim.Key, uint32) int, err error) error { @@ -358,6 +340,8 @@ func (tree oldRebuiltTree) treeSubrange(_ context.Context, min int, searcher btr return err } +// TreeWalk implements btrfstree.TreeOperator. It doesn't actually +// visit nodes or keypointers (just items). func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjID, errHandle func(*btrfstree.TreeError), cbs btrfstree.TreeWalkHandler) { tree := bt.RebuiltTree(ctx, treeID) if tree.RootErr != nil { @@ -370,11 +354,11 @@ func (bt *OldRebuiltForrest) TreeWalk(ctx context.Context, treeID btrfsprim.ObjI }) return } - tree.treeWalk(ctx, errHandle, cbs) + tree.treeWalk(ctx, cbs) } -func (tree oldRebuiltTree) treeWalk(ctx context.Context, errHandle func(*btrfstree.TreeError), cbs btrfstree.TreeWalkHandler) { - if cbs.Item == nil { +func (tree oldRebuiltTree) treeWalk(ctx context.Context, cbs btrfstree.TreeWalkHandler) { + if cbs.Item == nil && cbs.BadItem == nil { return } var node *btrfstree.Node @@ -407,10 +391,17 @@ func (tree oldRebuiltTree) treeWalk(ctx context.Context, errHandle func(*btrfstr ToMaxKey: indexItem.Value.Key, }, } - if err := cbs.Item(itemPath, item); err != nil { - errHandle(&btrfstree.TreeError{Path: itemPath, Err: err}) + switch item.Body.(type) { + case *btrfsitem.Error: + if cbs.BadItem != nil { + cbs.BadItem(itemPath, item) + } + default: + if cbs.Item != nil { + cbs.Item(itemPath, item) + } } - return true + return ctx.Err() == nil }) node.Free() } diff --git a/lib/btrfsutil/walk.go b/lib/btrfsutil/walk.go index bbdf992..b05218c 100644 --- a/lib/btrfsutil/walk.go +++ b/lib/btrfsutil/walk.go @@ -61,7 +61,7 @@ func WalkAllTrees(ctx context.Context, fs btrfstree.TreeOperator, cbs WalkAllTre }, } origItem := cbs.Item - cbs.Item = func(path btrfstree.Path, item btrfstree.Item) error { + cbs.Item = func(path btrfstree.Path, item btrfstree.Item) { if item.Key.ItemType == btrfsitem.ROOT_ITEM_KEY { trees = append(trees, struct { Name string @@ -73,9 +73,8 @@ func WalkAllTrees(ctx context.Context, fs btrfstree.TreeOperator, cbs WalkAllTre }) } if origItem != nil { - return origItem(path, item) + origItem(path, item) } - return nil } for i := 0; i < len(trees); i++ { -- cgit v1.2.3-2-g168b