From 4264394fae41b08026a187b7da9e9787927863ab Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Mar 2023 19:31:50 -0700 Subject: cmd/btrfs-rec: main.go: Don't let lines get too long --- cmd/btrfs-rec/main.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'cmd') diff --git a/cmd/btrfs-rec/main.go b/cmd/btrfs-rec/main.go index d221c3d..e6305da 100644 --- a/cmd/btrfs-rec/main.go +++ b/cmd/btrfs-rec/main.go @@ -86,10 +86,12 @@ func main() { globalFlags.logLevel.Level = dlog.LogLevelInfo argparser.PersistentFlags().Var(&globalFlags.logLevel, "verbosity", "set the verbosity") - argparser.PersistentFlags().StringArrayVar(&globalFlags.pvs, "pv", nil, "open the file `physical_volume` as part of the filesystem") + argparser.PersistentFlags().StringArrayVar(&globalFlags.pvs, "pv", nil, + "open the file `physical_volume` as part of the filesystem") noError(argparser.MarkPersistentFlagFilename("pv")) - argparser.PersistentFlags().StringVar(&globalFlags.mappings, "mappings", "", "load chunk/dev-extent/blockgroup data from external JSON file `mappings.json`") + argparser.PersistentFlags().StringVar(&globalFlags.mappings, "mappings", "", + "load chunk/dev-extent/blockgroup data from external JSON file `mappings.json`") noError(argparser.MarkPersistentFlagFilename("mappings")) globalFlags.stopProfiling = profile.AddProfileFlags(argparser.PersistentFlags(), "profile.") -- cgit v1.2.3-2-g168b From 1ba83231195ea3b78ce545f4518f70c74819345b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 31 Mar 2023 10:28:02 -0600 Subject: btrfsutil: Add a ReadGraph function, rebuildtrees: Clean up scan to match --- cmd/btrfs-rec/inspect/rebuildtrees/scan.go | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'cmd') diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/scan.go b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go index a6f9c7a..f266dab 100644 --- a/cmd/btrfs-rec/inspect/rebuildtrees/scan.go +++ b/cmd/btrfs-rec/inspect/rebuildtrees/scan.go @@ -41,31 +41,35 @@ type ScanDevicesResult struct { Sizes map[btrfsutil.ItemPtr]SizeAndErr // EXTENT_CSUM and EXTENT_DATA } -func ScanDevices(ctx context.Context, fs *btrfs.FS, nodeList []btrfsvol.LogicalAddr) (ScanDevicesResult, error) { +func ScanDevices(_ctx context.Context, fs *btrfs.FS, nodeList []btrfsvol.LogicalAddr) (ScanDevicesResult, error) { + // read-superblock ///////////////////////////////////////////////////////////// + ctx := dlog.WithField(_ctx, "btrfs.inspect.rebuild-trees.read.substep", "read-superblock") dlog.Info(ctx, "Reading superblock...") sb, err := fs.Superblock() if err != nil { return ScanDevicesResult{}, err } - dlog.Infof(ctx, "Reading node data from FS...") - - var stats textui.Portion[int] - stats.D = len(nodeList) - progressWriter := textui.NewProgress[textui.Portion[int]]( - dlog.WithField(ctx, "btrfs.inspect.rebuild-trees.read.substep", "read-nodes"), - dlog.LogLevelInfo, textui.Tunable(1*time.Second)) - + // read-roots ////////////////////////////////////////////////////////////////// + ctx = dlog.WithField(_ctx, "btrfs.inspect.rebuild-trees.read.substep", "read-roots") ret := ScanDevicesResult{ Superblock: *sb, Graph: btrfsutil.NewGraph(ctx, *sb), - Flags: make(map[btrfsutil.ItemPtr]FlagsAndErr), Names: make(map[btrfsutil.ItemPtr][]byte), Sizes: make(map[btrfsutil.ItemPtr]SizeAndErr), } + // read-nodes ////////////////////////////////////////////////////////////////// + ctx = dlog.WithField(_ctx, "btrfs.inspect.rebuild-trees.read.substep", "read-nodes") + dlog.Infof(ctx, "Reading node data from FS...") + var stats textui.Portion[int] + stats.D = len(nodeList) + progressWriter := textui.NewProgress[textui.Portion[int]]( + ctx, + dlog.LogLevelInfo, + textui.Tunable(1*time.Second)) progressWriter.Set(stats) for _, laddr := range nodeList { if err := ctx.Err(); err != nil { @@ -78,11 +82,8 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, nodeList []btrfsvol.LogicalA fs.ReleaseNode(node) return ScanDevicesResult{}, err } - ret.insertNode(node) - fs.ReleaseNode(node) - stats.N++ progressWriter.Set(stats) } @@ -92,7 +93,8 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, nodeList []btrfsvol.LogicalA progressWriter.Done() dlog.Info(ctx, "... done reading node data") - ctx = dlog.WithField(ctx, "btrfs.inspect.rebuild-trees.read.substep", "check") + // check /////////////////////////////////////////////////////////////////////// + ctx = dlog.WithField(_ctx, "btrfs.inspect.rebuild-trees.read.substep", "check") if err := ret.Graph.FinalCheck(ctx, fs); err != nil { return ScanDevicesResult{}, err } -- cgit v1.2.3-2-g168b From c1578391cc2089cd224fd8325c333038e0ba7b7b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 31 Mar 2023 18:01:47 -0600 Subject: maps: Add HasKey and HaveAnyKeysInCommon functions, use them --- cmd/btrfs-rec/inspect/rebuildmappings/process.go | 2 +- cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go | 22 +++++----------------- 2 files changed, 6 insertions(+), 18 deletions(-) (limited to 'cmd') diff --git a/cmd/btrfs-rec/inspect/rebuildmappings/process.go b/cmd/btrfs-rec/inspect/rebuildmappings/process.go index 7a49cc6..2e694b5 100644 --- a/cmd/btrfs-rec/inspect/rebuildmappings/process.go +++ b/cmd/btrfs-rec/inspect/rebuildmappings/process.go @@ -38,7 +38,7 @@ func RebuildMappings(ctx context.Context, fs *btrfs.FS, scanResults ScanDevicesR devIDs := maps.SortedKeys(scanResults) devices := fs.LV.PhysicalVolumes() for _, devID := range devIDs { - if _, ok := devices[devID]; !ok { + if !maps.HasKey(devices, devID) { return fmt.Errorf("device ID %v mentioned in scan results is not part of the filesystem", devID) } devResults := scanResults[devID] diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go index 0d25ac3..2160969 100644 --- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go +++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go @@ -517,24 +517,12 @@ func (o *rebuilder) resolveTreeAugments(ctx context.Context, treeID btrfsprim.Ob //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// func (queue *treeAugmentQueue) has(wantKey want) bool { - if queue != nil { - if queue.zero != nil { - if _, ok := queue.zero[wantKey]; ok { - return true - } - } - if queue.single != nil { - if _, ok := queue.single[wantKey]; ok { - return true - } - } - if queue.multi != nil { - if _, ok := queue.multi[wantKey]; ok { - return true - } - } + if queue == nil { + return false } - return false + return (queue.zero != nil && maps.HasKey(queue.zero, wantKey)) || + (queue.single != nil && maps.HasKey(queue.single, wantKey)) || + (queue.multi != nil && maps.HasKey(queue.multi, wantKey)) } func (queue *treeAugmentQueue) store(wantKey want, choices containers.Set[btrfsvol.LogicalAddr]) { -- cgit v1.2.3-2-g168b From 6b8c24fb78f0face6532c1170ff0dca46dd56223 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 1 Apr 2023 21:10:35 -0600 Subject: cmd/btrfs-rec: Have RebuiltForrest be opt-in on the CLI --- cmd/btrfs-rec/main.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/btrfs-rec/main.go b/cmd/btrfs-rec/main.go index e6305da..49a9649 100644 --- a/cmd/btrfs-rec/main.go +++ b/cmd/btrfs-rec/main.go @@ -48,7 +48,9 @@ var ( var globalFlags struct { logLevel textui.LogLevelFlag pvs []string + mappings string + rebuild bool stopProfiling profile.StopFunc @@ -94,6 +96,9 @@ func main() { "load chunk/dev-extent/blockgroup data from external JSON file `mappings.json`") noError(argparser.MarkPersistentFlagFilename("mappings")) + argparser.PersistentFlags().BoolVar(&globalFlags.rebuild, "rebuild", false, + "attempt to rebuild broken btrees when reading") + globalFlags.stopProfiling = profile.AddProfileFlags(argparser.PersistentFlags(), "profile.") globalFlags.openFlag = os.O_RDONLY @@ -180,6 +185,10 @@ func runWithRawFS(runE func(*btrfs.FS, *cobra.Command, []string) error) func(*co func runWithReadableFS(runE func(btrfs.ReadableFS, *cobra.Command, []string) error) func(*cobra.Command, []string) error { return runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error { - return runE(btrfsutil.NewOldRebuiltForrest(fs), cmd, args) + var rfs btrfs.ReadableFS = fs + if globalFlags.rebuild { + rfs = btrfsutil.NewOldRebuiltForrest(fs) + } + return runE(rfs, cmd, args) }) } -- cgit v1.2.3-2-g168b From bc94e6dbf6e9212820615a3d3f3e4542693351a6 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Mar 2023 19:31:50 -0700 Subject: cmd/btrfs-rec: ls-trees: Use runWithReadableFS --- cmd/btrfs-rec/inspect_lstrees.go | 13 +------------ cmd/btrfs-rec/main.go | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) (limited to 'cmd') diff --git a/cmd/btrfs-rec/inspect_lstrees.go b/cmd/btrfs-rec/inspect_lstrees.go index 24622b4..cb7bef8 100644 --- a/cmd/btrfs-rec/inspect_lstrees.go +++ b/cmd/btrfs-rec/inspect_lstrees.go @@ -33,20 +33,9 @@ func init() { "If no --node-list is given, then a slow sector-by-sector scan " + "will be used to find all lost+found nodes.", Args: cliutil.WrapPositionalArgs(cobra.NoArgs), - RunE: runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, _ []string) error { + RunE: runWithReadableFSAndNodeList(&nodeListFilename, func(fs btrfs.ReadableFS, nodeList []btrfsvol.LogicalAddr, cmd *cobra.Command, _ []string) error { ctx := cmd.Context() - var nodeList []btrfsvol.LogicalAddr - var err error - if nodeListFilename != "" { - nodeList, err = readJSONFile[[]btrfsvol.LogicalAddr](ctx, nodeListFilename) - } else { - nodeList, err = btrfsutil.ListNodes(ctx, fs) - } - if err != nil { - return err - } - var treeErrCnt int var treeItemCnt map[btrfsitem.Type]int flush := func() { diff --git a/cmd/btrfs-rec/main.go b/cmd/btrfs-rec/main.go index 49a9649..8d3193a 100644 --- a/cmd/btrfs-rec/main.go +++ b/cmd/btrfs-rec/main.go @@ -192,3 +192,25 @@ func runWithReadableFS(runE func(btrfs.ReadableFS, *cobra.Command, []string) err return runE(rfs, cmd, args) }) } + +func runWithReadableFSAndNodeList(nodeListFilename *string, runE func(btrfs.ReadableFS, []btrfsvol.LogicalAddr, *cobra.Command, []string) error) func(*cobra.Command, []string) error { + return runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error { + var nodeList []btrfsvol.LogicalAddr + var err error + if *nodeListFilename != "" { + nodeList, err = readJSONFile[[]btrfsvol.LogicalAddr](cmd.Context(), *nodeListFilename) + } else { + nodeList, err = btrfsutil.ListNodes(cmd.Context(), fs) + } + if err != nil { + return err + } + + var rfs btrfs.ReadableFS = fs + if globalFlags.rebuild { + rfs = btrfsutil.NewOldRebuiltForrest(fs) + } + + return runE(rfs, nodeList, cmd, args) + }) +} -- cgit v1.2.3-2-g168b From 5d2729a4e15dca6e22187cd5de272a2a2d191131 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 10 Mar 2023 19:31:50 -0700 Subject: cmd/btrfs-rec: Move --node-list to be a global flag --- cmd/btrfs-rec/inspect_lstrees.go | 12 +++------ cmd/btrfs-rec/inspect_rebuildtrees.go | 24 +++--------------- cmd/btrfs-rec/main.go | 48 +++++++++++++++++++++++++---------- 3 files changed, 41 insertions(+), 43 deletions(-) (limited to 'cmd') diff --git a/cmd/btrfs-rec/inspect_lstrees.go b/cmd/btrfs-rec/inspect_lstrees.go index cb7bef8..decb75c 100644 --- a/cmd/btrfs-rec/inspect_lstrees.go +++ b/cmd/btrfs-rec/inspect_lstrees.go @@ -25,15 +25,14 @@ import ( ) func init() { - var nodeListFilename string - cmd := &cobra.Command{ + inspectors.AddCommand(&cobra.Command{ Use: "ls-trees", Short: "A brief view what types of items are in each tree", Long: "" + "If no --node-list is given, then a slow sector-by-sector scan " + "will be used to find all lost+found nodes.", Args: cliutil.WrapPositionalArgs(cobra.NoArgs), - RunE: runWithReadableFSAndNodeList(&nodeListFilename, func(fs btrfs.ReadableFS, nodeList []btrfsvol.LogicalAddr, cmd *cobra.Command, _ []string) error { + RunE: runWithReadableFSAndNodeList(func(fs btrfs.ReadableFS, nodeList []btrfsvol.LogicalAddr, cmd *cobra.Command, _ []string) error { ctx := cmd.Context() var treeErrCnt int @@ -113,10 +112,5 @@ func init() { return nil }), - } - cmd.Flags().StringVar(&nodeListFilename, "node-list", "", - "Output of 'btrfs-recs inspect [rebuild-mappings] list-nodes' to use for a lost+found tree") - noError(cmd.MarkFlagFilename("node-list")) - - inspectors.AddCommand(cmd) + }) } diff --git a/cmd/btrfs-rec/inspect_rebuildtrees.go b/cmd/btrfs-rec/inspect_rebuildtrees.go index 676533a..1e808a0 100644 --- a/cmd/btrfs-rec/inspect_rebuildtrees.go +++ b/cmd/btrfs-rec/inspect_rebuildtrees.go @@ -17,13 +17,11 @@ import ( "git.lukeshu.com/btrfs-progs-ng/cmd/btrfs-rec/inspect/rebuildtrees" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfsutil" "git.lukeshu.com/btrfs-progs-ng/lib/textui" ) func init() { - var nodeListFilename string - cmd := &cobra.Command{ + inspectors.AddCommand(&cobra.Command{ Use: "rebuild-trees", Long: "" + "Rebuild broken btrees based on missing items that are implied " + @@ -34,20 +32,9 @@ func init() { "If no --node-list is given, then a slow sector-by-sector scan " + "will be used to find all nodes.", Args: cliutil.WrapPositionalArgs(cobra.NoArgs), - RunE: runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error { + RunE: runWithRawFSAndNodeList(func(fs *btrfs.FS, nodeList []btrfsvol.LogicalAddr, cmd *cobra.Command, args []string) error { ctx := cmd.Context() - var nodeList []btrfsvol.LogicalAddr - var err error - if nodeListFilename != "" { - nodeList, err = readJSONFile[[]btrfsvol.LogicalAddr](ctx, nodeListFilename) - } else { - nodeList, err = btrfsutil.ListNodes(ctx, fs) - } - if err != nil { - return err - } - rebuilder, err := rebuildtrees.NewRebuilder(ctx, fs, nodeList) if err != nil { return err @@ -78,10 +65,5 @@ func init() { return rebuildErr }), - } - cmd.Flags().StringVar(&nodeListFilename, "node-list", "", - "Output of 'btrfs-recs inspect [rebuild-mappings] list-nodes' to use for the node list") - noError(cmd.MarkFlagFilename("node-list")) - - inspectors.AddCommand(cmd) + }) } diff --git a/cmd/btrfs-rec/main.go b/cmd/btrfs-rec/main.go index 8d3193a..da3aced 100644 --- a/cmd/btrfs-rec/main.go +++ b/cmd/btrfs-rec/main.go @@ -50,6 +50,7 @@ var globalFlags struct { pvs []string mappings string + nodeList string rebuild bool stopProfiling profile.StopFunc @@ -96,6 +97,10 @@ func main() { "load chunk/dev-extent/blockgroup data from external JSON file `mappings.json`") noError(argparser.MarkPersistentFlagFilename("mappings")) + argparser.PersistentFlags().StringVar(&globalFlags.nodeList, "node-list", "", + "load node list (output of 'btrfs-recs inspect [rebuild-mappings] list-nodes') from external JSON file `nodes.json`") + noError(argparser.MarkPersistentFlagFilename("node-list")) + argparser.PersistentFlags().BoolVar(&globalFlags.rebuild, "rebuild", false, "attempt to rebuild broken btrees when reading") @@ -183,34 +188,51 @@ func runWithRawFS(runE func(*btrfs.FS, *cobra.Command, []string) error) func(*co }) } -func runWithReadableFS(runE func(btrfs.ReadableFS, *cobra.Command, []string) error) func(*cobra.Command, []string) error { +func runWithRawFSAndNodeList(runE func(*btrfs.FS, []btrfsvol.LogicalAddr, *cobra.Command, []string) error) func(*cobra.Command, []string) error { return runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error { - var rfs btrfs.ReadableFS = fs - if globalFlags.rebuild { - rfs = btrfsutil.NewOldRebuiltForrest(fs) - } - return runE(rfs, cmd, args) - }) -} + ctx := cmd.Context() -func runWithReadableFSAndNodeList(nodeListFilename *string, runE func(btrfs.ReadableFS, []btrfsvol.LogicalAddr, *cobra.Command, []string) error) func(*cobra.Command, []string) error { - return runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error { var nodeList []btrfsvol.LogicalAddr var err error - if *nodeListFilename != "" { - nodeList, err = readJSONFile[[]btrfsvol.LogicalAddr](cmd.Context(), *nodeListFilename) + if globalFlags.nodeList != "" { + nodeList, err = readJSONFile[[]btrfsvol.LogicalAddr](ctx, globalFlags.nodeList) } else { - nodeList, err = btrfsutil.ListNodes(cmd.Context(), fs) + nodeList, err = btrfsutil.ListNodes(ctx, fs) } if err != nil { return err } + return runE(fs, nodeList, cmd, args) + }) +} + +func _runWithReadableFS(wantNodeList bool, runE func(btrfs.ReadableFS, []btrfsvol.LogicalAddr, *cobra.Command, []string) error) func(*cobra.Command, []string) error { + inner := func(fs *btrfs.FS, nodeList []btrfsvol.LogicalAddr, cmd *cobra.Command, args []string) error { var rfs btrfs.ReadableFS = fs if globalFlags.rebuild { rfs = btrfsutil.NewOldRebuiltForrest(fs) } return runE(rfs, nodeList, cmd, args) + } + + return func(cmd *cobra.Command, args []string) error { + if wantNodeList { + return runWithRawFSAndNodeList(inner)(cmd, args) + } + return runWithRawFS(func(fs *btrfs.FS, cmd *cobra.Command, args []string) error { + return inner(fs, nil, cmd, args) + })(cmd, args) + } +} + +func runWithReadableFSAndNodeList(runE func(btrfs.ReadableFS, []btrfsvol.LogicalAddr, *cobra.Command, []string) error) func(*cobra.Command, []string) error { + return _runWithReadableFS(true, runE) +} + +func runWithReadableFS(runE func(btrfs.ReadableFS, *cobra.Command, []string) error) func(*cobra.Command, []string) error { + return _runWithReadableFS(false, func(fs btrfs.ReadableFS, _ []btrfsvol.LogicalAddr, cmd *cobra.Command, args []string) error { + return runE(fs, cmd, args) }) } -- cgit v1.2.3-2-g168b From 52143763329ab004ce28d660a8f67eac32fa481c Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 2 Apr 2023 11:24:13 -0600 Subject: btrfsutil: RebuiltTree: Take better advantage of cache pinning --- cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go | 6 ++- .../inspect/rebuildtrees/rebuild_wantcb.go | 61 ++++++++++++++-------- 2 files changed, 44 insertions(+), 23 deletions(-) (limited to 'cmd') diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go index 2160969..427070a 100644 --- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go +++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go @@ -198,11 +198,13 @@ func (o *rebuilder) processAddedItemQueue(ctx context.Context) error { ctx := dlog.WithField(ctx, "btrfs.inspect.rebuild-trees.rebuild.settle.item", key) tree := o.rebuilt.RebuiltTree(ctx, key.TreeID) - incPtr, ok := tree.RebuiltItems(ctx).Load(key.Key) + incPtr, ok := tree.RebuiltAcquireItems(ctx).Load(key.Key) + tree.RebuiltReleaseItems() if !ok { panic(fmt.Errorf("should not happen: failed to load already-added item: %v", key)) } - excPtr, ok := tree.RebuiltPotentialItems(ctx).Load(key.Key) + excPtr, ok := tree.RebuiltAcquirePotentialItems(ctx).Load(key.Key) + tree.RebuiltReleasePotentialItems() if ok && tree.RebuiltShouldReplace(incPtr.Node, excPtr.Node) { wantKey := wantWithTree{ TreeID: key.TreeID, diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go index eff2a83..0526e93 100644 --- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go +++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go @@ -43,18 +43,22 @@ func (o graphCallbacks) Want(ctx context.Context, reason string, treeID btrfspri } func (o *rebuilder) _want(ctx context.Context, wantKey wantWithTree) (key btrfsprim.Key, ok bool) { - if o.rebuilt.RebuiltTree(ctx, wantKey.TreeID) == nil { + tree := o.rebuilt.RebuiltTree(ctx, wantKey.TreeID) + if tree == nil { o.enqueueRetry(wantKey.TreeID) return btrfsprim.Key{}, false } + tgt := wantKey.Key.Key() + // check if we already have it - tgt := wantKey.Key.Key() - if key, _, ok := o.rebuilt.RebuiltTree(ctx, wantKey.TreeID).RebuiltItems(ctx).Search(func(key btrfsprim.Key, _ btrfsutil.ItemPtr) int { + key, _, ok = tree.RebuiltAcquireItems(ctx).Search(func(key btrfsprim.Key, _ btrfsutil.ItemPtr) int { key.Offset = 0 return tgt.Compare(key) - }); ok { + }) + tree.RebuiltReleaseItems() + if ok { return key, true } @@ -64,15 +68,16 @@ func (o *rebuilder) _want(ctx context.Context, wantKey wantWithTree) (key btrfsp return btrfsprim.Key{}, false } wants := make(containers.Set[btrfsvol.LogicalAddr]) - o.rebuilt.RebuiltTree(ctx, wantKey.TreeID).RebuiltPotentialItems(ctx).Subrange( + tree.RebuiltAcquirePotentialItems(ctx).Subrange( func(k btrfsprim.Key, _ btrfsutil.ItemPtr) int { k.Offset = 0 return tgt.Compare(k) }, func(_ btrfsprim.Key, v btrfsutil.ItemPtr) bool { - wants.InsertFrom(o.rebuilt.RebuiltTree(ctx, wantKey.TreeID).RebuiltLeafToRoots(ctx, v.Node)) + wants.InsertFrom(tree.RebuiltLeafToRoots(ctx, v.Node)) return true }) + tree.RebuiltReleasePotentialItems() o.wantAugment(ctx, wantKey, wants) return btrfsprim.Key{}, false } @@ -93,15 +98,19 @@ func (o graphCallbacks) WantOff(ctx context.Context, reason string, treeID btrfs } func (o *rebuilder) _wantOff(ctx context.Context, wantKey wantWithTree) (ok bool) { - if o.rebuilt.RebuiltTree(ctx, wantKey.TreeID) == nil { + tree := o.rebuilt.RebuiltTree(ctx, wantKey.TreeID) + if tree == nil { o.enqueueRetry(wantKey.TreeID) return false } + tgt := wantKey.Key.Key() + // check if we already have it - tgt := wantKey.Key.Key() - if _, ok := o.rebuilt.RebuiltTree(ctx, wantKey.TreeID).RebuiltItems(ctx).Load(tgt); ok { + _, ok = tree.RebuiltAcquireItems(ctx).Load(tgt) + tree.RebuiltReleaseItems() + if ok { return true } @@ -111,12 +120,13 @@ func (o *rebuilder) _wantOff(ctx context.Context, wantKey wantWithTree) (ok bool return false } wants := make(containers.Set[btrfsvol.LogicalAddr]) - o.rebuilt.RebuiltTree(ctx, wantKey.TreeID).RebuiltPotentialItems(ctx).Subrange( + tree.RebuiltAcquirePotentialItems(ctx).Subrange( func(k btrfsprim.Key, _ btrfsutil.ItemPtr) int { return tgt.Compare(k) }, func(_ btrfsprim.Key, v btrfsutil.ItemPtr) bool { - wants.InsertFrom(o.rebuilt.RebuiltTree(ctx, wantKey.TreeID).RebuiltLeafToRoots(ctx, v.Node)) + wants.InsertFrom(tree.RebuiltLeafToRoots(ctx, v.Node)) return true }) + tree.RebuiltReleasePotentialItems() o.wantAugment(ctx, wantKey, wants) return false } @@ -134,16 +144,18 @@ func (o graphCallbacks) WantDirIndex(ctx context.Context, reason string, treeID } ctx = withWant(ctx, logFieldItemWant, reason, wantKey) - if o.rebuilt.RebuiltTree(ctx, treeID) == nil { + tree := o.rebuilt.RebuiltTree(ctx, treeID) + if tree == nil { o.enqueueRetry(treeID) return } + tgt := wantKey.Key.Key() + // check if we already have it - tgt := wantKey.Key.Key() found := false - o.rebuilt.RebuiltTree(ctx, treeID).RebuiltItems(ctx).Subrange( + tree.RebuiltAcquireItems(ctx).Subrange( func(key btrfsprim.Key, _ btrfsutil.ItemPtr) int { key.Offset = 0 return tgt.Compare(key) @@ -154,6 +166,7 @@ func (o graphCallbacks) WantDirIndex(ctx context.Context, reason string, treeID } return !found }) + tree.RebuiltReleaseItems() if found { return } @@ -164,17 +177,18 @@ func (o graphCallbacks) WantDirIndex(ctx context.Context, reason string, treeID return } wants := make(containers.Set[btrfsvol.LogicalAddr]) - o.rebuilt.RebuiltTree(ctx, treeID).RebuiltPotentialItems(ctx).Subrange( + tree.RebuiltAcquirePotentialItems(ctx).Subrange( func(key btrfsprim.Key, _ btrfsutil.ItemPtr) int { key.Offset = 0 return tgt.Compare(key) }, func(_ btrfsprim.Key, ptr btrfsutil.ItemPtr) bool { if itemName, ok := o.scan.Names[ptr]; ok && bytes.Equal(itemName, name) { - wants.InsertFrom(o.rebuilt.RebuiltTree(ctx, treeID).RebuiltLeafToRoots(ctx, ptr.Node)) + wants.InsertFrom(tree.RebuiltLeafToRoots(ctx, ptr.Node)) } return true }) + tree.RebuiltReleasePotentialItems() o.wantAugment(ctx, wantKey, wants) } @@ -259,7 +273,8 @@ func (o graphCallbacks) _wantRange( ctx = withWant(ctx, logFieldItemWant, reason, wantKey) wantKey.Key.OffsetType = offsetRange - if o.rebuilt.RebuiltTree(ctx, treeID) == nil { + tree := o.rebuilt.RebuiltTree(ctx, treeID) + if tree == nil { o.enqueueRetry(treeID) return } @@ -275,7 +290,7 @@ func (o graphCallbacks) _wantRange( }) o._walkRange( ctx, - o.rebuilt.RebuiltTree(ctx, treeID).RebuiltItems(ctx), + tree.RebuiltAcquireItems(ctx), treeID, objID, typ, beg, end, func(runKey btrfsprim.Key, _ btrfsutil.ItemPtr, runBeg, runEnd uint64) { var overlappingGaps []*containers.RBNode[gap] @@ -315,12 +330,13 @@ func (o graphCallbacks) _wantRange( }) } }) + tree.RebuiltReleaseItems() // Step 2: Fill each gap. if gaps.Len() == 0 { return } - potentialItems := o.rebuilt.RebuiltTree(ctx, treeID).RebuiltPotentialItems(ctx) + potentialItems := tree.RebuiltAcquirePotentialItems(ctx) gaps.Range(func(rbNode *containers.RBNode[gap]) bool { gap := rbNode.Value last := gap.Beg @@ -340,7 +356,7 @@ func (o graphCallbacks) _wantRange( wantKey.Key.OffsetLow = gap.Beg wantKey.Key.OffsetHigh = gap.End wantCtx := withWant(ctx, logFieldItemWant, reason, wantKey) - o.wantAugment(wantCtx, wantKey, o.rebuilt.RebuiltTree(wantCtx, treeID).RebuiltLeafToRoots(wantCtx, v.Node)) + o.wantAugment(wantCtx, wantKey, tree.RebuiltLeafToRoots(wantCtx, v.Node)) last = runEnd }) if last < gap.End { @@ -352,6 +368,7 @@ func (o graphCallbacks) _wantRange( } return true }) + tree.RebuiltReleasePotentialItems() } // WantCSum implements btrfscheck.GraphCallbacks. @@ -372,7 +389,9 @@ func (o graphCallbacks) WantCSum(ctx context.Context, reason string, inodeTree, o.enqueueRetry(inodeTree) return } - inodePtr, ok := o.rebuilt.RebuiltTree(inodeCtx, inodeTree).RebuiltItems(inodeCtx).Load(inodeWant.Key.Key()) + tree := o.rebuilt.RebuiltTree(inodeCtx, inodeTree) + inodePtr, ok := tree.RebuiltAcquireItems(inodeCtx).Load(inodeWant.Key.Key()) + tree.RebuiltReleaseItems() if !ok { panic(fmt.Errorf("should not happen: could not load key: %v", inodeWant)) } -- cgit v1.2.3-2-g168b