summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-04-07 13:52:35 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2023-04-13 13:18:40 -0600
commit01d7bcfc588c5551e8ac387f62d2fc4468ba1f4c (patch)
tree6b4e58e4ffec6295ffe82086d8c37cbf0e39c609
parentc88331692ea676acf67eb489a600688cf0c62fc6 (diff)
btrfsutil: RebuiltForrest: Allow skipping the .AddedItem loop
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go5
-rw-r--r--lib/btrfsutil/rebuilt_callbacks.go7
-rw-r--r--lib/btrfsutil/rebuilt_forrest.go7
-rw-r--r--lib/btrfsutil/rebuilt_tree.go48
4 files changed, 42 insertions, 25 deletions
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
index 92b5ee5..0c52556 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
@@ -11,13 +11,16 @@ 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/btrfsutil"
)
type forrestCallbacks struct {
*rebuilder
}
-// AddedItem implements btrfsutil.RebuiltForrestCallbacks.
+var _ btrfsutil.RebuiltForrestExtendedCallbacks = forrestCallbacks{}
+
+// AddedItem implements btrfsutil.RebuiltForrestExtendedCallbacks.
func (o forrestCallbacks) AddedItem(_ context.Context, tree btrfsprim.ObjID, key btrfsprim.Key) {
o.addedItemQueue.Insert(keyAndTree{
TreeID: tree,
diff --git a/lib/btrfsutil/rebuilt_callbacks.go b/lib/btrfsutil/rebuilt_callbacks.go
index fef16d4..3a7e6e6 100644
--- a/lib/btrfsutil/rebuilt_callbacks.go
+++ b/lib/btrfsutil/rebuilt_callbacks.go
@@ -14,17 +14,20 @@ import (
)
type RebuiltForrestCallbacks interface {
- AddedItem(ctx context.Context, tree btrfsprim.ObjID, key btrfsprim.Key)
AddedRoot(ctx context.Context, tree btrfsprim.ObjID, root btrfsvol.LogicalAddr)
LookupRoot(ctx context.Context, tree btrfsprim.ObjID) (offset btrfsprim.Generation, item btrfsitem.Root, ok bool)
LookupUUID(ctx context.Context, uuid btrfsprim.UUID) (id btrfsprim.ObjID, ok bool)
}
+type RebuiltForrestExtendedCallbacks interface {
+ RebuiltForrestCallbacks
+ AddedItem(ctx context.Context, tree btrfsprim.ObjID, key btrfsprim.Key)
+}
+
type noopRebuiltForrestCallbacks struct {
forrest *RebuiltForrest
}
-func (noopRebuiltForrestCallbacks) AddedItem(context.Context, btrfsprim.ObjID, btrfsprim.Key) {}
func (noopRebuiltForrestCallbacks) AddedRoot(context.Context, btrfsprim.ObjID, btrfsvol.LogicalAddr) {
}
diff --git a/lib/btrfsutil/rebuilt_forrest.go b/lib/btrfsutil/rebuilt_forrest.go
index 29a5210..4249396 100644
--- a/lib/btrfsutil/rebuilt_forrest.go
+++ b/lib/btrfsutil/rebuilt_forrest.go
@@ -73,8 +73,11 @@ type RebuiltForrest struct {
rebuiltSharedCache
}
-// NewRebuiltForrest returns a new RebuiltForrest instance. The
-// RebuiltForrestCallbacks may be nil.
+// NewRebuiltForrest returns a new RebuiltForrest instance.
+//
+// The `cb` RebuiltForrestCallbacks may be nil. If `cb` also
+// implements RebuiltForrestExtendedCallbacks, then a series of
+// .AddedItem() calls will be made before each call to .AddedRoot().
func NewRebuiltForrest(fs btrfs.ReadableFS, graph Graph, cb RebuiltForrestCallbacks) *RebuiltForrest {
ret := &RebuiltForrest{
inner: fs,
diff --git a/lib/btrfsutil/rebuilt_tree.go b/lib/btrfsutil/rebuilt_tree.go
index 31a31be..e4d5ddd 100644
--- a/lib/btrfsutil/rebuilt_tree.go
+++ b/lib/btrfsutil/rebuilt_tree.go
@@ -320,37 +320,45 @@ func (tree *RebuiltTree) RebuiltAddRoot(ctx context.Context, rootNode btrfsvol.L
ctx = dlog.WithField(ctx, "btrfs.util.rebuilt-tree.add-root", fmt.Sprintf("tree=%v rootNode=%v", tree.ID, rootNode))
dlog.Info(ctx, "adding root...")
- var stats rebuiltRootStats
- leafToRoots := tree.acquireLeafToRoots(ctx)
- stats.Leafs.D = len(leafToRoots)
- progressWriter := textui.NewProgress[rebuiltRootStats](ctx, dlog.LogLevelInfo, textui.Tunable(1*time.Second))
- for i, leaf := range maps.SortedKeys(leafToRoots) {
- stats.Leafs.N = i
- progressWriter.Set(stats)
+ shouldFlush := tree.ID == btrfsprim.ROOT_TREE_OBJECTID || tree.ID == btrfsprim.UUID_TREE_OBJECTID
+
+ if extCB, ok := tree.forrest.cb.(RebuiltForrestExtendedCallbacks); ok {
+ var stats rebuiltRootStats
+ leafToRoots := tree.acquireLeafToRoots(ctx)
+ stats.Leafs.D = len(leafToRoots)
+ progressWriter := textui.NewProgress[rebuiltRootStats](ctx, dlog.LogLevelInfo, textui.Tunable(1*time.Second))
+ for i, leaf := range maps.SortedKeys(leafToRoots) {
+ stats.Leafs.N = i
+ progressWriter.Set(stats)
- if tree.Roots.HasAny(leafToRoots[leaf]) || !leafToRoots[leaf].Has(rootNode) {
- continue
- }
+ if tree.Roots.HasAny(leafToRoots[leaf]) || !leafToRoots[leaf].Has(rootNode) {
+ continue
+ }
+
+ stats.AddedLeafs++
+ progressWriter.Set(stats)
- stats.AddedLeafs++
+ for _, itemKey := range tree.forrest.graph.Nodes[leaf].Items {
+ extCB.AddedItem(ctx, tree.ID, itemKey)
+ stats.AddedItems++
+ progressWriter.Set(stats)
+ }
+ }
+ stats.Leafs.N = len(leafToRoots)
+ tree.releaseLeafToRoots()
progressWriter.Set(stats)
+ progressWriter.Done()
- for _, itemKey := range tree.forrest.graph.Nodes[leaf].Items {
- tree.forrest.cb.AddedItem(ctx, tree.ID, itemKey)
- stats.AddedItems++
- progressWriter.Set(stats)
+ if stats.AddedItems == 0 {
+ shouldFlush = false
}
}
- stats.Leafs.N = len(leafToRoots)
- tree.releaseLeafToRoots()
- progressWriter.Set(stats)
- progressWriter.Done()
tree.Roots.Insert(rootNode)
tree.forrest.incItems.Delete(tree.ID) // force re-gen
tree.forrest.excItems.Delete(tree.ID) // force re-gen
- if (tree.ID == btrfsprim.ROOT_TREE_OBJECTID || tree.ID == btrfsprim.UUID_TREE_OBJECTID) && stats.AddedItems > 0 {
+ if shouldFlush {
tree.forrest.flushNegativeCache(ctx)
}
tree.forrest.cb.AddedRoot(ctx, tree.ID, rootNode)