summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/btrfs/io3_btree.go44
-rw-r--r--pkg/btrfs/io4_fs.go (renamed from pkg/btrfs/io3_fs.go)0
-rw-r--r--pkg/btrfs/types_node.go11
-rw-r--r--pkg/btrfsmisc/walk.go59
4 files changed, 92 insertions, 22 deletions
diff --git a/pkg/btrfs/io3_btree.go b/pkg/btrfs/io3_btree.go
index 01da746..3c1535b 100644
--- a/pkg/btrfs/io3_btree.go
+++ b/pkg/btrfs/io3_btree.go
@@ -19,9 +19,49 @@ import (
// - For .Item() callbacks, the last element will always have a
// NodeAddr of 0.
//
-// ex:
+// For example, given the tree structure
//
-// {-1, 0x01, 3}→{9, 0x02, 2}→{9, 0x03, 1}→{9, 0x04, 0}→{9, 0, 0}
+// [superblock]
+// |
+// | <------------------------------------------ pathElem={idx:-1, addr:0x01, lvl:3}
+// |
+// +[0x01]-----------+
+// | lvl=3 |
+// +-+-+-+-+-+-+-+-+-+
+// |1|2|3|4|5|6|7|8|9|
+// +---+---+---+---+-+
+// |
+// | <------------------------------ pathElem={idx:8, addr:0x02, lvl:2}
+// |
+// +[0x02]-----------+
+// | lvl=2 |
+// +-+-+-+-+-+-+-+-+-+
+// |1|2|3|4|5|6|7|8|9|
+// +---+---+---+---+-+
+// |
+// | <-------------------- pathElem={idx:7, addr:0x03, lvl:1}
+// |
+// +[0x03]-----------+
+// | lvl=1 |
+// +-+-+-+-+-+-+-+-+-+
+// |1|2|3|4|5|6|7|8|9|
+// +---+---+---+---+-+
+// |
+// | <---------------- pathElem={idx:4, addr:0x04, lvl:0}
+// |
+// +[0x04]-----------+
+// | lvl=0 |
+// +-+-+-+-+-+-+-+-+-+
+// |1|2|3|4|5|6|7|8|9|
+// +---+---+---+---+-+
+// |
+// | <--------------- pathElem={idx:5, addr:0, lvl:0}
+// |
+// [item]
+//
+// the path would be
+//
+// {-1, 0x01, 3}→{8, 0x02, 2}→{7, 0x03, 1}→{4, 0x04, 0}→{2, 0, 0}
type TreePath []TreePathElem
// A TreePathElem essentially represents a KeyPointer.
diff --git a/pkg/btrfs/io3_fs.go b/pkg/btrfs/io4_fs.go
index 75b973b..75b973b 100644
--- a/pkg/btrfs/io3_fs.go
+++ b/pkg/btrfs/io4_fs.go
diff --git a/pkg/btrfs/types_node.go b/pkg/btrfs/types_node.go
index 8aafc49..92f7513 100644
--- a/pkg/btrfs/types_node.go
+++ b/pkg/btrfs/types_node.go
@@ -49,6 +49,13 @@ var nodeFlagNames = []string{
func (f NodeFlags) Has(req NodeFlags) bool { return f&req == req }
func (f NodeFlags) String() string { return util.BitfieldString(f, nodeFlagNames, util.HexLower) }
+type BackrefRev uint8
+
+const (
+ OldBackrefRev = BackrefRev(iota)
+ MixedBackrefRev = BackrefRev(iota)
+)
+
// Node: main //////////////////////////////////////////////////////////////////////////////////////
type Node struct {
@@ -72,7 +79,7 @@ type NodeHeader struct {
MetadataUUID UUID `bin:"off=0x20, siz=0x10"`
Addr btrfsvol.LogicalAddr `bin:"off=0x30, siz=0x8"` // Logical address of this node
Flags NodeFlags `bin:"off=0x38, siz=0x7"`
- BackrefRev uint8 `bin:"off=0x3f, siz=0x1"`
+ BackrefRev BackrefRev `bin:"off=0x3f, siz=0x1"`
ChunkTreeUUID UUID `bin:"off=0x40, siz=0x10"`
Generation Generation `bin:"off=0x50, siz=0x8"`
Owner ObjID `bin:"off=0x58, siz=0x8"` // The ID of the tree that contains this node
@@ -347,7 +354,7 @@ func ReadNode[Addr ~int64](fs util.File[Addr], sb Superblock, addr Addr, laddrCB
// sanity checking
if nodeRef.Data.Head.MetadataUUID != sb.EffectiveMetadataUUID() {
- return nil, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, ErrNotANode)
+ return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, ErrNotANode)
}
stored := nodeRef.Data.Head.Checksum
diff --git a/pkg/btrfsmisc/walk.go b/pkg/btrfsmisc/walk.go
index 7d08394..0f3f811 100644
--- a/pkg/btrfsmisc/walk.go
+++ b/pkg/btrfsmisc/walk.go
@@ -30,6 +30,7 @@ type WalkFSHandler struct {
PreTree func(name string, laddr btrfsvol.LogicalAddr)
PostTree func(name string, laddr btrfsvol.LogicalAddr)
// Callbacks for nodes or smaller
+ UnsafeNodes bool
btrfs.TreeWalkHandler
}
@@ -73,15 +74,17 @@ func WalkFS(fs *btrfs.FS, cbs WalkFSHandler) {
return nil
}
- origNode := cbs.Node
- cbs.Node = func(path btrfs.TreePath, node *util.Ref[btrfsvol.LogicalAddr, btrfs.Node], err error) error {
- if err != nil {
- handleErr(path, err)
- }
- if node != nil && origNode != nil {
- return origNode(path, node, nil)
+ if !cbs.UnsafeNodes {
+ origNode := cbs.Node
+ cbs.Node = func(path btrfs.TreePath, node *util.Ref[btrfsvol.LogicalAddr, btrfs.Node], err error) error {
+ if err != nil {
+ handleErr(path, err)
+ }
+ if node != nil && origNode != nil {
+ return origNode(path, node, nil)
+ }
+ return nil
}
- return nil
}
treeName = "superblock"
@@ -92,39 +95,59 @@ func WalkFS(fs *btrfs.FS, cbs WalkFSHandler) {
}
treeName = "root tree"
- cbs.PreTree(treeName, superblock.Data.RootTree)
+ if cbs.PreTree != nil {
+ cbs.PreTree(treeName, superblock.Data.RootTree)
+ }
if err := fs.TreeWalk(superblock.Data.RootTree, cbs.TreeWalkHandler); err != nil {
handleErr(nil, err)
}
- cbs.PostTree(treeName, superblock.Data.RootTree)
+ if cbs.PostTree != nil {
+ cbs.PostTree(treeName, superblock.Data.RootTree)
+ }
treeName = "chunk tree"
- cbs.PreTree(treeName, superblock.Data.ChunkTree)
+ if cbs.PreTree != nil {
+ cbs.PreTree(treeName, superblock.Data.ChunkTree)
+ }
if err := fs.TreeWalk(superblock.Data.ChunkTree, cbs.TreeWalkHandler); err != nil {
handleErr(nil, err)
}
- cbs.PostTree(treeName, superblock.Data.ChunkTree)
+ if cbs.PostTree != nil {
+ cbs.PostTree(treeName, superblock.Data.ChunkTree)
+ }
treeName = "log tree"
- cbs.PreTree(treeName, superblock.Data.LogTree)
+ if cbs.PreTree != nil {
+ cbs.PreTree(treeName, superblock.Data.LogTree)
+ }
if err := fs.TreeWalk(superblock.Data.LogTree, cbs.TreeWalkHandler); err != nil {
handleErr(nil, err)
}
- cbs.PostTree(treeName, superblock.Data.LogTree)
+ if cbs.PostTree != nil {
+ cbs.PostTree(treeName, superblock.Data.LogTree)
+ }
treeName = "block group tree"
- cbs.PreTree(treeName, superblock.Data.BlockGroupRoot)
+ if cbs.PreTree != nil {
+ cbs.PreTree(treeName, superblock.Data.BlockGroupRoot)
+ }
if err := fs.TreeWalk(superblock.Data.BlockGroupRoot, cbs.TreeWalkHandler); err != nil {
handleErr(nil, err)
}
- cbs.PostTree(treeName, superblock.Data.BlockGroupRoot)
+ if cbs.PostTree != nil {
+ cbs.PostTree(treeName, superblock.Data.BlockGroupRoot)
+ }
for _, tree := range foundTrees {
treeName = tree.Name
- cbs.PreTree(treeName, tree.Root)
+ if cbs.PreTree != nil {
+ cbs.PreTree(treeName, tree.Root)
+ }
if err := fs.TreeWalk(tree.Root, cbs.TreeWalkHandler); err != nil {
handleErr(nil, err)
}
- cbs.PostTree(treeName, tree.Root)
+ if cbs.PostTree != nil {
+ cbs.PostTree(treeName, tree.Root)
+ }
}
}