summaryrefslogtreecommitdiff
path: root/lib/btrfsprogs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfsprogs')
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/orphans.go60
-rw-r--r--lib/btrfsprogs/btrfsinspect/rebuildnodes/scan.go26
-rw-r--r--lib/btrfsprogs/btrfsinspect/scandevices.go51
3 files changed, 100 insertions, 37 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/orphans.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/orphans.go
index 55cf95b..51313a9 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/orphans.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/orphans.go
@@ -6,6 +6,8 @@ package rebuildnodes
import (
"context"
+ "fmt"
+ "time"
"github.com/datawire/dlib/dlog"
@@ -16,6 +18,7 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/containers"
"git.lukeshu.com/btrfs-progs-ng/lib/diskio"
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
+ "git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
func listRoots(graph graph.Graph, leaf btrfsvol.LogicalAddr) containers.Set[btrfsvol.LogicalAddr] {
@@ -54,6 +57,31 @@ func (a keyAndTree) Cmp(b keyAndTree) int {
return containers.NativeCmp(a.TreeID, b.TreeID)
}
+type crawlStats struct {
+ DoneOrphans int
+ TotalOrphans int
+
+ VisitedNodes int
+ FoundLeafs int
+}
+
+func (s crawlStats) String() string {
+ return fmt.Sprintf("... crawling orphans %v%% (%v/%v); visited %d nodes, found %d leaf nodes",
+ int(100*float64(s.DoneOrphans)/float64(s.TotalOrphans)),
+ s.DoneOrphans, s.TotalOrphans, s.VisitedNodes, s.FoundLeafs)
+}
+
+type readStats struct {
+ DoneLeafNodes int
+ TotalLeafNodes int
+}
+
+func (s readStats) String() string {
+ return fmt.Sprintf("... reading leafs %v%% (%v/%v)",
+ int(100*float64(s.DoneLeafNodes)/float64(s.TotalLeafNodes)),
+ s.DoneLeafNodes, s.TotalLeafNodes)
+}
+
func indexOrphans(ctx context.Context, fs diskio.File[btrfsvol.LogicalAddr], sb btrfstree.Superblock, graph graph.Graph) (
orphans containers.Set[btrfsvol.LogicalAddr],
leaf2orphans map[btrfsvol.LogicalAddr]containers.Set[btrfsvol.LogicalAddr],
@@ -71,18 +99,15 @@ func indexOrphans(ctx context.Context, fs diskio.File[btrfsvol.LogicalAddr], sb
leaf2orphans = make(map[btrfsvol.LogicalAddr]containers.Set[btrfsvol.LogicalAddr])
visited := make(containers.Set[btrfsvol.LogicalAddr])
- lastPct, lastVisited, lastLeafs := -1, 0, 0
- total := len(orphans)
done := 0
+ crawlProgressWriter := textui.NewProgress[crawlStats](ctx, dlog.LogLevelInfo, 1*time.Second)
progress := func() {
- pct := int(100 * float64(done) / float64(total))
- if pct != lastPct || (len(visited) != lastVisited && len(visited)%500 == 0) || len(leaf2orphans) != lastLeafs || done == total {
- dlog.Infof(ctx, "... crawling orphans %v%% (%v/%v); visited %d nodes, found %d leaf nodes",
- pct, done, total, len(visited), len(leaf2orphans))
- lastPct = pct
- lastVisited = len(visited)
- lastLeafs = len(leaf2orphans)
- }
+ crawlProgressWriter.Set(crawlStats{
+ DoneOrphans: done,
+ TotalOrphans: len(orphans),
+ VisitedNodes: len(visited),
+ FoundLeafs: len(leaf2orphans),
+ })
}
progress()
for _, orphan := range maps.SortedKeys(orphans) {
@@ -102,17 +127,16 @@ func indexOrphans(ctx context.Context, fs diskio.File[btrfsvol.LogicalAddr], sb
done++
progress()
}
+ crawlProgressWriter.Done()
key2leaf = new(containers.SortedMap[keyAndTree, btrfsvol.LogicalAddr])
- total = len(leaf2orphans)
done = 0
+ readProgressWriter := textui.NewProgress[readStats](ctx, dlog.LogLevelInfo, 1*time.Second)
progress = func() {
- pct := int(100 * float64(done) / float64(total))
- if pct != lastPct || done == total {
- dlog.Infof(ctx, "... reading leafs %v%% (%v/%v)",
- pct, done, total)
- lastPct = pct
- }
+ readProgressWriter.Set(readStats{
+ DoneLeafNodes: done,
+ TotalLeafNodes: len(leaf2orphans),
+ })
}
progress()
for _, laddr := range maps.SortedKeys(leaf2orphans) {
@@ -136,5 +160,7 @@ func indexOrphans(ctx context.Context, fs diskio.File[btrfsvol.LogicalAddr], sb
done++
progress()
}
+ readProgressWriter.Done()
+
return orphans, leaf2orphans, key2leaf, nil
}
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/scan.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/scan.go
index 9174035..3575534 100644
--- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/scan.go
+++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/scan.go
@@ -6,6 +6,8 @@ package rebuildnodes
import (
"context"
+ "fmt"
+ "time"
"github.com/datawire/dlib/dlog"
@@ -17,6 +19,7 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap"
"git.lukeshu.com/btrfs-progs-ng/lib/containers"
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
+ "git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
type scanResult struct {
@@ -24,6 +27,16 @@ type scanResult struct {
nodeGraph *graph.Graph
}
+type scanStats struct {
+ N, D int
+}
+
+func (s scanStats) String() string {
+ return fmt.Sprintf("... %v%% (%v/%v)",
+ int(100*float64(s.N)/float64(s.D)),
+ s.N, s.D)
+}
+
func ScanDevices(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.ScanDevicesResult) (*scanResult, error) {
dlog.Infof(ctx, "Reading node data from FS...")
@@ -32,16 +45,11 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.Sca
return nil, err
}
- lastPct := -1
total := countNodes(scanResults)
done := 0
+ progressWriter := textui.NewProgress[scanStats](ctx, dlog.LogLevelInfo, 1*time.Second)
progress := func(done, total int) {
- pct := int(100 * float64(done) / float64(total))
- if pct != lastPct || done == total {
- dlog.Infof(ctx, "... %v%% (%v/%v)",
- pct, done, total)
- lastPct = pct
- }
+ progressWriter.Set(scanStats{N: done, D: total})
}
ret := &scanResult{
@@ -69,10 +77,10 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.Sca
progress(done, total)
}
}
-
if done != total {
panic("should not happen")
}
+ progressWriter.Done()
missing := ret.uuidMap.MissingRootItems()
if len(missing) > 0 {
@@ -81,10 +89,12 @@ func ScanDevices(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.Sca
dlog.Info(ctx, "... done reading node data")
+ progressWriter = textui.NewProgress[scanStats](ctx, dlog.LogLevelInfo, 1*time.Second)
dlog.Infof(ctx, "Checking keypointers for dead-ends...")
if err := ret.nodeGraph.FinalCheck(fs, *sb, progress); err != nil {
return nil, err
}
+ progressWriter.Done()
dlog.Info(ctx, "... done checking keypointers")
return ret, nil
diff --git a/lib/btrfsprogs/btrfsinspect/scandevices.go b/lib/btrfsprogs/btrfsinspect/scandevices.go
index a382e17..4834826 100644
--- a/lib/btrfsprogs/btrfsinspect/scandevices.go
+++ b/lib/btrfsprogs/btrfsinspect/scandevices.go
@@ -10,6 +10,7 @@ import (
"fmt"
"strings"
"sync"
+ "time"
"github.com/datawire/dlib/dgroup"
"github.com/datawire/dlib/dlog"
@@ -21,6 +22,7 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
+ "git.lukeshu.com/btrfs-progs-ng/lib/textui"
)
type ScanDevicesResult map[btrfsvol.DeviceID]ScanOneDeviceResult
@@ -78,6 +80,31 @@ type SysExtentCSum struct {
Sums btrfsitem.ExtentCSum
}
+type scanStats struct {
+ DevName string
+ DevSize btrfsvol.PhysicalAddr
+
+ Pos btrfsvol.PhysicalAddr
+
+ NumFoundNodes int
+ NumFoundChunks int
+ NumFoundBlockGroups int
+ NumFoundDevExtents int
+ NumFoundExtentCSums int
+}
+
+func (s scanStats) String() string {
+ return fmt.Sprintf("... dev[%q] scanned %v%% (%d/%d) (found: %v nodes, %v chunks, %v block groups, %v dev extents, %v sum items)",
+ s.DevName,
+ int(100*float64(s.Pos)/float64(s.DevSize)),
+ s.Pos, s.DevSize,
+ s.NumFoundNodes,
+ s.NumFoundChunks,
+ s.NumFoundBlockGroups,
+ s.NumFoundDevExtents,
+ s.NumFoundExtentCSums)
+}
+
// ScanOneDevice mostly mimics btrfs-progs
// cmds/rescue-chunk-recover.c:scan_one_device().
func ScanOneDevice(ctx context.Context, dev *btrfs.Device, sb btrfstree.Superblock) (ScanOneDeviceResult, error) {
@@ -103,19 +130,18 @@ func ScanOneDevice(ctx context.Context, dev *btrfs.Device, sb btrfstree.Superblo
var sums strings.Builder
sums.Grow(numSums * csumSize)
- lastProgress := -1
+ progressWriter := textui.NewProgress[scanStats](ctx, dlog.LogLevelInfo, 1*time.Second)
progress := func(pos btrfsvol.PhysicalAddr) {
- pct := int(100 * float64(pos) / float64(devSize))
- if pct != lastProgress || pos == devSize {
- dlog.Infof(ctx, "... dev[%q] scanned %v%% (found: %v nodes, %v chunks, %v block groups, %v dev extents, %v sum items)",
- dev.Name(), pct,
- len(result.FoundNodes),
- len(result.FoundChunks),
- len(result.FoundBlockGroups),
- len(result.FoundDevExtents),
- len(result.FoundExtentCSums))
- lastProgress = pct
- }
+ progressWriter.Set(scanStats{
+ DevName: dev.Name(),
+ DevSize: devSize,
+ Pos: pos,
+ NumFoundNodes: len(result.FoundNodes),
+ NumFoundChunks: len(result.FoundChunks),
+ NumFoundBlockGroups: len(result.FoundBlockGroups),
+ NumFoundDevExtents: len(result.FoundDevExtents),
+ NumFoundExtentCSums: len(result.FoundExtentCSums),
+ })
}
var minNextNode btrfsvol.PhysicalAddr
@@ -212,6 +238,7 @@ func ScanOneDevice(ctx context.Context, dev *btrfs.Device, sb btrfstree.Superblo
}
}
progress(devSize)
+ progressWriter.Done()
result.Checksums = btrfssum.SumRun[btrfsvol.PhysicalAddr]{
ChecksumSize: csumSize,