diff options
-rw-r--r-- | cmd/btrfs-fsck/main.go | 2 | ||||
-rw-r--r-- | cmd/btrfs-fsck/pass1.go | 8 | ||||
-rw-r--r-- | cmd/btrfs-fsck/pass2.go | 5 | ||||
-rw-r--r-- | cmd/btrfs-rec/inspect_lstrees.go | 4 | ||||
-rw-r--r-- | lib/btrfs/io2_lv.go | 10 | ||||
-rw-r--r-- | lib/btrfs/io3_btree.go | 41 | ||||
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/print_tree.go | 2 | ||||
-rw-r--r-- | lib/btrfsprogs/btrfsrepair/clearnodes.go | 2 | ||||
-rw-r--r-- | lib/btrfsprogs/btrfsutil/walk.go | 4 |
9 files changed, 57 insertions, 21 deletions
diff --git a/cmd/btrfs-fsck/main.go b/cmd/btrfs-fsck/main.go index fd9eb1b..e4e2b25 100644 --- a/cmd/btrfs-fsck/main.go +++ b/cmd/btrfs-fsck/main.go @@ -37,7 +37,7 @@ func Main(ctx context.Context, imgfilenames ...string) (err error) { return err } - pass2(fs, foundNodes) + pass2(ctx, fs, foundNodes) return nil } diff --git a/cmd/btrfs-fsck/pass1.go b/cmd/btrfs-fsck/pass1.go index e41694a..a625193 100644 --- a/cmd/btrfs-fsck/pass1.go +++ b/cmd/btrfs-fsck/pass1.go @@ -22,7 +22,7 @@ func pass1(ctx context.Context, fs *btrfs.FS, superblock *btrfs.Superblock) (map fmt.Printf("Pass 1: ... walking fs\n") visitedNodes := make(map[btrfsvol.LogicalAddr]struct{}) - btrfsutil.WalkAllTrees(fs, btrfsutil.WalkAllTreesHandler{ + btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ TreeWalkHandler: btrfs.TreeWalkHandler{ Node: func(path btrfs.TreePath, node *util.Ref[btrfsvol.LogicalAddr, btrfs.Node]) error { visitedNodes[node.Addr] = struct{}{} @@ -57,12 +57,12 @@ func pass1(ctx context.Context, fs *btrfs.FS, superblock *btrfs.Superblock) (map btrfsinspect.PrintPhysicalSpace(os.Stdout, fs) fmt.Printf("Pass 1: ... writing re-constructed chunks\n") - pass1WriteReconstructedChunks(fs) + pass1WriteReconstructedChunks(ctx, fs) return fsFoundNodes, nil } -func pass1WriteReconstructedChunks(fs *btrfs.FS) { +func pass1WriteReconstructedChunks(ctx context.Context, fs *btrfs.FS) { superblock, _ := fs.Superblock() // FIXME(lukeshu): OK, so this just assumes that all the @@ -145,7 +145,7 @@ func pass1WriteReconstructedChunks(fs *btrfs.FS) { fmt.Printf("Pass 1: ... write new node: error: %v\n", err) } - if err := fs.ReInit(); err != nil { + if err := fs.ReInit(ctx); err != nil { fmt.Printf("Pass 1: ... re-init mappings: %v\n", err) } diff --git a/cmd/btrfs-fsck/pass2.go b/cmd/btrfs-fsck/pass2.go index 78bd2e5..ef55d93 100644 --- a/cmd/btrfs-fsck/pass2.go +++ b/cmd/btrfs-fsck/pass2.go @@ -5,6 +5,7 @@ package main import ( + "context" "fmt" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" @@ -13,11 +14,11 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/util" ) -func pass2(fs *btrfs.FS, foundNodes map[btrfsvol.LogicalAddr]struct{}) { +func pass2(ctx context.Context, fs *btrfs.FS, foundNodes map[btrfsvol.LogicalAddr]struct{}) { fmt.Printf("\nPass 2: orphaned nodes\n") visitedNodes := make(map[btrfsvol.LogicalAddr]struct{}) - btrfsutil.WalkAllTrees(fs, btrfsutil.WalkAllTreesHandler{ + btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ TreeWalkHandler: btrfs.TreeWalkHandler{ Node: func(path btrfs.TreePath, node *util.Ref[btrfsvol.LogicalAddr, btrfs.Node]) error { visitedNodes[node.Addr] = struct{}{} diff --git a/cmd/btrfs-rec/inspect_lstrees.go b/cmd/btrfs-rec/inspect_lstrees.go index 0a98369..590ec23 100644 --- a/cmd/btrfs-rec/inspect_lstrees.go +++ b/cmd/btrfs-rec/inspect_lstrees.go @@ -26,10 +26,10 @@ func init() { Short: "A brief view what types of items are in each tree", Args: cliutil.WrapPositionalArgs(cobra.NoArgs), }, - RunE: func(fs *btrfs.FS, _ *cobra.Command, _ []string) error { + RunE: func(fs *btrfs.FS, cmd *cobra.Command, _ []string) error { var treeErrCnt int var treeItemCnt map[btrfsitem.Type]int - btrfsutil.WalkAllTrees(fs, btrfsutil.WalkAllTreesHandler{ + btrfsutil.WalkAllTrees(cmd.Context(), fs, btrfsutil.WalkAllTreesHandler{ PreTree: func(name string, treeID btrfs.ObjID) { treeErrCnt = 0 treeItemCnt = make(map[btrfsitem.Type]int) diff --git a/lib/btrfs/io2_lv.go b/lib/btrfs/io2_lv.go index eee58d5..b3f9276 100644 --- a/lib/btrfs/io2_lv.go +++ b/lib/btrfs/io2_lv.go @@ -38,7 +38,7 @@ func (fs *FS) AddDevice(ctx context.Context, dev *Device) error { } fs.cacheSuperblocks = nil fs.cacheSuperblock = nil - if err := fs.initDev(*sb); err != nil { + if err := fs.initDev(ctx, *sb); err != nil { dlog.Errorf(ctx, "error: AddDevice: %q: %v", dev.Name(), err) } return nil @@ -133,21 +133,21 @@ func (fs *FS) Superblock() (*Superblock, error) { return &sbs[0].Data, nil } -func (fs *FS) ReInit() error { +func (fs *FS) ReInit(ctx context.Context) error { fs.LV.ClearMappings() for _, dev := range fs.LV.PhysicalVolumes() { sb, err := dev.Superblock() if err != nil { return fmt.Errorf("file %q: %w", dev.Name(), err) } - if err := fs.initDev(*sb); err != nil { + if err := fs.initDev(ctx, *sb); err != nil { return fmt.Errorf("file %q: %w", dev.Name(), err) } } return nil } -func (fs *FS) initDev(sb Superblock) error { +func (fs *FS) initDev(ctx context.Context, sb Superblock) error { syschunks, err := sb.ParseSysChunkArray() if err != nil { return err @@ -160,7 +160,7 @@ func (fs *FS) initDev(sb Superblock) error { } } var errs derror.MultiError - fs.TreeWalk(CHUNK_TREE_OBJECTID, + fs.TreeWalk(ctx, CHUNK_TREE_OBJECTID, func(err *TreeError) { errs = append(errs, err) }, diff --git a/lib/btrfs/io3_btree.go b/lib/btrfs/io3_btree.go index 1cb1d74..5bbb8d1 100644 --- a/lib/btrfs/io3_btree.go +++ b/lib/btrfs/io3_btree.go @@ -5,6 +5,7 @@ package btrfs import ( + "context" "fmt" "io" iofs "io/fs" @@ -18,6 +19,9 @@ import ( ) type Trees interface { + // Canceling the Context causes TreeWalk to return early; no + // values from the Context are used. + // // The lifecycle of callbacks is: // // 001 .PreNode() @@ -31,7 +35,7 @@ type Trees interface { // else: // 004 .Item() (or .BadItem()) // 007 .PostNode() - TreeWalk(treeID ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) + TreeWalk(ctx context.Context, treeID ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) TreeLookup(treeID ObjID, key Key) (Item, error) TreeSearch(treeID ObjID, fn func(Key) int) (Item, error) @@ -247,7 +251,7 @@ type TreeWalkHandler struct { BadItem func(TreePath, Item) error } -func (fs *FS) TreeWalk(treeID ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) { +func (fs *FS) TreeWalk(ctx context.Context, treeID ObjID, errHandle func(*TreeError), cbs TreeWalkHandler) { path := TreePath{ TreeID: treeID, } @@ -261,10 +265,13 @@ func (fs *FS) TreeWalk(treeID ObjID, errHandle func(*TreeError), cbs TreeWalkHan NodeAddr: rootInfo.RootNode, NodeLevel: rootInfo.Level, }) - fs.treeWalk(path, errHandle, cbs) + fs.treeWalk(ctx, path, errHandle, cbs) } -func (fs *FS) treeWalk(path TreePath, errHandle func(*TreeError), cbs TreeWalkHandler) { +func (fs *FS) treeWalk(ctx context.Context, path TreePath, errHandle func(*TreeError), cbs TreeWalkHandler) { + if ctx.Err() != nil { + return + } if path.Nodes[len(path.Nodes)-1].NodeAddr == 0 { return } @@ -273,8 +280,14 @@ func (fs *FS) treeWalk(path TreePath, errHandle func(*TreeError), cbs TreeWalkHa if err := cbs.PreNode(path); err != nil { errHandle(&TreeError{Path: path, Err: err}) } + if ctx.Err() != nil { + return + } } node, err := fs.readNodeAtLevel(path.Nodes[len(path.Nodes)-1].NodeAddr, path.Nodes[len(path.Nodes)-1].NodeLevel) + if ctx.Err() != nil { + return + } if err != nil && node != nil && cbs.BadNode != nil { // opportunity to fix the node err = cbs.BadNode(path, node, err) @@ -288,6 +301,9 @@ func (fs *FS) treeWalk(path TreePath, errHandle func(*TreeError), cbs TreeWalkHa } } } + if ctx.Err() != nil { + return + } if node != nil { for i, item := range node.Data.BodyInternal { itemPath := path.Append(TreePathElem{ @@ -299,12 +315,18 @@ func (fs *FS) treeWalk(path TreePath, errHandle func(*TreeError), cbs TreeWalkHa if err := cbs.PreKeyPointer(itemPath, item); err != nil { errHandle(&TreeError{Path: itemPath, Err: err}) } + if ctx.Err() != nil { + return + } } - fs.treeWalk(itemPath, errHandle, cbs) + fs.treeWalk(ctx, itemPath, errHandle, cbs) if cbs.PostKeyPointer != nil { if err := cbs.PostKeyPointer(itemPath, item); err != nil { errHandle(&TreeError{Path: itemPath, Err: err}) } + if ctx.Err() != nil { + return + } } } for i, item := range node.Data.BodyLeaf { @@ -318,12 +340,18 @@ func (fs *FS) treeWalk(path TreePath, errHandle func(*TreeError), cbs TreeWalkHa if err := cbs.BadItem(itemPath, item); err != nil { errHandle(&TreeError{Path: itemPath, Err: err}) } + if ctx.Err() != nil { + return + } } } else { if cbs.Item != nil { if err := cbs.Item(itemPath, item); err != nil { errHandle(&TreeError{Path: itemPath, Err: err}) } + if ctx.Err() != nil { + return + } } } } @@ -332,6 +360,9 @@ func (fs *FS) treeWalk(path TreePath, errHandle func(*TreeError), cbs TreeWalkHa if err := cbs.PostNode(path, node); err != nil { errHandle(&TreeError{Path: path, Err: err}) } + if ctx.Err() != nil { + return + } } } diff --git a/lib/btrfsprogs/btrfsinspect/print_tree.go b/lib/btrfsprogs/btrfsinspect/print_tree.go index 6c4f550..142f5e5 100644 --- a/lib/btrfsprogs/btrfsinspect/print_tree.go +++ b/lib/btrfsprogs/btrfsinspect/print_tree.go @@ -44,6 +44,7 @@ func DumpTrees(ctx context.Context, out io.Writer, fs *btrfs.FS) { printTree(ctx, out, fs, btrfs.BLOCK_GROUP_TREE_OBJECTID) } fs.TreeWalk( + ctx, btrfs.ROOT_TREE_OBJECTID, func(err *btrfs.TreeError) { dlog.Error(ctx, err) @@ -343,6 +344,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfs.Ob } handlers.BadItem = handlers.Item fs.TreeWalk( + ctx, treeID, func(err *btrfs.TreeError) { dlog.Error(ctx, err) diff --git a/lib/btrfsprogs/btrfsrepair/clearnodes.go b/lib/btrfsprogs/btrfsrepair/clearnodes.go index dbe1c3a..b38a333 100644 --- a/lib/btrfsprogs/btrfsrepair/clearnodes.go +++ b/lib/btrfsprogs/btrfsrepair/clearnodes.go @@ -21,7 +21,7 @@ func ClearBadNodes(ctx context.Context, fs *btrfs.FS) error { var uuidsInited bool var metadataUUID, chunkTreeUUID btrfs.UUID - btrfsutil.WalkAllTrees(fs, btrfsutil.WalkAllTreesHandler{ + btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ Err: func(err *btrfsutil.WalkError) { dlog.Error(ctx, err) }, diff --git a/lib/btrfsprogs/btrfsutil/walk.go b/lib/btrfsprogs/btrfsutil/walk.go index d2b6367..c597e5e 100644 --- a/lib/btrfsprogs/btrfsutil/walk.go +++ b/lib/btrfsprogs/btrfsutil/walk.go @@ -5,6 +5,7 @@ package btrfsutil import ( + "context" "fmt" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" @@ -34,7 +35,7 @@ type WalkAllTreesHandler struct { // WalkAllTrees 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 WalkError. -func WalkAllTrees(fs *btrfs.FS, cbs WalkAllTreesHandler) { +func WalkAllTrees(ctx context.Context, fs *btrfs.FS, cbs WalkAllTreesHandler) { var treeName string trees := []struct { @@ -83,6 +84,7 @@ func WalkAllTrees(fs *btrfs.FS, cbs WalkAllTreesHandler) { cbs.PreTree(treeName, tree.ID) } fs.TreeWalk( + ctx, tree.ID, func(err *btrfs.TreeError) { cbs.Err(&WalkError{TreeName: treeName, Err: err}) }, cbs.TreeWalkHandler, |