diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-08-30 21:39:17 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-08-30 23:39:57 -0600 |
commit | ecb13992b042460889a908f32a0505dda5fe206f (patch) | |
tree | 83aff65c7cb04650f0068134aa798805f4a9c314 /lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_classify.go | |
parent | a9d6b935eef8124efbcfd2c9569fbccd932051de (diff) |
wip rework rebuildnodes
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_classify.go')
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_classify.go | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_classify.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_classify.go index aa90582..e171e49 100644 --- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_classify.go +++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/s2_classify.go @@ -6,6 +6,7 @@ package rebuildnodes import ( "context" + "errors" iofs "io/fs" "github.com/datawire/dlib/dlog" @@ -47,6 +48,32 @@ func classifyNodes(ctx context.Context, fs _FS, scanResults btrfsinspect.ScanDev } } + var potentialRoot btrfsvol.LogicalAddr // zero for non-lost nodes, non-zero for lost nodes + nodeHandler := func(path btrfstree.TreePath, nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node], err error) error { + if err != nil && (errors.Is(err, btrfstree.ErrNotANode) || errors.As(err, new(*btrfstree.IOError))) { + badNodes = append(badNodes, badNode{ + Err: err.Error(), + Path: path.DeepCopy(), + }) + return err + } + addr := path.Node(-1).ToNodeAddr + visitedNodes[addr] = struct{}{} + if potentialRoot != 0 { + // lost node + if addr != potentialRoot { + delete(orphanedNodes, addr) + } + // TODO: Compare `nodeRef.Data.Head.Owner` and `path.Node(-1).FromTree` to + // maybe reconstruct a missing root item. This is a sort of catch-22; we + // trust this data less because lost nodes may be discarded and not just + // lost, but non-lost nodes will never have a missing root item, so lost + // nodes are all we have to work with on this. + } + progress() + return nil + } + walkHandler := btrfstree.TreeWalkHandler{ PreNode: func(path btrfstree.TreePath) error { addr := path.Node(-1).ToNodeAddr @@ -57,18 +84,11 @@ func classifyNodes(ctx context.Context, fs _FS, scanResults btrfsinspect.ScanDev } return nil }, - Node: func(path btrfstree.TreePath, _ *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error { - addr := path.Node(-1).ToNodeAddr - visitedNodes[addr] = struct{}{} - progress() - return nil + Node: func(path btrfstree.TreePath, nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error { + return nodeHandler(path, nodeRef, nil) }, - BadNode: func(path btrfstree.TreePath, _ *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node], err error) error { - badNodes = append(badNodes, badNode{ - Err: err.Error(), - Path: path.DeepCopy(), - }) - return err + BadNode: func(path btrfstree.TreePath, nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node], err error) error { + return nodeHandler(path, nodeRef, err) }, } @@ -96,16 +116,7 @@ func classifyNodes(ctx context.Context, fs _FS, scanResults btrfsinspect.ScanDev dlog.Infof(ctx, "... (finished processing %v attached nodes, proceeding to process %v lost nodes, for a total of %v)", len(visitedNodes), len(orphanedNodes), len(visitedNodes)+len(orphanedNodes)) - for _, potentialRoot := range maps.SortedKeys(orphanedNodes) { - walkHandler.Node = func(path btrfstree.TreePath, _ *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error { - addr := path.Node(-1).ToNodeAddr - if addr != potentialRoot { - delete(orphanedNodes, addr) - } - visitedNodes[addr] = struct{}{} - progress() - return nil - } + for _, potentialRoot = range maps.SortedKeys(orphanedNodes) { walkFromNode(ctx, fs, potentialRoot, func(err *btrfstree.TreeError) { // do nothing |