summaryrefslogtreecommitdiff
path: root/lib/btrfsprogs/btrfsinspect/rebuildnodes
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/rebuildnodes')
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/forrest.go1
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/tree.go1
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/keyio/keyio.go6
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go14
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_treecb.go20
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_wantcb.go10
6 files changed, 38 insertions, 14 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/forrest.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/forrest.go
index 9ec2849..dbbc6eb 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/forrest.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/forrest.go
@@ -22,6 +22,7 @@ import (
type Callbacks 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)
}
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/tree.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/tree.go
index eab3eb2..39d8871 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/tree.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/btrees/tree.go
@@ -304,6 +304,7 @@ func (tree *RebuiltTree) AddRoot(ctx context.Context, rootNode btrfsvol.LogicalA
if (tree.ID == btrfsprim.ROOT_TREE_OBJECTID || tree.ID == btrfsprim.UUID_TREE_OBJECTID) && stats.AddedItems > 0 {
tree.forrest.flushNegativeCache(ctx)
}
+ tree.forrest.cb.AddedRoot(ctx, tree.ID, rootNode)
}
// main public API /////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/keyio/keyio.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/keyio/keyio.go
index 9e3b144..04df2b6 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/keyio/keyio.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/keyio/keyio.go
@@ -7,6 +7,7 @@ package keyio
import (
"context"
"fmt"
+ "sync"
"github.com/datawire/dlib/dlog"
@@ -48,6 +49,7 @@ type Handle struct {
Names map[ItemPtr][]byte // DIR_INDEX
Sizes map[ItemPtr]SizeAndErr // EXTENT_CSUM and EXTENT_DATA
+ mu sync.Mutex
cache containers.ARCache[btrfsvol.LogicalAddr, *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]]
}
@@ -153,6 +155,8 @@ func (o *Handle) readNode(ctx context.Context, laddr btrfsvol.LogicalAddr) *disk
}
func (o *Handle) ReadItem(ctx context.Context, ptr ItemPtr) btrfsitem.Item {
+ o.mu.Lock()
+ defer o.mu.Unlock()
if o.graph.Nodes[ptr.Node].Level != 0 {
panic(fmt.Errorf("should not happen: keyio.Handle.ReadItem called for non-leaf node@%v", ptr.Node))
}
@@ -164,5 +168,5 @@ func (o *Handle) ReadItem(ctx context.Context, ptr ItemPtr) btrfsitem.Item {
panic(fmt.Errorf("should not happen: keyio.Handle.ReadItem called for out-of-bounds item index: index=%v len=%v",
ptr.Idx, len(items)))
}
- return items[ptr.Idx].Body
+ return items[ptr.Idx].Body.CloneItem()
}
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go
index dc78c2e..bc36485 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go
@@ -56,6 +56,7 @@ type rebuilder struct {
Key containers.Optional[btrfsprim.Key]
}
treeQueue containers.Set[btrfsprim.ObjID]
+ retryItemQueue map[btrfsprim.ObjID]containers.Set[keyAndTree]
addedItemQueue containers.Set[keyAndTree]
settledItemQueue containers.Set[keyAndTree]
augmentQueue map[btrfsprim.ObjID]*treeAugmentQueue
@@ -98,6 +99,7 @@ func (o *rebuilder) Rebuild(ctx context.Context) error {
ctx = dlog.WithField(ctx, "btrfsinspect.rebuild-nodes.step", "rebuild")
// Initialize
+ o.retryItemQueue = make(map[btrfsprim.ObjID]containers.Set[keyAndTree])
o.addedItemQueue = make(containers.Set[keyAndTree])
o.settledItemQueue = make(containers.Set[keyAndTree])
o.augmentQueue = make(map[btrfsprim.ObjID]*treeAugmentQueue)
@@ -133,7 +135,7 @@ func (o *rebuilder) Rebuild(ctx context.Context) error {
}
runtime.GC()
- // Apply augments (drain o.augmentQueue, fill o.addedItemQueue).
+ // Apply augments (drain o.augmentQueue (and maybe o.retryItemQueue), fill o.addedItemQueue).
if err := o.processAugmentQueue(ctx); err != nil {
return err
}
@@ -286,6 +288,7 @@ func (o *rebuilder) processSettledItemQueue(ctx context.Context) error {
Key: item.Key,
Body: item.Body,
})
+ item.Body.Free()
if item.ItemType == btrfsitem.ROOT_ITEM_KEY {
o.treeQueue.Insert(item.ObjectID)
}
@@ -300,7 +303,7 @@ func (o *rebuilder) processSettledItemQueue(ctx context.Context) error {
return grp.Wait()
}
-// processAugmentQueue drains o.augmentQueue, filling o.addedItemQueue.
+// processAugmentQueue drains o.augmentQueue (and maybe o.retryItemQueue), filling o.addedItemQueue.
func (o *rebuilder) processAugmentQueue(ctx context.Context) error {
ctx = dlog.WithField(ctx, "btrfsinspect.rebuild-nodes.rebuild.substep", "apply-augments")
@@ -342,9 +345,12 @@ func (o *rebuilder) processAugmentQueue(ctx context.Context) error {
return nil
}
-func (o *rebuilder) enqueueRetry() {
+func (o *rebuilder) enqueueRetry(ifTreeID btrfsprim.ObjID) {
if o.curKey.Key.OK {
- o.settledItemQueue.Insert(keyAndTree{
+ if o.retryItemQueue[ifTreeID] == nil {
+ o.retryItemQueue[ifTreeID] = make(containers.Set[keyAndTree])
+ }
+ o.retryItemQueue[ifTreeID].Insert(keyAndTree{
TreeID: o.curKey.TreeID,
Key: o.curKey.Key.Val,
})
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_treecb.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_treecb.go
index eb0204c..492436b 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_treecb.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_treecb.go
@@ -10,6 +10,7 @@ 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"
)
// AddedItem implements btrees.Callbacks.
@@ -20,6 +21,13 @@ func (o *rebuilder) AddedItem(ctx context.Context, tree btrfsprim.ObjID, key btr
})
}
+// AddedRoot implements btrees.Callbacks.
+func (o *rebuilder) AddedRoot(ctx context.Context, tree btrfsprim.ObjID, root btrfsvol.LogicalAddr) {
+ if retries := o.retryItemQueue[tree]; retries != nil {
+ o.addedItemQueue.InsertFrom(retries)
+ }
+}
+
// LookupRoot implements btrees.Callbacks.
func (o *rebuilder) LookupRoot(ctx context.Context, tree btrfsprim.ObjID) (offset btrfsprim.Generation, item btrfsitem.Root, ok bool) {
wantKey := WantWithTree{
@@ -33,10 +41,12 @@ func (o *rebuilder) LookupRoot(ctx context.Context, tree btrfsprim.ObjID) (offse
ctx = withWant(ctx, logFieldTreeWant, "tree Root", wantKey)
foundKey, ok := o._want(ctx, wantKey)
if !ok {
- o.enqueueRetry()
+ o.enqueueRetry(btrfsprim.ROOT_TREE_OBJECTID)
return 0, btrfsitem.Root{}, false
}
- switch itemBody := o.rebuilt.Tree(ctx, wantKey.TreeID).ReadItem(ctx, foundKey).(type) {
+ itemBody := o.rebuilt.Tree(ctx, wantKey.TreeID).ReadItem(ctx, foundKey)
+ defer itemBody.Free()
+ switch itemBody := itemBody.(type) {
case *btrfsitem.Root:
return btrfsprim.Generation(foundKey.Offset), *itemBody, true
case *btrfsitem.Error:
@@ -57,10 +67,12 @@ func (o *rebuilder) LookupUUID(ctx context.Context, uuid btrfsprim.UUID) (id btr
}
ctx = withWant(ctx, logFieldTreeWant, "resolve parent UUID", wantKey)
if !o._wantOff(ctx, wantKey) {
- o.enqueueRetry()
+ o.enqueueRetry(btrfsprim.UUID_TREE_OBJECTID)
return 0, false
}
- switch itemBody := o.rebuilt.Tree(ctx, wantKey.TreeID).ReadItem(ctx, wantKey.Key.Key()).(type) {
+ itemBody := o.rebuilt.Tree(ctx, wantKey.TreeID).ReadItem(ctx, wantKey.Key.Key())
+ defer itemBody.Free()
+ switch itemBody := itemBody.(type) {
case *btrfsitem.UUIDMap:
return itemBody.ObjID, true
case *btrfsitem.Error:
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_wantcb.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_wantcb.go
index c57b2bb..adf3cff 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_wantcb.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild_wantcb.go
@@ -40,7 +40,7 @@ func (o *rebuilder) want(ctx context.Context, reason string, treeID btrfsprim.Ob
func (o *rebuilder) _want(ctx context.Context, wantKey WantWithTree) (key btrfsprim.Key, ok bool) {
if o.rebuilt.Tree(ctx, wantKey.TreeID) == nil {
- o.enqueueRetry()
+ o.enqueueRetry(wantKey.TreeID)
return btrfsprim.Key{}, false
}
@@ -90,7 +90,7 @@ func (o *rebuilder) wantOff(ctx context.Context, reason string, treeID btrfsprim
func (o *rebuilder) _wantOff(ctx context.Context, wantKey WantWithTree) (ok bool) {
if o.rebuilt.Tree(ctx, wantKey.TreeID) == nil {
- o.enqueueRetry()
+ o.enqueueRetry(wantKey.TreeID)
return false
}
@@ -131,7 +131,7 @@ func (o *rebuilder) wantDirIndex(ctx context.Context, reason string, treeID btrf
ctx = withWant(ctx, logFieldItemWant, reason, wantKey)
if o.rebuilt.Tree(ctx, treeID) == nil {
- o.enqueueRetry()
+ o.enqueueRetry(treeID)
return
}
@@ -256,7 +256,7 @@ func (o *rebuilder) _wantRange(
wantKey.Key.OffsetType = offsetRange
if o.rebuilt.Tree(ctx, treeID) == nil {
- o.enqueueRetry()
+ o.enqueueRetry(treeID)
return
}
@@ -365,7 +365,7 @@ func (o *rebuilder) wantCSum(ctx context.Context, reason string, inodeTree, inod
}
inodeCtx := withWant(ctx, logFieldItemWant, reason, inodeWant)
if !o._wantOff(inodeCtx, inodeWant) {
- o.enqueueRetry()
+ o.enqueueRetry(inodeTree)
return
}
inodePtr, ok := o.rebuilt.Tree(inodeCtx, inodeTree).Items(inodeCtx).Load(inodeWant.Key.Key())