diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-04-05 10:10:34 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-04-09 12:17:50 -0600 |
commit | 8e215721b38972c522b692032bf1c516eb62359f (patch) | |
tree | f77874f4d545d93a4b38d225f071393d29683258 /lib/btrfs/btrfstree/path.go | |
parent | 825fe95475952b18fc586630de5ddaf3faacbde7 (diff) |
btrfstree: Do a better job of checking node ownership
This now considers the interior nodes *between* the root and the leaf,
instead of just considering the root and the leaf.
Diffstat (limited to 'lib/btrfs/btrfstree/path.go')
-rw-r--r-- | lib/btrfs/btrfstree/path.go | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/lib/btrfs/btrfstree/path.go b/lib/btrfs/btrfstree/path.go index 537df9a..57669ee 100644 --- a/lib/btrfs/btrfstree/path.go +++ b/lib/btrfs/btrfstree/path.go @@ -69,7 +69,7 @@ type PathElem interface { } type PathRoot struct { - Tree Tree + Forrest Forrest // It should be no surprise that these 4 members mimic the 4 // members of a 'RawTree'. TreeID btrfsprim.ObjID @@ -133,6 +133,45 @@ func (path Path) String() string { return ret.String() } +func checkOwner( + ctx context.Context, forrest Forrest, treeID btrfsprim.ObjID, failOpen bool, + ownerToCheck btrfsprim.ObjID, genToCheck btrfsprim.Generation, +) error { + for { + if ownerToCheck == treeID { + return nil + } + + 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) + } + + if parentID == 0 && parentGen == 0 { + return fmt.Errorf("owner=%v is not acceptable in this tree", + ownerToCheck) + } + if genToCheck > parentGen { + return fmt.Errorf("claimed owner=%v might be acceptable in this tree (if generation<=%v) but not with claimed generation=%v", + ownerToCheck, parentGen, genToCheck) + } + treeID = parentID + } +} + // NodeExpectations returns the address to read and the expectations // to have when reading the node pointed to by this Path. // @@ -153,7 +192,8 @@ 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 firstElem.Tree.TreeCheckOwner(ctx, failOpen, owner, gen) + return checkOwner(ctx, firstElem.Forrest, lastElem.TreeID, failOpen, + owner, gen) }, MinItem: containers.OptionalValue(btrfsprim.Key{}), MaxItem: containers.OptionalValue(btrfsprim.MaxKey), @@ -164,7 +204,8 @@ 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 firstElem.Tree.TreeCheckOwner(ctx, failOpen, owner, gen) + return checkOwner(ctx, firstElem.Forrest, lastElem.FromTree, failOpen, + owner, gen) }, MinItem: containers.OptionalValue(lastElem.ToMinKey), MaxItem: containers.OptionalValue(lastElem.ToMaxKey), |