From d0b7bc25341c936e96a64a540824f77ed79878ce Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 30 Mar 2023 00:53:34 -0600 Subject: btrfstree: Move Path.NodeExpectations from readnode.go to path.go --- lib/btrfs/btrfstree/path.go | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'lib/btrfs/btrfstree/path.go') diff --git a/lib/btrfs/btrfstree/path.go b/lib/btrfs/btrfstree/path.go index c07d8a0..1335b76 100644 --- a/lib/btrfs/btrfstree/path.go +++ b/lib/btrfs/btrfstree/path.go @@ -11,6 +11,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" ) // Path is a path from the superblock (i.e. the root of the btrfs @@ -123,6 +124,56 @@ func (path Path) DeepCopy() Path { return append(Path(nil), path...) } +// NodeExpectations returns the address to read and the expectations +// to have when reading the node pointed to by this Path. +// +// `ok` is false if the path is empty or if this Path points to an +// item rather than a node. +func (path Path) NodeExpectations(fs NodeFile) (_ btrfsvol.LogicalAddr, _ NodeExpectations, ok bool) { + if path.Node(-1).ToNodeAddr == 0 && path.Node(-1).ToNodeGeneration == 0 && path.Node(-1).ToNodeLevel == 0 { + return 0, NodeExpectations{}, false + } + + checkOwner := func(owner btrfsprim.ObjID, gen btrfsprim.Generation) error { + var treeParents []btrfsprim.ObjID + + tree := path.Node(-1).FromTree + for { + if owner == tree { + // OK! + return nil + } + + treeParents = append(treeParents, tree) + parent, parentGen, parentOK := fs.ParentTree(tree) + if !parentOK { + // Failed look up parent info; fail open. + return nil + } + + if parent == 0 { + // End of the line. + return fmt.Errorf("expected owner in %v but claims to have owner=%v", + treeParents, owner) + } + if gen > parentGen { + return fmt.Errorf("claimed owner=%v might be acceptable in this tree (if generation<=%v) but not with claimed generation=%v", + owner, parentGen, gen) + } + tree = parent + } + } + + return path.Node(-1).ToNodeAddr, NodeExpectations{ + LAddr: containers.OptionalValue(path.Node(-1).ToNodeAddr), + Level: containers.OptionalValue(path.Node(-1).ToNodeLevel), + Generation: containers.OptionalValue(path.Node(-1).ToNodeGeneration), + Owner: checkOwner, + MinItem: containers.OptionalValue(path.Node(-1).ToKey), + MaxItem: containers.OptionalValue(path.Node(-1).ToMaxKey), + }, true +} + func (path Path) Parent() Path { return path[:len(path)-1] } -- cgit v1.2.3-54-g00ecf