summaryrefslogtreecommitdiff
path: root/cmd/btrfs-rec/inspect
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-04-07 15:30:46 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2023-04-17 21:51:58 -0600
commitee2564cc3164e2c235b3d617a1a4fed2f9d9efc6 (patch)
tree49c9dc81d64e3c22aa954025010e2edeedb94522 /cmd/btrfs-rec/inspect
parent72c0d02ebf69b12ab434a5243978f05a65c43e3b (diff)
btrfsutil.RebuiltForrest, rebuildtrees: Be more permissive of broken UUID_TREEs
Diffstat (limited to 'cmd/btrfs-rec/inspect')
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go40
1 files changed, 39 insertions, 1 deletions
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
index b8205ae..466082c 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
@@ -75,7 +75,9 @@ func (o forrestCallbacks) LookupUUID(ctx context.Context, uuid btrfsprim.UUID) (
}
ctx = withWant(ctx, logFieldTreeWant, "resolve parent UUID", wantKey)
if !o._wantOff(ctx, wantKey) {
- o.enqueueRetry(btrfsprim.UUID_TREE_OBJECTID)
+ if id, ok := o.slowLookupUUID(ctx, uuid); ok {
+ return id, nil
+ }
return 0, btrfstree.ErrNoItem
}
item, _ := discardErr(o.rebuilt.RebuiltTree(ctx, wantKey.TreeID)).TreeLookup(ctx, wantKey.Key.Key())
@@ -85,6 +87,9 @@ func (o forrestCallbacks) LookupUUID(ctx context.Context, uuid btrfsprim.UUID) (
return itemBody.ObjID, nil
case *btrfsitem.Error:
graphCallbacks(o).FSErr(ctx, fmt.Errorf("error decoding item: %v: %w", wantKey, itemBody.Err))
+ if id, ok := o.slowLookupUUID(ctx, uuid); ok {
+ return id, nil
+ }
return 0, itemBody.Err
default:
// This is a panic because the item decoder should not emit UUID_SUBVOL items as anything but
@@ -92,3 +97,36 @@ func (o forrestCallbacks) LookupUUID(ctx context.Context, uuid btrfsprim.UUID) (
panic(fmt.Errorf("should not happen: UUID_SUBVOL item has unexpected type: %T", itemBody))
}
}
+
+func (o forrestCallbacks) slowLookupUUID(ctx context.Context, uuid btrfsprim.UUID) (id btrfsprim.ObjID, ok bool) {
+ rootTree, err := o.rebuilt.RebuiltTree(ctx, btrfsprim.ROOT_TREE_OBJECTID)
+ if err != nil {
+ o.enqueueRetry(btrfsprim.ROOT_TREE_OBJECTID)
+ return 0, false
+ }
+ var ret btrfsprim.ObjID
+ _ = rootTree.TreeRange(ctx, func(item btrfstree.Item) bool {
+ if item.Key.ItemType != btrfsprim.ROOT_ITEM_KEY {
+ return true
+ }
+ switch itemBody := item.Body.(type) {
+ case *btrfsitem.Root:
+ if itemBody.UUID == uuid {
+ ret = item.Key.ObjectID
+ return false
+ }
+ case *btrfsitem.Error:
+ graphCallbacks(o).FSErr(ctx, fmt.Errorf("error decoding item: %v: %w", item.Key, itemBody.Err))
+ default:
+ // This is a panic because the item decoder should not emit ROOT_ITEM items as anything but
+ // btrfsitem.Root or btrfsitem.Error without this code also being updated.
+ panic(fmt.Errorf("should not happen: ROOT_ITEM item has unexpected type: %T", itemBody))
+ }
+ return true
+ })
+ if ret == 0 {
+ o.enqueueRetry(btrfsprim.ROOT_TREE_OBJECTID)
+ return 0, false
+ }
+ return ret, true
+}