diff options
-rw-r--r-- | lib/btrfs/btrfsitem/item_uuid.go | 9 | ||||
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go | 22 | ||||
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go | 9 |
3 files changed, 24 insertions, 16 deletions
diff --git a/lib/btrfs/btrfsitem/item_uuid.go b/lib/btrfs/btrfsitem/item_uuid.go index 03823ce..451ccae 100644 --- a/lib/btrfs/btrfsitem/item_uuid.go +++ b/lib/btrfs/btrfsitem/item_uuid.go @@ -5,6 +5,8 @@ package btrfsitem import ( + "encoding/binary" + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) @@ -18,3 +20,10 @@ type UUIDMap struct { // UUID_SUBVOL=251 UUID_RECEIVED_SUBVOL=252 ObjID btrfsprim.ObjID `bin:"off=0, siz=8"` binstruct.End `bin:"off=8"` } + +func KeyToUUID(key btrfsprim.Key) btrfsprim.UUID { + var uuid btrfsprim.UUID + binary.LittleEndian.PutUint64(uuid[:8], uint64(key.ObjectID)) + binary.LittleEndian.PutUint64(uuid[8:], uint64(key.Offset)) + return uuid +} diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go index 7ccccea..7950393 100644 --- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go +++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/rebuildnodes.go @@ -260,7 +260,8 @@ func reInitBrokenNodes(ctx context.Context, fs _FS, nodeScanResults btrfsinspect lastPct := -1 total := countNodes(nodeScanResults) - progress := func(done int) { + done := 0 + progress := func() { pct := int(100 * float64(done) / float64(total)) if pct != lastPct || done == total { dlog.Infof(ctx, "... %v%% (%v/%v)", @@ -268,21 +269,20 @@ func reInitBrokenNodes(ctx context.Context, fs _FS, nodeScanResults btrfsinspect lastPct = pct } } - var done int rebuiltNodes := make(map[btrfsvol.LogicalAddr]*RebuiltNode) - dbg := make(map[btrfsvol.LogicalAddr]btrfstree.TreePath) + visitedNodes := make(map[btrfsvol.LogicalAddr]struct{}) walkHandler := btrfstree.TreeWalkHandler{ Node: func(path btrfstree.TreePath, _ *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error { - if other, conflict := dbg[path.Node(-1).ToNodeAddr]; conflict { - panic(fmt.Errorf("same node visited twice: %v != %v", other, path)) + addr := path.Node(-1).ToNodeAddr + if _, alreadyVisited := visitedNodes[addr]; alreadyVisited { + // Can happen because of COW subvolumes; + // this is really a DAG not a tree. + return iofs.SkipDir } - dbg[path.Node(-1).ToNodeAddr] = path.DeepCopy() + visitedNodes[addr] = struct{}{} done++ - if done != len(dbg) { - panic(fmt.Errorf("done=%v != len(dbg)=%v", done, len(dbg))) - } - progress(done) + progress() return nil }, BadNode: func(path btrfstree.TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node], err error) error { @@ -310,6 +310,7 @@ func reInitBrokenNodes(ctx context.Context, fs _FS, nodeScanResults btrfsinspect // nodeScanResults so that we don't need to specifically check // if any of the root nodes referenced directly by the // superblock are dead. + progress() btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ Err: func(err *btrfsutil.WalkError) { // do nothing @@ -323,6 +324,7 @@ func reInitBrokenNodes(ctx context.Context, fs _FS, nodeScanResults btrfsinspect }, walkHandler) } + progress() return rebuiltNodes, nil } diff --git a/lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go b/lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go index 606f8f9..ba090fb 100644 --- a/lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go +++ b/lib/btrfsprogs/btrfsinspect/rebuildnodes/uuidmap.go @@ -6,7 +6,6 @@ package rebuildnodes import ( "context" - "encoding/binary" "fmt" "github.com/datawire/dlib/dlog" @@ -86,9 +85,7 @@ func buildUUIDMap(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.Sc return uuidMap{}, err } case btrfsitem.UUIDMap: - var uuid btrfsprim.UUID - binary.BigEndian.PutUint64(uuid[:8], uint64(item.Key.ObjectID)) - binary.BigEndian.PutUint64(uuid[8:], uint64(item.Key.Offset)) + uuid := btrfsitem.KeyToUUID(item.Key) if err := maybeSet("ObjID2UUID", ret.ObjID2UUID, itemBody.ObjID, uuid); err != nil { return uuidMap{}, err } @@ -106,7 +103,7 @@ func buildUUIDMap(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.Sc missing := make(map[btrfsprim.ObjID]struct{}) for treeID := range seenTreeIDs { - if _, ok := ret.ObjID2UUID[treeID]; !ok { + if _, ok := ret.ObjID2UUID[treeID]; !ok && treeID != btrfsprim.ROOT_TREE_OBJECTID { missing[treeID] = struct{}{} continue } @@ -115,7 +112,7 @@ func buildUUIDMap(ctx context.Context, fs *btrfs.FS, scanResults btrfsinspect.Sc } } if len(missing) > 0 { - dlog.Errorf(ctx, "... could not find root items for trees %v", maps.SortedKeys(missing)) + dlog.Errorf(ctx, "... could not find root items for %d trees: %v", len(missing), maps.SortedKeys(missing)) } dlog.Info(ctx, "... done building table") |