summaryrefslogtreecommitdiff
path: root/lib/btrfs/btrfstree
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-03-23 21:33:19 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2023-03-23 21:33:19 -0600
commitbf5eed5af5c34b8cf9dc2985a7c4475602929bb1 (patch)
tree9cb910940a1e16982f5c5012a4fbeb37ba172f82 /lib/btrfs/btrfstree
parentf0a9faf21dbe508d57da3b18be9121559c70876a (diff)
parent418553acc64567ebc95122e28b07657526c92923 (diff)
Merge branch 'lukeshu/tree-api-pt1-changes'
Diffstat (limited to 'lib/btrfs/btrfstree')
-rw-r--r--lib/btrfs/btrfstree/btree_forrest.go5
-rw-r--r--lib/btrfs/btrfstree/readnode.go34
-rw-r--r--lib/btrfs/btrfstree/types_node.go4
3 files changed, 27 insertions, 16 deletions
diff --git a/lib/btrfs/btrfstree/btree_forrest.go b/lib/btrfs/btrfstree/btree_forrest.go
index 8f8e2de..38a2721 100644
--- a/lib/btrfs/btrfstree/btree_forrest.go
+++ b/lib/btrfs/btrfstree/btree_forrest.go
@@ -21,6 +21,8 @@ type TreeRoot struct {
RootNode btrfsvol.LogicalAddr
Level uint8
Generation btrfsprim.Generation
+
+ RootInode btrfsprim.ObjID // only for subvolume trees
}
// LookupTreeRoot is a utility function to help with implementing the
@@ -59,7 +61,7 @@ func LookupTreeRoot(_ context.Context, fs TreeOperator, sb Superblock, treeID bt
rootItem, err := fs.TreeSearch(btrfsprim.ROOT_TREE_OBJECTID, SearchRootItem(treeID))
if err != nil {
if errors.Is(err, ErrNoItem) {
- err = ErrNoTree
+ err = fmt.Errorf("%w: %s", ErrNoTree, err)
}
return nil, fmt.Errorf("tree %s: %w", treeID.Format(btrfsprim.ROOT_TREE_OBJECTID), err)
}
@@ -70,6 +72,7 @@ func LookupTreeRoot(_ context.Context, fs TreeOperator, sb Superblock, treeID bt
RootNode: rootItemBody.ByteNr,
Level: rootItemBody.Level,
Generation: rootItemBody.Generation,
+ RootInode: rootItemBody.RootDirID,
}, nil
case *btrfsitem.Error:
return nil, fmt.Errorf("malformed ROOT_ITEM for tree %v: %w", treeID, rootItemBody.Err)
diff --git a/lib/btrfs/btrfstree/readnode.go b/lib/btrfs/btrfstree/readnode.go
index c2e3b0f..ac82c62 100644
--- a/lib/btrfs/btrfstree/readnode.go
+++ b/lib/btrfs/btrfstree/readnode.go
@@ -20,13 +20,13 @@ type NodeFile interface {
// ParentTree, given a tree ID, returns that tree's parent
// tree, if it has one.
//
- // - non-zero, true : the parent tree ID
+ // - non-zero, ?, true : the parent tree ID
//
- // - 0, true : the tree does not have a parent
+ // - 0, 0, true : the tree does not have a parent
//
- // - any, false : the tree's parent information could not be
+ // - ?, ?, false : the tree's parent information could not be
// looked up
- ParentTree(btrfsprim.ObjID) (btrfsprim.ObjID, bool)
+ ParentTree(btrfsprim.ObjID) (btrfsprim.ObjID, btrfsprim.Generation, bool)
}
// FSReadNode is a utility function to help with implementing the
@@ -40,25 +40,33 @@ func FSReadNode(
return nil, fmt.Errorf("btrfs.FS.ReadNode: %w", err)
}
- var treeParents []btrfsprim.ObjID
- checkOwner := func(owner btrfsprim.ObjID) error {
- exp := path.Node(-1).FromTree
+ checkOwner := func(owner btrfsprim.ObjID, gen btrfsprim.Generation) error {
+ var treeParents []btrfsprim.ObjID
+
+ tree := path.Node(-1).FromTree
for {
- if owner == exp {
+ if owner == tree {
+ // OK!
return nil
}
- treeParents = append(treeParents, exp)
- var ok bool
- exp, ok = fs.ParentTree(exp)
- if !ok {
+
+ treeParents = append(treeParents, tree)
+ parent, parentGen, parentOK := fs.ParentTree(tree)
+ if !parentOK {
// Failed look up parent info; fail open.
return nil
}
- if exp == 0 {
+
+ 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
}
}
diff --git a/lib/btrfs/btrfstree/types_node.go b/lib/btrfs/btrfstree/types_node.go
index 622f23c..bfcbbf4 100644
--- a/lib/btrfs/btrfstree/types_node.go
+++ b/lib/btrfs/btrfstree/types_node.go
@@ -417,7 +417,7 @@ type NodeExpectations struct {
// Things knowable from the parent.
Level containers.Optional[uint8]
Generation containers.Optional[btrfsprim.Generation]
- Owner func(btrfsprim.ObjID) error
+ Owner func(btrfsprim.ObjID, btrfsprim.Generation) error
MinItem containers.Optional[btrfsprim.Key]
// Things knowable from the structure of the tree.
MaxItem containers.Optional[btrfsprim.Key]
@@ -547,7 +547,7 @@ func (exp NodeExpectations) Check(node *Node) error {
exp.Generation.Val, node.Head.Generation))
}
if exp.Owner != nil {
- if err := exp.Owner(node.Head.Owner); err != nil {
+ if err := exp.Owner(node.Head.Owner, node.Head.Generation); err != nil {
errs = append(errs, err)
}
}