diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-12-24 04:38:24 -0700 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-12-24 04:55:21 -0700 |
commit | bc06b340b71a07a0bb500e1bb7e81ece19f1a9c5 (patch) | |
tree | c93b73fd2426da5c902147d2a4eb1f4efbc5371f /lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go | |
parent | d1173de57640e67f4bdc4a0cdc923ff8f509f7df (diff) |
rebuildnodes: Track item sizes at startup, to avoid extra i/o
Diffstat (limited to 'lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go')
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go | 59 |
1 files changed, 13 insertions, 46 deletions
diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go index 5badc33..66eaf1a 100644 --- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go +++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuild.go @@ -51,7 +51,7 @@ type rebuilder struct { } func RebuildNodes(ctx context.Context, fs *btrfs.FS, nodeScanResults btrfsinspect.ScanDevicesResult) (map[btrfsprim.ObjID]containers.Set[btrfsvol.LogicalAddr], error) { - nodeGraph, err := ScanDevices(ctx, fs, nodeScanResults) // ScanDevices does its own logging + nodeGraph, keyIO, err := ScanDevices(ctx, fs, nodeScanResults) // ScanDevices does its own logging if err != nil { return nil, err } @@ -63,7 +63,6 @@ func RebuildNodes(ctx context.Context, fs *btrfs.FS, nodeScanResults btrfsinspec } dlog.Info(ctx, "Rebuilding node tree...") - keyIO := keyio.NewHandle(fs, *sb, nodeGraph) o := &rebuilder{ sb: *sb, @@ -499,7 +498,6 @@ func (o *rebuilder) wantFunc(ctx context.Context, treeID btrfsprim.ObjID, objID func (o *rebuilder) _wantRange( ctx context.Context, treeID btrfsprim.ObjID, objID btrfsprim.ObjID, typ btrfsprim.ItemType, - sizeFn func(btrfsprim.Key) (uint64, error), beg, end uint64, ) { if !o.rebuilt.AddTree(ctx, treeID) { @@ -507,6 +505,18 @@ func (o *rebuilder) _wantRange( return } + sizeFn := func(key btrfsprim.Key) (uint64, error) { + ptr, ok := o.rebuilt.Keys(treeID).Load(key) + if !ok { + panic(fmt.Errorf("should not happen: could not load key: %v", key)) + } + sizeAndErr, ok := o.keyIO.Sizes[ptr] + if !ok { + panic(fmt.Errorf("should not happen: %v item did not have a size recorded", typ)) + } + return sizeAndErr.Size, sizeAndErr.Err + } + // Step 1: Build a listing of the runs that we do have. runMin := btrfsprim.Key{ ObjectID: objID, @@ -661,54 +671,11 @@ func (o *rebuilder) _wantRange( func (o *rebuilder) wantCSum(ctx context.Context, beg, end btrfsvol.LogicalAddr) { const treeID = btrfsprim.CSUM_TREE_OBJECTID o._wantRange(ctx, treeID, btrfsprim.EXTENT_CSUM_OBJECTID, btrfsprim.EXTENT_CSUM_KEY, - func(key btrfsprim.Key) (uint64, error) { - ptr, ok := o.rebuilt.Keys(treeID).Load(key) - if !ok { - panic(fmt.Errorf("should not happen: could not load key: %v", key)) - } - body, ok := o.keyIO.ReadItem(ptr) - if !ok { - panic(fmt.Errorf("should not happen: could not read item: %v", key)) - } - switch body := body.(type) { - case btrfsitem.ExtentCSum: - return uint64(body.Size()), nil - case btrfsitem.Error: - return 0, fmt.Errorf("error decoding item: tree=%v key=%v: %w", treeID, key, body.Err) - default: - // This is a panic because the item decoder should not emit EXTENT_CSUM - // items as anything but btrfsitem.ExtentCSum or btrfsitem.Error without - // this code also being updated. - panic(fmt.Errorf("should not happen: EXTENT_CSUM item has unexpected type: %T", body)) - } - }, uint64(beg), uint64(end)) } // wantFileExt implements rebuildCallbacks. func (o *rebuilder) wantFileExt(ctx context.Context, treeID btrfsprim.ObjID, ino btrfsprim.ObjID, size int64) { o._wantRange(ctx, treeID, ino, btrfsprim.EXTENT_DATA_KEY, - func(key btrfsprim.Key) (uint64, error) { - ptr, ok := o.rebuilt.Keys(treeID).Load(key) - if !ok { - panic(fmt.Errorf("should not happen: could not load key: %v", key)) - } - body, ok := o.keyIO.ReadItem(ptr) - if !ok { - panic(fmt.Errorf("should not happen: could not read item: %v", key)) - } - switch body := body.(type) { - case btrfsitem.FileExtent: - size, err := body.Size() - return uint64(size), err - case btrfsitem.Error: - return 0, fmt.Errorf("error decoding item: tree=%v key=%v: %w", treeID, key, body.Err) - default: - // This is a panic because the item decoder should not emit EXTENT_DATA - // items as anything but btrfsitem.FileExtent or btrfsitem.Error without - // this code also being updated. - panic(fmt.Errorf("should not happen: EXTENT_DATA item has unexpected type: %T", body)) - } - }, 0, uint64(size)) } |