1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
package btrfstree
import (
"fmt"
"github.com/datawire/dlib/derror"
"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"
)
type NodeExpectations struct {
LAddr containers.Optional[btrfsvol.LogicalAddr]
// Things knowable from the parent.
Level containers.Optional[uint8]
Generation containers.Optional[btrfsprim.Generation]
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]
}
func (exp NodeExpectations) Check(node *Node) error {
var errs derror.MultiError
if exp.LAddr.OK && node.Head.Addr != exp.LAddr.Val {
errs = append(errs, fmt.Errorf("read from laddr=%v but claims to be at laddr=%v",
exp.LAddr.Val, node.Head.Addr))
}
if exp.Level.OK && node.Head.Level != exp.Level.Val {
errs = append(errs, fmt.Errorf("expected level=%v but claims to be level=%v",
exp.Level.Val, node.Head.Level))
}
if node.Head.Level > MaxLevel {
errs = append(errs, fmt.Errorf("maximum level=%v but claims to be level=%v",
MaxLevel, node.Head.Level))
}
if exp.Generation.OK && node.Head.Generation != exp.Generation.Val {
errs = append(errs, fmt.Errorf("expected generation=%v but claims to be generation=%v",
exp.Generation.Val, node.Head.Generation))
}
if exp.Owner != nil {
if err := exp.Owner(node.Head.Owner, node.Head.Generation); err != nil {
errs = append(errs, err)
}
}
if node.Head.NumItems == 0 {
errs = append(errs, fmt.Errorf("has no items"))
} else {
if minItem, _ := node.MinItem(); exp.MinItem.OK && exp.MinItem.Val.Compare(minItem) > 0 {
errs = append(errs, fmt.Errorf("expected minItem>=%v but node has minItem=%v",
exp.MinItem, minItem))
}
if maxItem, _ := node.MaxItem(); exp.MaxItem.OK && exp.MaxItem.Val.Compare(maxItem) < 0 {
errs = append(errs, fmt.Errorf("expected maxItem<=%v but node has maxItem=%v",
exp.MaxItem, maxItem))
}
}
if len(errs) > 0 {
return errs
}
return nil
}
|