diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-07-07 02:51:57 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-07-08 00:16:01 -0600 |
commit | 22c32850798c264b6a20539b9cd1699228368ce9 (patch) | |
tree | eea4fe596bc584cba96245d8bfbe92503d1a4c61 /pkg | |
parent | fa98ff69f24545e1836201c30ab43cc2527c52e3 (diff) |
write btrfs-clear-bad-nodes
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/btrfs/io3_btree.go | 44 | ||||
-rw-r--r-- | pkg/btrfs/io4_fs.go (renamed from pkg/btrfs/io3_fs.go) | 0 | ||||
-rw-r--r-- | pkg/btrfs/types_node.go | 11 | ||||
-rw-r--r-- | pkg/btrfsmisc/walk.go | 59 |
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) + } } } |