From 677755c799c1b6b942349c7d9de836335c7bbf55 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 3 Feb 2023 11:32:52 -0700 Subject: btrfsitem: Have all Item implementations be pointers to structs --- lib/btrfsprogs/btrfsinspect/print_tree.go | 52 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'lib/btrfsprogs/btrfsinspect/print_tree.go') diff --git a/lib/btrfsprogs/btrfsinspect/print_tree.go b/lib/btrfsprogs/btrfsinspect/print_tree.go index 3807df5..409ce0c 100644 --- a/lib/btrfsprogs/btrfsinspect/print_tree.go +++ b/lib/btrfsprogs/btrfsinspect/print_tree.go @@ -121,11 +121,11 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri itemOffset, itemSize) switch body := item.Body.(type) { - case btrfsitem.FreeSpaceHeader: + case *btrfsitem.FreeSpaceHeader: textui.Fprintf(out, "\t\tlocation %v\n", fmtKey(body.Location)) textui.Fprintf(out, "\t\tcache generation %v entries %v bitmaps %v\n", body.Generation, body.NumEntries, body.NumBitmaps) - case btrfsitem.Inode: + case *btrfsitem.Inode: textui.Fprintf(out, ""+ "\t\tgeneration %v transid %v size %v nbytes %v\n"+ "\t\tblock group %v mode %o links %v uid %v gid %v rdev %v\n"+ @@ -137,14 +137,14 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri textui.Fprintf(out, "\t\tctime %v\n", fmtTime(body.CTime)) textui.Fprintf(out, "\t\tmtime %v\n", fmtTime(body.MTime)) textui.Fprintf(out, "\t\totime %v\n", fmtTime(body.OTime)) - case btrfsitem.InodeRefs: - for _, ref := range body { + case *btrfsitem.InodeRefs: + for _, ref := range body.Refs { textui.Fprintf(out, "\t\tindex %v namelen %v name: %s\n", ref.Index, ref.NameLen, ref.Name) } // case btrfsitem.INODE_EXTREF_KEY: // // TODO - case btrfsitem.DirEntry: + case *btrfsitem.DirEntry: textui.Fprintf(out, "\t\tlocation %v type %v\n", fmtKey(body.Location), body.Type) textui.Fprintf(out, "\t\ttransid %v data_len %v name_len %v\n", @@ -155,7 +155,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri } // case btrfsitem.DIR_LOG_INDEX_KEY, btrfsitem.DIR_LOG_ITEM_KEY: // // TODO - case btrfsitem.Root: + case *btrfsitem.Root: textui.Fprintf(out, "\t\tgeneration %v root_dirid %v bytenr %d byte_limit %v bytes_used %v\n", body.Generation, body.RootDirID, body.ByteNr, body.ByteLimit, body.BytesUsed) textui.Fprintf(out, "\t\tlast_snapshot %v flags %v refs %v\n", @@ -175,7 +175,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri textui.Fprintf(out, "\t\tstime %v\n", fmtTime(body.STime)) textui.Fprintf(out, "\t\trtime %v\n", fmtTime(body.RTime)) } - case btrfsitem.RootRef: + case *btrfsitem.RootRef: var tag string switch item.Key.ItemType { case btrfsitem.ROOT_REF_KEY: @@ -187,7 +187,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri } textui.Fprintf(out, "\t\troot %v key dirid %v sequence %v name %s\n", tag, body.DirID, body.Sequence, body.Name) - case btrfsitem.Extent: + case *btrfsitem.Extent: textui.Fprintf(out, "\t\trefs %v gen %v flags %v\n", body.Head.Refs, body.Head.Generation, body.Head.Flags) if body.Head.Flags.Has(btrfsitem.EXTENT_FLAG_TREE_BLOCK) { @@ -195,7 +195,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri fmtKey(body.Info.Key), body.Info.Level) } printExtentInlineRefs(out, body.Refs) - case btrfsitem.Metadata: + case *btrfsitem.Metadata: textui.Fprintf(out, "\t\trefs %v gen %v flags %v\n", body.Head.Refs, body.Head.Generation, body.Head.Flags) textui.Fprintf(out, "\t\ttree block skinny level %v\n", item.Key.Offset) @@ -204,7 +204,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri // // TODO // case btrfsitem.SHARED_DATA_REF_KEY: // // TODO - case btrfsitem.ExtentCSum: + case *btrfsitem.ExtentCSum: start := btrfsvol.LogicalAddr(item.Key.Offset) textui.Fprintf(out, "\t\trange start %d end %d length %d", start, start.Add(body.Size()), body.Size()) @@ -222,7 +222,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri return nil }) textui.Fprintf(out, "\n") - case btrfsitem.FileExtent: + case *btrfsitem.FileExtent: textui.Fprintf(out, "\t\tgeneration %v type %v\n", body.Generation, body.Type) switch body.Type { @@ -249,15 +249,15 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri default: textui.Fprintf(out, "\t\t(error) unknown file extent type %v", body.Type) } - case btrfsitem.BlockGroup: + case *btrfsitem.BlockGroup: textui.Fprintf(out, "\t\tblock group used %v chunk_objectid %v flags %v\n", body.Used, body.ChunkObjectID, body.Flags) - case btrfsitem.FreeSpaceInfo: + case *btrfsitem.FreeSpaceInfo: textui.Fprintf(out, "\t\tfree space info extent count %v flags %d\n", body.ExtentCount, body.Flags) - case btrfsitem.FreeSpaceBitmap: + case *btrfsitem.FreeSpaceBitmap: textui.Fprintf(out, "\t\tfree space bitmap\n") - case btrfsitem.Chunk: + case *btrfsitem.Chunk: textui.Fprintf(out, "\t\tlength %d owner %d stripe_len %v type %v\n", body.Head.Size, body.Head.Owner, body.Head.StripeLen, body.Head.Type) textui.Fprintf(out, "\t\tio_align %v io_width %v sector_size %v\n", @@ -270,7 +270,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri textui.Fprintf(out, "\t\t\tdev_uuid %v\n", stripe.DeviceUUID) } - case btrfsitem.Dev: + case *btrfsitem.Dev: textui.Fprintf(out, ""+ "\t\tdevid %d total_bytes %v bytes_used %v\n"+ "\t\tio_align %v io_width %v sector_size %v type %v\n"+ @@ -284,18 +284,18 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri body.SeekSpeed, body.Bandwidth, body.DevUUID, body.FSUUID) - case btrfsitem.DevExtent: + case *btrfsitem.DevExtent: textui.Fprintf(out, ""+ "\t\tdev extent chunk_tree %d\n"+ "\t\tchunk_objectid %v chunk_offset %d length %d\n"+ "\t\tchunk_tree_uuid %v\n", body.ChunkTree, body.ChunkObjectID, body.ChunkOffset, body.Length, body.ChunkTreeUUID) - case btrfsitem.QGroupStatus: + case *btrfsitem.QGroupStatus: textui.Fprintf(out, ""+ "\t\tversion %v generation %v flags %v scan %d\n", body.Version, body.Generation, body.Flags, body.RescanProgress) - case btrfsitem.QGroupInfo: + case *btrfsitem.QGroupInfo: textui.Fprintf(out, ""+ "\t\tgeneration %v\n"+ "\t\treferenced %d referenced_compressed %d\n"+ @@ -303,7 +303,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri body.Generation, body.ReferencedBytes, body.ReferencedBytesCompressed, body.ExclusiveBytes, body.ExclusiveBytesCompressed) - case btrfsitem.QGroupLimit: + case *btrfsitem.QGroupLimit: textui.Fprintf(out, ""+ "\t\tflags %x\n"+ "\t\tmax_referenced %d max_exclusive %d\n"+ @@ -311,11 +311,11 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri uint64(body.Flags), body.MaxReferenced, body.MaxExclusive, body.RsvReferenced, body.RsvExclusive) - case btrfsitem.UUIDMap: + case *btrfsitem.UUIDMap: textui.Fprintf(out, "\t\tsubvol_id %d\n", body.ObjID) // case btrfsitem.STRING_ITEM_KEY: // // TODO - case btrfsitem.DevStats: + case *btrfsitem.DevStats: textui.Fprintf(out, "\t\tpersistent item objectid %v offset %v\n", item.Key.ObjectID.Format(item.Key.ItemType), item.Key.Offset) switch item.Key.ObjectID { @@ -332,7 +332,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri } // case btrfsitem.TEMPORARY_ITEM_KEY: // // TODO - case btrfsitem.Empty: + case *btrfsitem.Empty: switch item.Key.ItemType { case btrfsitem.ORPHAN_ITEM_KEY: // 48 textui.Fprintf(out, "\t\torphan item\n") @@ -351,7 +351,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri default: textui.Fprintf(out, "\t\t(error) unhandled empty item type: %v\n", item.Key.ItemType) } - case btrfsitem.Error: + case *btrfsitem.Error: textui.Fprintf(out, "\t\t(error) error item: %v\n", body.Err) default: textui.Fprintf(out, "\t\t(error) unhandled item type: %T\n", body) @@ -423,10 +423,10 @@ func printExtentInlineRefs(out io.Writer, refs []btrfsitem.ExtentInlineRef) { default: textui.Fprintf(out, "\t\t(error) unexpected empty sub-item type: %v\n", ref.Type) } - case btrfsitem.ExtentDataRef: + case *btrfsitem.ExtentDataRef: textui.Fprintf(out, "\t\textent data backref root %v objectid %v offset %v count %v\n", subitem.Root, subitem.ObjectID, subitem.Offset, subitem.Count) - case btrfsitem.SharedDataRef: + case *btrfsitem.SharedDataRef: textui.Fprintf(out, "\t\tshared data backref parent %v count %v\n", ref.Offset, subitem.Count) default: -- cgit v1.2.3-54-g00ecf From 6d62529a4badae01b4b1c22dbf3f0e462a908a0b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 4 Feb 2023 01:11:17 -0700 Subject: tree-wide: Cache all calls to binstruct.StaticSize --- lib/btrfs/btrfstree/types_node.go | 47 +++++++++++++++++------------- lib/btrfs/btrfstree/types_superblock.go | 4 +-- lib/btrfs/io1_pv.go | 6 ++-- lib/btrfsprogs/btrfsinspect/print_tree.go | 4 ++- lib/btrfsprogs/btrfsinspect/scandevices.go | 4 +-- 5 files changed, 37 insertions(+), 28 deletions(-) (limited to 'lib/btrfsprogs/btrfsinspect/print_tree.go') diff --git a/lib/btrfs/btrfstree/types_node.go b/lib/btrfs/btrfstree/types_node.go index de493d6..85aae23 100644 --- a/lib/btrfs/btrfstree/types_node.go +++ b/lib/btrfs/btrfstree/types_node.go @@ -21,6 +21,13 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) +var ( + nodeHeaderSize = binstruct.StaticSize(NodeHeader{}) + keyPointerSize = binstruct.StaticSize(KeyPointer{}) + itemHeaderSize = binstruct.StaticSize(ItemHeader{}) + csumSize = binstruct.StaticSize(btrfssum.CSum{}) +) + type NodeFlags uint64 const sizeofNodeFlags = 7 @@ -103,11 +110,11 @@ type NodeHeader struct { // MaxItems returns the maximum possible valid value of // .Head.NumItems. func (node Node) MaxItems() uint32 { - bodyBytes := node.Size - uint32(binstruct.StaticSize(NodeHeader{})) + bodyBytes := node.Size - uint32(nodeHeaderSize) if node.Head.Level > 0 { - return bodyBytes / uint32(binstruct.StaticSize(KeyPointer{})) + return bodyBytes / uint32(keyPointerSize) } else { - return bodyBytes / uint32(binstruct.StaticSize(ItemHeader{})) + return bodyBytes / uint32(itemHeaderSize) } } @@ -144,7 +151,7 @@ func (node Node) CalculateChecksum() (btrfssum.CSum, error) { if err != nil { return btrfssum.CSum{}, err } - return node.ChecksumType.Sum(data[binstruct.StaticSize(btrfssum.CSum{}):]) + return node.ChecksumType.Sum(data[csumSize:]) } func (node Node) ValidateChecksum() error { @@ -165,17 +172,16 @@ func (node *Node) UnmarshalBinary(nodeBuf []byte) (int, error) { Size: uint32(len(nodeBuf)), ChecksumType: node.ChecksumType, } - if len(nodeBuf) <= binstruct.StaticSize(NodeHeader{}) { + if len(nodeBuf) <= nodeHeaderSize { return 0, fmt.Errorf("size must be greater than %v, but is %v", - binstruct.StaticSize(NodeHeader{}), - len(nodeBuf)) + nodeHeaderSize, len(nodeBuf)) } n, err := binstruct.Unmarshal(nodeBuf, &node.Head) if err != nil { return n, err - } else if n != binstruct.StaticSize(NodeHeader{}) { + } else if n != nodeHeaderSize { return n, fmt.Errorf("header consumed %v bytes but expected %v", - n, binstruct.StaticSize(NodeHeader{})) + n, nodeHeaderSize) } if node.Head.Level > 0 { _n, err := node.unmarshalInternal(nodeBuf[n:]) @@ -201,10 +207,9 @@ func (node Node) MarshalBinary() ([]byte, error) { if node.Size == 0 { return nil, fmt.Errorf(".Size must be set") } - if node.Size <= uint32(binstruct.StaticSize(NodeHeader{})) { + if node.Size <= uint32(nodeHeaderSize) { return nil, fmt.Errorf(".Size must be greater than %v, but is %v", - binstruct.StaticSize(NodeHeader{}), - node.Size) + nodeHeaderSize, node.Size) } if node.Head.Level > 0 { node.Head.NumItems = uint32(len(node.BodyInternal)) @@ -217,19 +222,19 @@ func (node Node) MarshalBinary() ([]byte, error) { if bs, err := binstruct.Marshal(node.Head); err != nil { return buf, err } else { - if len(bs) != binstruct.StaticSize(NodeHeader{}) { + if len(bs) != nodeHeaderSize { return nil, fmt.Errorf("header is %v bytes but expected %v", - len(bs), binstruct.StaticSize(NodeHeader{})) + len(bs), nodeHeaderSize) } copy(buf, bs) } if node.Head.Level > 0 { - if err := node.marshalInternalTo(buf[binstruct.StaticSize(NodeHeader{}):]); err != nil { + if err := node.marshalInternalTo(buf[nodeHeaderSize:]); err != nil { return buf, err } } else { - if err := node.marshalLeafTo(buf[binstruct.StaticSize(NodeHeader{}):]); err != nil { + if err := node.marshalLeafTo(buf[nodeHeaderSize:]); err != nil { return buf, err } } @@ -374,9 +379,9 @@ func (node *Node) LeafFreeSpace() uint32 { panic(fmt.Errorf("Node.LeafFreeSpace: not a leaf node")) } freeSpace := node.Size - freeSpace -= uint32(binstruct.StaticSize(NodeHeader{})) + freeSpace -= uint32(nodeHeaderSize) for _, item := range node.BodyLeaf { - freeSpace -= uint32(binstruct.StaticSize(ItemHeader{})) + freeSpace -= uint32(itemHeaderSize) bs, _ := binstruct.Marshal(item.Body) freeSpace -= uint32(len(bs)) } @@ -423,11 +428,11 @@ var bytePool containers.SlicePool[byte] // *NodeError[Addr]. Notable errors that may be inside of the // NodeError are ErrNotANode and *IOError. func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp NodeExpectations) (*diskio.Ref[Addr, Node], error) { - if int(sb.NodeSize) < binstruct.StaticSize(NodeHeader{}) { + if int(sb.NodeSize) < nodeHeaderSize { return nil, &NodeError[Addr]{ Op: "btrfstree.ReadNode", NodeAddr: addr, Err: fmt.Errorf("superblock.NodeSize=%v is too small to contain even a node header (%v bytes)", - sb.NodeSize, binstruct.StaticSize(NodeHeader{})), + sb.NodeSize, nodeHeaderSize), } } nodeBuf := bytePool.Get(int(sb.NodeSize)) @@ -461,7 +466,7 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N } stored := nodeRef.Data.Head.Checksum - calced, err := nodeRef.Data.ChecksumType.Sum(nodeBuf[binstruct.StaticSize(btrfssum.CSum{}):]) + calced, err := nodeRef.Data.ChecksumType.Sum(nodeBuf[csumSize:]) if err != nil { bytePool.Put(nodeBuf) return nodeRef, &NodeError[Addr]{Op: "btrfstree.ReadNode", NodeAddr: addr, Err: err} diff --git a/lib/btrfs/btrfstree/types_superblock.go b/lib/btrfs/btrfstree/types_superblock.go index 9258f9a..140d4a1 100644 --- a/lib/btrfs/btrfstree/types_superblock.go +++ b/lib/btrfs/btrfstree/types_superblock.go @@ -1,4 +1,4 @@ -// Copyright (C) 2022 Luke Shumaker +// Copyright (C) 2022-2023 Luke Shumaker // // SPDX-License-Identifier: GPL-2.0-or-later @@ -81,7 +81,7 @@ func (sb Superblock) CalculateChecksum() (btrfssum.CSum, error) { if err != nil { return btrfssum.CSum{}, err } - return sb.ChecksumType.Sum(data[binstruct.StaticSize(btrfssum.CSum{}):]) + return sb.ChecksumType.Sum(data[csumSize:]) } func (sb Superblock) ValidateChecksum() error { diff --git a/lib/btrfs/io1_pv.go b/lib/btrfs/io1_pv.go index 0e7cd9c..72d33f5 100644 --- a/lib/btrfs/io1_pv.go +++ b/lib/btrfs/io1_pv.go @@ -1,4 +1,4 @@ -// Copyright (C) 2022 Luke Shumaker +// Copyright (C) 2022-2023 Luke Shumaker // // SPDX-License-Identifier: GPL-2.0-or-later @@ -28,11 +28,13 @@ var SuperblockAddrs = []btrfsvol.PhysicalAddr{ 0x40_0000_0000, // 256GiB } +var superblockSize = binstruct.StaticSize(btrfstree.Superblock{}) + func (dev *Device) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Superblock], error) { if dev.cacheSuperblocks != nil { return dev.cacheSuperblocks, nil } - superblockSize := btrfsvol.PhysicalAddr(binstruct.StaticSize(btrfstree.Superblock{})) + superblockSize := btrfsvol.PhysicalAddr(superblockSize) sz := dev.Size() diff --git a/lib/btrfsprogs/btrfsinspect/print_tree.go b/lib/btrfsprogs/btrfsinspect/print_tree.go index 409ce0c..8acf9cc 100644 --- a/lib/btrfsprogs/btrfsinspect/print_tree.go +++ b/lib/btrfsprogs/btrfsinspect/print_tree.go @@ -92,6 +92,8 @@ func DumpTrees(ctx context.Context, out io.Writer, fs *btrfs.FS) { textui.Fprintf(out, "uuid %v\n", superblock.FSUUID) } +var nodeHeaderSize = binstruct.StaticSize(btrfstree.NodeHeader{}) + // printTree mimics btrfs-progs // kernel-shared/print-tree.c:btrfs_print_tree() and // kernel-shared/print-tree.c:btrfs_print_leaf() @@ -100,7 +102,7 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri handlers := btrfstree.TreeWalkHandler{ Node: func(path btrfstree.TreePath, nodeRef *diskio.Ref[btrfsvol.LogicalAddr, btrfstree.Node]) error { printHeaderInfo(out, nodeRef.Data) - itemOffset = nodeRef.Data.Size - uint32(binstruct.StaticSize(btrfstree.NodeHeader{})) + itemOffset = nodeRef.Data.Size - uint32(nodeHeaderSize) return nil }, PreKeyPointer: func(_ btrfstree.TreePath, item btrfstree.KeyPointer) error { diff --git a/lib/btrfsprogs/btrfsinspect/scandevices.go b/lib/btrfsprogs/btrfsinspect/scandevices.go index 91b5136..0cfee5b 100644 --- a/lib/btrfsprogs/btrfsinspect/scandevices.go +++ b/lib/btrfsprogs/btrfsinspect/scandevices.go @@ -105,6 +105,8 @@ func (s scanStats) String() string { s.NumFoundExtentCSums) } +var sbSize = btrfsvol.PhysicalAddr(binstruct.StaticSize(btrfstree.Superblock{})) + // 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) { @@ -114,8 +116,6 @@ func ScanOneDevice(ctx context.Context, dev *btrfs.Device, sb btrfstree.Superblo FoundNodes: make(map[btrfsvol.LogicalAddr][]btrfsvol.PhysicalAddr), } - sbSize := btrfsvol.PhysicalAddr(binstruct.StaticSize(btrfstree.Superblock{})) - devSize := dev.Size() if sb.NodeSize < sb.SectorSize { return result, fmt.Errorf("node_size(%v) < sector_size(%v)", -- cgit v1.2.3-54-g00ecf