diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-04-17 02:05:51 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-04-17 02:05:51 -0600 |
commit | 4efa228eb104145bb0750fb68c0d9493dc5854d5 (patch) | |
tree | 1dbcbd104be9e1034037a2d43b5927b1b61c08d6 /lib/btrfs | |
parent | 4adcf5f67965bf355cc7e16ec11e2293c2506700 (diff) | |
parent | f262c7bbc72796ae36b7e40dc38ab7167d138d5b (diff) |
Merge branch 'lukeshu/rebuilt-v2-pt2-lax-parents'
Diffstat (limited to 'lib/btrfs')
-rw-r--r-- | lib/btrfs/btrfstree/btree_tree.go | 2 | ||||
-rw-r--r-- | lib/btrfs/btrfstree/path.go | 22 |
2 files changed, 13 insertions, 11 deletions
diff --git a/lib/btrfs/btrfstree/btree_tree.go b/lib/btrfs/btrfstree/btree_tree.go index 6056ae8..b9b9201 100644 --- a/lib/btrfs/btrfstree/btree_tree.go +++ b/lib/btrfs/btrfstree/btree_tree.go @@ -54,7 +54,7 @@ func (tree *RawTree) walk(ctx context.Context, sb Superblock, path Path, cbs Tre } // 001 - nodeAddr, nodeExp, ok := path.NodeExpectations(ctx, true) // TODO(lukeshu): Consider whether failing open is the right thing here + nodeAddr, nodeExp, ok := path.NodeExpectations(ctx) if !ok { return } diff --git a/lib/btrfs/btrfstree/path.go b/lib/btrfs/btrfstree/path.go index 57669ee..327a39b 100644 --- a/lib/btrfs/btrfstree/path.go +++ b/lib/btrfs/btrfstree/path.go @@ -12,6 +12,7 @@ import ( "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/containers" + "git.lukeshu.com/btrfs-progs-ng/lib/slices" ) // Path is a path from the superblock or a ROOT_ITEM to a node or @@ -134,9 +135,10 @@ func (path Path) String() string { } func checkOwner( - ctx context.Context, forrest Forrest, treeID btrfsprim.ObjID, failOpen bool, + ctx context.Context, forrest Forrest, treeID btrfsprim.ObjID, ownerToCheck btrfsprim.ObjID, genToCheck btrfsprim.Generation, ) error { + var stack []btrfsprim.ObjID for { if ownerToCheck == treeID { return nil @@ -144,22 +146,22 @@ func checkOwner( tree, err := forrest.ForrestLookup(ctx, treeID) if err != nil { - if failOpen { - return nil - } return fmt.Errorf("unable to determine whether owner=%v generation=%v is acceptable: %w", ownerToCheck, genToCheck, err) } parentID, parentGen, err := tree.TreeParentID(ctx) if err != nil { - if failOpen { - return nil - } return fmt.Errorf("unable to determine whether owner=%v generation=%v is acceptable: %w", ownerToCheck, genToCheck, err) } + stack = append(stack, treeID) + if slices.Contains(parentID, stack) { + // Don't get stuck in an infinite loop if there's a cycle. + parentID = 0 + } + if parentID == 0 && parentGen == 0 { return fmt.Errorf("owner=%v is not acceptable in this tree", ownerToCheck) @@ -177,7 +179,7 @@ func checkOwner( // // `ok` is false if the path is empty or if this Path points to an // item rather than a node. -func (path Path) NodeExpectations(ctx context.Context, failOpen bool) (_ btrfsvol.LogicalAddr, _ NodeExpectations, ok bool) { +func (path Path) NodeExpectations(ctx context.Context) (_ btrfsvol.LogicalAddr, _ NodeExpectations, ok bool) { if len(path) == 0 { return 0, NodeExpectations{}, false } @@ -192,7 +194,7 @@ func (path Path) NodeExpectations(ctx context.Context, failOpen bool) (_ btrfsvo Level: containers.OptionalValue(lastElem.ToLevel), Generation: containers.OptionalValue(lastElem.ToGeneration), Owner: func(owner btrfsprim.ObjID, gen btrfsprim.Generation) error { - return checkOwner(ctx, firstElem.Forrest, lastElem.TreeID, failOpen, + return checkOwner(ctx, firstElem.Forrest, lastElem.TreeID, owner, gen) }, MinItem: containers.OptionalValue(btrfsprim.Key{}), @@ -204,7 +206,7 @@ func (path Path) NodeExpectations(ctx context.Context, failOpen bool) (_ btrfsvo Level: containers.OptionalValue(lastElem.ToLevel), Generation: containers.OptionalValue(lastElem.ToGeneration), Owner: func(owner btrfsprim.ObjID, gen btrfsprim.Generation) error { - return checkOwner(ctx, firstElem.Forrest, lastElem.FromTree, failOpen, + return checkOwner(ctx, firstElem.Forrest, lastElem.FromTree, owner, gen) }, MinItem: containers.OptionalValue(lastElem.ToMinKey), |