diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/btrfs/btrfsitem/item_qgroupinfo.go | 21 | ||||
-rw-r--r-- | lib/btrfs/btrfsitem/item_qgrouplimit.go | 46 | ||||
-rw-r--r-- | lib/btrfs/btrfsitem/item_qgroupstatus.go | 43 | ||||
-rw-r--r-- | lib/btrfs/btrfsitem/items_gen.go | 9 | ||||
-rw-r--r-- | lib/btrfs/btrfsprim/itemtype.go | 6 | ||||
-rw-r--r-- | lib/btrfs/btrfsprim/objid.go | 2 | ||||
-rw-r--r-- | lib/btrfsprogs/btrfsinspect/print_tree.go | 30 |
7 files changed, 148 insertions, 9 deletions
diff --git a/lib/btrfs/btrfsitem/item_qgroupinfo.go b/lib/btrfs/btrfsitem/item_qgroupinfo.go new file mode 100644 index 0000000..8cceb0b --- /dev/null +++ b/lib/btrfs/btrfsitem/item_qgroupinfo.go @@ -0,0 +1,21 @@ +// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com> +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" +) + +// key.objectid = 0 +// key.offset = ID of the qgroup +type QGroupInfo struct { // QGROUP_INFO=242 + Generation btrfsprim.Generation `bin:"off=0, siz=8"` + ReferencedBytes uint64 `bin:"off=8, siz=8"` + ReferencedBytesCompressed uint64 `bin:"off=16, siz=8"` + ExclusiveBytes uint64 `bin:"off=24, siz=8"` + ExclusiveBytesCompressed uint64 `bin:"off=32, siz=8"` + binstruct.End `bin:"off=40"` +} diff --git a/lib/btrfs/btrfsitem/item_qgrouplimit.go b/lib/btrfs/btrfsitem/item_qgrouplimit.go new file mode 100644 index 0000000..9d1e05f --- /dev/null +++ b/lib/btrfs/btrfsitem/item_qgrouplimit.go @@ -0,0 +1,46 @@ +// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com> +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" +) + +type QGroupLimitFlags uint64 + +const ( + QGroupLimitFlagMaxRfer = 1 << iota + QGroupLimitFlagMaxExcl + QGroupLimitFlagRsvRfer + QGroupLimitFlagRsvExcl + QGroupLimitFlagRferCmpr + QGroupLimitFlagExclCmpr +) + +var qgroupLimitFlagNames = []string{ + "MAX_RFER", + "MAX_EXCL", + "RSV_RFER", + "RSV_EXCL", + "RFER_CMPR", + "EXCL_CMPR", +} + +func (f QGroupLimitFlags) Has(req QGroupLimitFlags) bool { return f&req == req } +func (f QGroupLimitFlags) String() string { + return fmtutil.BitfieldString(f, qgroupLimitFlagNames, fmtutil.HexNone) +} + +// key.objectid = 0 +// key.offset = ID of the qgroup +type QGroupLimit struct { // QGROUP_LIMIT=244 + Flags QGroupLimitFlags `bin:"off=0, siz=8"` + MaxReferenced uint64 `bin:"off=8, siz=8"` + MaxExclusive uint64 `bin:"off=16, siz=8"` + RsvReferenced uint64 `bin:"off=24, siz=8"` + RsvExclusive uint64 `bin:"off=32, siz=8"` + binstruct.End `bin:"off=40"` +} diff --git a/lib/btrfs/btrfsitem/item_qgroupstatus.go b/lib/btrfs/btrfsitem/item_qgroupstatus.go new file mode 100644 index 0000000..e7bd62c --- /dev/null +++ b/lib/btrfs/btrfsitem/item_qgroupstatus.go @@ -0,0 +1,43 @@ +// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com> +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package btrfsitem + +import ( + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" + "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" +) + +type QGroupStatusFlags uint64 + +const ( + QGroupStatusFlagOn QGroupStatusFlags = 1 << iota + QGroupStatusFlagRescan + QGroupStatusFlagInconsistent +) + +var qgroupStatusFlagNames = []string{ + "ON", + "RESCAN", + "INCONSISTENT", +} + +func (f QGroupStatusFlags) Has(req QGroupStatusFlags) bool { return f&req == req } +func (f QGroupStatusFlags) String() string { + return fmtutil.BitfieldString(f, qgroupStatusFlagNames, fmtutil.HexNone) +} + +const QGroupStatusVersion uint64 = 1 + +// key.objectid = 0 +// key.offset = 0 +type QGroupStatus struct { // QGROUP_STATUS=240 + Version uint64 `bin:"off=0, siz=8"` + Generation btrfsprim.Generation `bin:"off=8, siz=8"` + Flags QGroupStatusFlags `bin:"off=16, siz=8"` + RescanProgress btrfsvol.LogicalAddr `bin:"off=24, siz=8"` + binstruct.End `bin:"off=32"` +} diff --git a/lib/btrfs/btrfsitem/items_gen.go b/lib/btrfs/btrfsitem/items_gen.go index 0ae69d4..9daef81 100644 --- a/lib/btrfs/btrfsitem/items_gen.go +++ b/lib/btrfs/btrfsitem/items_gen.go @@ -27,7 +27,10 @@ const ( METADATA_ITEM_KEY = btrfsprim.METADATA_ITEM_KEY ORPHAN_ITEM_KEY = btrfsprim.ORPHAN_ITEM_KEY PERSISTENT_ITEM_KEY = btrfsprim.PERSISTENT_ITEM_KEY + QGROUP_INFO_KEY = btrfsprim.QGROUP_INFO_KEY + QGROUP_LIMIT_KEY = btrfsprim.QGROUP_LIMIT_KEY QGROUP_RELATION_KEY = btrfsprim.QGROUP_RELATION_KEY + QGROUP_STATUS_KEY = btrfsprim.QGROUP_STATUS_KEY ROOT_BACKREF_KEY = btrfsprim.ROOT_BACKREF_KEY ROOT_ITEM_KEY = btrfsprim.ROOT_ITEM_KEY ROOT_REF_KEY = btrfsprim.ROOT_REF_KEY @@ -59,7 +62,10 @@ var keytype2gotype = map[Type]reflect.Type{ METADATA_ITEM_KEY: reflect.TypeOf(Metadata{}), ORPHAN_ITEM_KEY: reflect.TypeOf(Empty{}), PERSISTENT_ITEM_KEY: reflect.TypeOf(DevStats{}), + QGROUP_INFO_KEY: reflect.TypeOf(QGroupInfo{}), + QGROUP_LIMIT_KEY: reflect.TypeOf(QGroupLimit{}), QGROUP_RELATION_KEY: reflect.TypeOf(Empty{}), + QGROUP_STATUS_KEY: reflect.TypeOf(QGroupStatus{}), ROOT_BACKREF_KEY: reflect.TypeOf(RootRef{}), ROOT_ITEM_KEY: reflect.TypeOf(Root{}), ROOT_REF_KEY: reflect.TypeOf(RootRef{}), @@ -91,6 +97,9 @@ func (FreeSpaceInfo) isItem() {} func (Inode) isItem() {} func (InodeRefs) isItem() {} func (Metadata) isItem() {} +func (QGroupInfo) isItem() {} +func (QGroupLimit) isItem() {} +func (QGroupStatus) isItem() {} func (Root) isItem() {} func (RootRef) isItem() {} func (SharedDataRef) isItem() {} diff --git a/lib/btrfs/btrfsprim/itemtype.go b/lib/btrfs/btrfsprim/itemtype.go index 5c7d0e8..0b6baee 100644 --- a/lib/btrfs/btrfsprim/itemtype.go +++ b/lib/btrfs/btrfsprim/itemtype.go @@ -25,7 +25,10 @@ const ( METADATA_ITEM_KEY = ItemType(169) ORPHAN_ITEM_KEY = ItemType(48) PERSISTENT_ITEM_KEY = ItemType(249) + QGROUP_INFO_KEY = ItemType(242) + QGROUP_LIMIT_KEY = ItemType(244) QGROUP_RELATION_KEY = ItemType(246) + QGROUP_STATUS_KEY = ItemType(240) ROOT_BACKREF_KEY = ItemType(144) ROOT_ITEM_KEY = ItemType(132) ROOT_REF_KEY = ItemType(156) @@ -58,7 +61,10 @@ func (t ItemType) String() string { METADATA_ITEM_KEY: "METADATA_ITEM", ORPHAN_ITEM_KEY: "ORPHAN_ITEM", PERSISTENT_ITEM_KEY: "PERSISTENT_ITEM", + QGROUP_INFO_KEY: "QGROUP_INFO", + QGROUP_LIMIT_KEY: "QGROUP_LIMIT", QGROUP_RELATION_KEY: "QGROUP_RELATION", + QGROUP_STATUS_KEY: "QGROUP_STATUS", ROOT_BACKREF_KEY: "ROOT_BACKREF", ROOT_ITEM_KEY: "ROOT_ITEM", ROOT_REF_KEY: "ROOT_REF", diff --git a/lib/btrfs/btrfsprim/objid.go b/lib/btrfs/btrfsprim/objid.go index 5ba213d..8ad290b 100644 --- a/lib/btrfs/btrfsprim/objid.go +++ b/lib/btrfs/btrfsprim/objid.go @@ -68,7 +68,7 @@ func (id ObjID) Format(typ ItemType) string { case DEV_EXTENT_KEY: return fmt.Sprintf("%d", int64(id)) case QGROUP_RELATION_KEY: - //nolint:gomnd // TODO: I'm not sure what the 48/16 bit split means. + //nolint:gomnd // The left 48 bits are the "qgroup level", and the right 16 bits are the subvolume ID. return fmt.Sprintf("%d/%d", uint64(id)>>48, uint64(id)&((1<<48)-1)) diff --git a/lib/btrfsprogs/btrfsinspect/print_tree.go b/lib/btrfsprogs/btrfsinspect/print_tree.go index 62d1d7b..3fc3a3f 100644 --- a/lib/btrfsprogs/btrfsinspect/print_tree.go +++ b/lib/btrfsprogs/btrfsinspect/print_tree.go @@ -291,12 +291,26 @@ func printTree(ctx context.Context, out io.Writer, fs *btrfs.FS, treeID btrfspri "\t\tchunk_tree_uuid %v\n", body.ChunkTree, body.ChunkObjectID, body.ChunkOffset, body.Length, body.ChunkTreeUUID) - // case btrfsitem.QGROUP_STATUS_KEY: - // // TODO - // case btrfsitem.QGROUP_INFO_KEY: - // // TODO - // case btrfsitem.QGROUP_LIMIT_KEY: - // // TODO + 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: + textui.Fprintf(out, ""+ + "\t\tgeneration %v\n"+ + "\t\treferenced %d referenced_compressed %d\n"+ + "\t\texclusive %d exclusive_compressed %d\n", + body.Generation, + body.ReferencedBytes, body.ReferencedBytesCompressed, + body.ExclusiveBytes, body.ExclusiveBytesCompressed) + case btrfsitem.QGroupLimit: + textui.Fprintf(out, ""+ + "\t\tflags %x\n"+ + "\t\tmax_referenced %d max_exclusive %d\n"+ + "\t\trsv_referenced %d rsv_exclusive %d\n", + uint64(body.Flags), + body.MaxReferenced, body.MaxExclusive, + body.RsvReferenced, body.RsvExclusive) case btrfsitem.UUIDMap: textui.Fprintf(out, "\t\tsubvol_id %d\n", body.ObjID) // case btrfsitem.STRING_ITEM_KEY: @@ -426,8 +440,8 @@ func fmtKey(key btrfsprim.Key) string { var out strings.Builder textui.Fprintf(&out, "key (%v %v", key.ObjectID.Format(key.ItemType), key.ItemType) switch key.ItemType { - case btrfsitem.QGROUP_RELATION_KEY: // TODO, btrfsitem.QGROUP_INFO_KEY, btrfsitem.QGROUP_LIMIT_KEY: - panic("TODO: printing qgroup items not yet implemented") + case btrfsitem.QGROUP_RELATION_KEY, btrfsitem.QGROUP_INFO_KEY, btrfsitem.QGROUP_LIMIT_KEY: + textui.Fprintf(&out, " %v)", btrfsprim.ObjID(key.Offset).Format(btrfsprim.QGROUP_RELATION_KEY)) case btrfsitem.UUID_SUBVOL_KEY, btrfsitem.UUID_RECEIVED_SUBVOL_KEY: textui.Fprintf(&out, " %#08x)", key.Offset) case btrfsitem.ROOT_ITEM_KEY: |