From b589943af25661c140bacdc0afc2550e1e2db852 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 1 Jul 2022 00:31:57 -0600 Subject: add more callbacks to WalkFS --- cmd/btrfs-fsck/pass1.go | 27 +++++++++++++++------------ cmd/btrfs-fsck/pass2.go | 15 +++++++++------ pkg/btrfsmisc/walk.go | 33 ++++++++++++++++++++++++++------- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/cmd/btrfs-fsck/pass1.go b/cmd/btrfs-fsck/pass1.go index 6812c73..5188d65 100644 --- a/cmd/btrfs-fsck/pass1.go +++ b/cmd/btrfs-fsck/pass1.go @@ -22,19 +22,22 @@ func pass1(fs *btrfs.FS, superblock *util.Ref[btrfs.PhysicalAddr, btrfs.Superblo fmt.Printf("Pass 1: ... walking fs\n") visitedNodes := make(map[btrfs.LogicalAddr]struct{}) - btrfsmisc.WalkFS(fs, btrfs.WalkTreeHandler{ - Node: func(path btrfs.WalkTreePath, node *util.Ref[btrfs.LogicalAddr, btrfs.Node], err error) error { - if err != nil { - err = fmt.Errorf("%v: %w", path, err) - fmt.Printf("Pass 1: ... walk fs: error: %v\n", err) - } - if node != nil { - visitedNodes[node.Addr] = struct{}{} - } - return err + btrfsmisc.WalkFS(fs, btrfsmisc.WalkFSHandler{ + WalkTreeHandler: btrfs.WalkTreeHandler{ + Node: func(path btrfs.WalkTreePath, node *util.Ref[btrfs.LogicalAddr, btrfs.Node], err error) error { + if err != nil { + err = fmt.Errorf("%v: %w", path, err) + fmt.Printf("Pass 1: ... walk fs: error: %v\n", err) + } + if node != nil { + visitedNodes[node.Addr] = struct{}{} + } + return err + }, + }, + Err: func(err error) { + fmt.Printf("Pass 1: ... walk fs: error: %v\n", err) }, - }, func(err error) { - fmt.Printf("Pass 1: ... walk fs: error: %v\n", err) }) fsFoundNodes := make(map[btrfs.LogicalAddr]struct{}) diff --git a/cmd/btrfs-fsck/pass2.go b/cmd/btrfs-fsck/pass2.go index acea740..7970cca 100644 --- a/cmd/btrfs-fsck/pass2.go +++ b/cmd/btrfs-fsck/pass2.go @@ -13,13 +13,16 @@ func pass2(fs *btrfs.FS, foundNodes map[btrfs.LogicalAddr]struct{}) { fmt.Printf("\nPass 2: orphaned nodes\n") visitedNodes := make(map[btrfs.LogicalAddr]struct{}) - btrfsmisc.WalkFS(fs, btrfs.WalkTreeHandler{ - Node: func(path btrfs.WalkTreePath, node *util.Ref[btrfs.LogicalAddr, btrfs.Node], err error) error { - visitedNodes[node.Addr] = struct{}{} - return nil + btrfsmisc.WalkFS(fs, btrfsmisc.WalkFSHandler{ + WalkTreeHandler: btrfs.WalkTreeHandler{ + Node: func(path btrfs.WalkTreePath, node *util.Ref[btrfs.LogicalAddr, btrfs.Node], err error) error { + visitedNodes[node.Addr] = struct{}{} + return nil + }, + }, + Err: func(err error) { + fmt.Printf("Pass 2: walk FS: error: %v\n", err) }, - }, func(err error) { - fmt.Printf("Pass 2: walk FS: error: %v\n", err) }) orphanedNodes := make(map[btrfs.LogicalAddr]int) diff --git a/pkg/btrfsmisc/walk.go b/pkg/btrfsmisc/walk.go index fc0edbc..a82bd5f 100644 --- a/pkg/btrfsmisc/walk.go +++ b/pkg/btrfsmisc/walk.go @@ -23,13 +23,22 @@ func (e WalkErr) Error() string { return fmt.Sprintf("%v: %v: %v", e.TreeName, e.Path, e.Err) } +type WalkFSHandler struct { + Err func(error) + // Callbacks for entire trees + PreTree func(name string, laddr btrfs.LogicalAddr) + PostTree func(name string, laddr btrfs.LogicalAddr) + // Callbacks for nodes or smaller + btrfs.WalkTreeHandler +} + // WalkFS walks all trees in a *btrfs.FS. Rather than returning an // error, it calls errCb each time an error is encountered. The error // will always be of type WalkErr. -func WalkFS(fs *btrfs.FS, cbs btrfs.WalkTreeHandler, errCb func(error)) { +func WalkFS(fs *btrfs.FS, cbs WalkFSHandler) { var treeName string handleErr := func(path btrfs.WalkTreePath, err error) { - errCb(WalkErr{ + cbs.Err(WalkErr{ TreeName: treeName, Path: path, Err: err, @@ -82,29 +91,39 @@ func WalkFS(fs *btrfs.FS, cbs btrfs.WalkTreeHandler, errCb func(error)) { } treeName = "root tree" - if err := fs.WalkTree(superblock.Data.RootTree, cbs); err != nil { + cbs.PreTree(treeName, superblock.Data.RootTree) + if err := fs.WalkTree(superblock.Data.RootTree, cbs.WalkTreeHandler); err != nil { handleErr(nil, err) } + cbs.PostTree(treeName, superblock.Data.RootTree) treeName = "chunk tree" - if err := fs.WalkTree(superblock.Data.ChunkTree, cbs); err != nil { + cbs.PreTree(treeName, superblock.Data.ChunkTree) + if err := fs.WalkTree(superblock.Data.ChunkTree, cbs.WalkTreeHandler); err != nil { handleErr(nil, err) } + cbs.PostTree(treeName, superblock.Data.ChunkTree) treeName = "log tree" - if err := fs.WalkTree(superblock.Data.LogTree, cbs); err != nil { + cbs.PreTree(treeName, superblock.Data.LogTree) + if err := fs.WalkTree(superblock.Data.LogTree, cbs.WalkTreeHandler); err != nil { handleErr(nil, err) } + cbs.PostTree(treeName, superblock.Data.LogTree) treeName = "block group tree" - if err := fs.WalkTree(superblock.Data.BlockGroupRoot, cbs); err != nil { + cbs.PreTree(treeName, superblock.Data.BlockGroupRoot) + if err := fs.WalkTree(superblock.Data.BlockGroupRoot, cbs.WalkTreeHandler); err != nil { handleErr(nil, err) } + cbs.PostTree(treeName, superblock.Data.BlockGroupRoot) for _, tree := range foundTrees { treeName = tree.Name - if err := fs.WalkTree(tree.Root, cbs); err != nil { + cbs.PreTree(treeName, tree.Root) + if err := fs.WalkTree(tree.Root, cbs.WalkTreeHandler); err != nil { handleErr(nil, err) } + cbs.PostTree(treeName, tree.Root) } } -- cgit v1.2.3-2-g168b