diff options
Diffstat (limited to 'lib/btrfs/btrfsitem')
22 files changed, 199 insertions, 49 deletions
diff --git a/lib/btrfs/btrfsitem/item_blockgroup.go b/lib/btrfs/btrfsitem/item_blockgroup.go index ae0ca12..dc561bd 100644 --- a/lib/btrfs/btrfsitem/item_blockgroup.go +++ b/lib/btrfs/btrfsitem/item_blockgroup.go @@ -10,8 +10,20 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" ) -// key.objectid = logical_addr -// key.offset = size of chunk +// A BlockGroup tracks allocation of the logical address space. +// +// Compare with: +// - DevExtents, which track allocation of the physical address space. +// - Chunks, which map logical addresses to physical addresses. +// +// The relationship between the three is +// +// DevExtent---[many:one]---Chunk---[one:one]---BlockGroup +// +// Key: +// +// key.objectid = logical_addr +// key.offset = size of chunk type BlockGroup struct { // trivial BLOCK_GROUP_ITEM=192 Used int64 `bin:"off=0, siz=8"` ChunkObjectID btrfsprim.ObjID `bin:"off=8, siz=8"` // always FIRST_CHUNK_TREE_OBJECTID diff --git a/lib/btrfs/btrfsitem/item_chunk.go b/lib/btrfs/btrfsitem/item_chunk.go index 2280a0b..607df75 100644 --- a/lib/btrfs/btrfsitem/item_chunk.go +++ b/lib/btrfs/btrfsitem/item_chunk.go @@ -11,10 +11,20 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/containers" ) -// Maps logical address to physical. +// A Chunk maps logical addresses to physical addresses. // -// key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID -// key.offset = logical_addr +// Compare with: +// - DevExtents, which track allocation of the physical address space. +// - BlockGroups, which track allocation of the logical address space. +// +// The relationship between the three is +// +// DevExtent---[many:one]---Chunk---[one:one]---BlockGroup +// +// Key: +// +// key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID +// key.offset = logical_addr type Chunk struct { // complex CHUNK_ITEM=228 Head ChunkHeader Stripes []ChunkStripe diff --git a/lib/btrfs/btrfsitem/item_dev.go b/lib/btrfs/btrfsitem/item_dev.go index 188711e..7fd6833 100644 --- a/lib/btrfs/btrfsitem/item_dev.go +++ b/lib/btrfs/btrfsitem/item_dev.go @@ -10,8 +10,12 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" ) -// key.objectid = BTRFS_DEV_ITEMS_OBJECTID -// key.offset = device_id (starting at 1) +// A Dev describes a physical volume that is part of the filesystem. +// +// Key: +// +// key.objectid = BTRFS_DEV_ITEMS_OBJECTID +// key.offset = device_id (starting at 1) type Dev struct { // trivial DEV_ITEM=216 DevID btrfsvol.DeviceID `bin:"off=0x0, siz=0x8"` diff --git a/lib/btrfs/btrfsitem/item_devextent.go b/lib/btrfs/btrfsitem/item_devextent.go index cade165..6998277 100644 --- a/lib/btrfs/btrfsitem/item_devextent.go +++ b/lib/btrfs/btrfsitem/item_devextent.go @@ -10,8 +10,23 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" ) -// key.objectid = device_id -// key.offset = physical_addr +// A DevExtent tracks allocation of the physical address space. +// +// Compare with: +// - BlockGroups, which track allocation of the logical address space. +// - Chunks, which map logical addresses to physical addresses. +// +// The relationship between the three is +// +// DevExtent---[many:one]---Chunk---[one:one]---BlockGroup +// +// The device ID identifies which Dev item describes the physical +// volume that the DevExtent is on. +// +// Key: +// +// key.objectid = device_id +// key.offset = physical_addr type DevExtent struct { // trivial DEV_EXTENT=204 ChunkTree btrfsprim.ObjID `bin:"off=0, siz=8"` // always CHUNK_TREE_OBJECTID ChunkObjectID btrfsprim.ObjID `bin:"off=8, siz=8"` // which chunk within .ChunkTree owns this extent, always FIRST_CHUNK_TREE_OBJECTID diff --git a/lib/btrfs/btrfsitem/item_dir.go b/lib/btrfs/btrfsitem/item_dir.go index c1b3c09..cd16d57 100644 --- a/lib/btrfs/btrfsitem/item_dir.go +++ b/lib/btrfs/btrfsitem/item_dir.go @@ -19,10 +19,14 @@ func NameHash(dat []byte) uint64 { return uint64(^crc32.Update(1, crc32.MakeTable(crc32.Castagnoli), dat)) } -// key.objectid = inode of directory containing this entry -// key.offset = -// - for DIR_ITEM and XATTR_ITEM = NameHash(name) -// - for DIR_INDEX = index id in the directory (starting at 2, because "." and "..") +// A DirEntry is an member of a directory. +// +// Key: +// +// key.objectid = inode of directory containing this entry +// key.offset = one of: +// - for DIR_ITEM and XATTR_ITEM = NameHash(name) +// - for DIR_INDEX = index id in the directory (starting at 2, because of "." and "..") type DirEntry struct { // complex DIR_ITEM=84 DIR_INDEX=96 XATTR_ITEM=24 Location btrfsprim.Key `bin:"off=0x0, siz=0x11"` TransID int64 `bin:"off=0x11, siz=8"` diff --git a/lib/btrfs/btrfsitem/item_extent.go b/lib/btrfs/btrfsitem/item_extent.go index 871ed90..edfef7c 100644 --- a/lib/btrfs/btrfsitem/item_extent.go +++ b/lib/btrfs/btrfsitem/item_extent.go @@ -13,8 +13,22 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) -// key.objectid = laddr of the extent -// key.offset = length of the extent +// Extent items map from regions in the logical address space to +// regions in a file. +// +// Compare with: +// +// - Metadata, which are like Extents but without .Info. +// - FileExtents, which map from regions in a file to regions in the +// logical address space. +// +// An Extent may contain (inline or not) several ExtentDataRef items +// and/or ShareDataRef items. +// +// Key: +// +// key.objectid = laddr of the extent +// key.offset = length of the extent type Extent struct { // complex EXTENT_ITEM=168 Head ExtentHeader Info TreeBlockInfo // only if .Head.Flags.Has(EXTENT_FLAG_TREE_BLOCK) diff --git a/lib/btrfs/btrfsitem/item_extentcsum.go b/lib/btrfs/btrfsitem/item_extentcsum.go index dfa166d..a963c16 100644 --- a/lib/btrfs/btrfsitem/item_extentcsum.go +++ b/lib/btrfs/btrfsitem/item_extentcsum.go @@ -11,8 +11,12 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" ) -// key.objectid = BTRFS_EXTENT_CSUM_OBJECTID -// key.offset = laddr of checksummed region +// An ExtentCSum checksums regions of the logical address space. +// +// Key: +// +// key.objectid = BTRFS_EXTENT_CSUM_OBJECTID +// key.offset = laddr of checksummed region type ExtentCSum struct { // trivial EXTENT_CSUM=128 // Checksum of each sector starting at key.offset btrfssum.SumRun[btrfsvol.LogicalAddr] diff --git a/lib/btrfs/btrfsitem/item_extentdataref.go b/lib/btrfs/btrfsitem/item_extentdataref.go index 6f2257b..bd7bb04 100644 --- a/lib/btrfs/btrfsitem/item_extentdataref.go +++ b/lib/btrfs/btrfsitem/item_extentdataref.go @@ -9,8 +9,12 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) -// key.objectid = laddr of the extent being referenced -// key.offset = crc32c([root,objectid,offset]) +// ExtentDataRef is part of an Extent. +// +// Key: +// +// key.objectid = laddr of the extent being referenced +// key.offset = crc32c([root,objectid,offset]) type ExtentDataRef struct { // trivial EXTENT_DATA_REF=178 Root btrfsprim.ObjID `bin:"off=0, siz=8"` // subvolume tree ID that references this extent ObjectID btrfsprim.ObjID `bin:"off=8, siz=8"` // inode number that references this extent within the .Root subvolume diff --git a/lib/btrfs/btrfsitem/item_fileextent.go b/lib/btrfs/btrfsitem/item_fileextent.go index 6b08897..df3d371 100644 --- a/lib/btrfs/btrfsitem/item_fileextent.go +++ b/lib/btrfs/btrfsitem/item_fileextent.go @@ -12,8 +12,19 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" ) -// key.objectid = inode -// key.offset = offset within file +// FileExtent items map from regions in a file to regions in the +// logical address space. +// +// Compare with: +// +// - Extents, which map from regions in the logical address space to +// regions in a file. +// - Metadata, which are like Extents but without .Info. +// +// Key: +// +// key.objectid = inode +// key.offset = offset within file type FileExtent struct { // complex EXTENT_DATA=108 Generation btrfsprim.Generation `bin:"off=0x0, siz=0x8"` // transaction ID that created this extent RAMBytes int64 `bin:"off=0x8, siz=0x8"` // upper bound of what compressed data will decompress to diff --git a/lib/btrfs/btrfsitem/item_freespacebitmap.go b/lib/btrfs/btrfsitem/item_freespacebitmap.go index ebc00e4..d70a2b5 100644 --- a/lib/btrfs/btrfsitem/item_freespacebitmap.go +++ b/lib/btrfs/btrfsitem/item_freespacebitmap.go @@ -4,8 +4,13 @@ package btrfsitem -// key.objectid = object ID of the FreeSpaceInfo (logical_addr) -// key.offset = offset of the FreeSpaceInfo (size) +// FreeSpaceBitmap is used in conjunction with FreeSpaceInfo for +// highly-fragmented blockgroups. +// +// Key: +// +// key.objectid = object ID of the FreeSpaceInfo (logical_addr) +// key.offset = offset of the FreeSpaceInfo (size) type FreeSpaceBitmap struct { // complex FREE_SPACE_BITMAP=200 Bitmap []byte } diff --git a/lib/btrfs/btrfsitem/item_freespaceinfo.go b/lib/btrfs/btrfsitem/item_freespaceinfo.go index 9b886af..7782d27 100644 --- a/lib/btrfs/btrfsitem/item_freespaceinfo.go +++ b/lib/btrfs/btrfsitem/item_freespaceinfo.go @@ -9,8 +9,14 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) -// key.objectid = object ID of the BlockGroup (logical_addr) -// key.offset = offset of the BlockGroup (size) +// FreeSpaceInfo is the main way (v2) that free space is tracked in a +// BlockGroup. For highly-fragmented blockgorups, it may be augmented +// by a FreeSpaceBitmap. +// +// Key: +// +// key.objectid = object ID of the BlockGroup (logical_addr) +// key.offset = offset of the BlockGroup (size) type FreeSpaceInfo struct { // trivial FREE_SPACE_INFO=198 ExtentCount int32 `bin:"off=0, siz=4"` Flags FreeSpaceFlags `bin:"off=4, siz=4"` diff --git a/lib/btrfs/btrfsitem/item_inode.go b/lib/btrfs/btrfsitem/item_inode.go index 6951c76..0b6a1c2 100644 --- a/lib/btrfs/btrfsitem/item_inode.go +++ b/lib/btrfs/btrfsitem/item_inode.go @@ -10,8 +10,10 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) -// key.objectid = inode number -// key.offset = 0 +// Inode is a file/dir/whatever in the filesystem. +// +// key.objectid = inode number +// key.offset = 0 type Inode struct { // trivial INODE_ITEM=1 Generation btrfsprim.Generation `bin:"off=0x00, siz=0x08"` TransID int64 `bin:"off=0x08, siz=0x08"` diff --git a/lib/btrfs/btrfsitem/item_inoderef.go b/lib/btrfs/btrfsitem/item_inoderef.go index 074b26d..f38295d 100644 --- a/lib/btrfs/btrfsitem/item_inoderef.go +++ b/lib/btrfs/btrfsitem/item_inoderef.go @@ -12,11 +12,16 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/containers" ) -// key.objectid = inode number of the file -// key.offset = inode number of the parent directory +// An InodeRefs item is a set of back-references that point to a given +// Inode. // -// Might have multiple entries if the same file has multiple hardlinks -// in the same directory. +// Key: +// +// key.objectid = inode number of the file +// key.offset = inode number of the parent directory +// +// There might be multiple back-references in a single InodeRef item +// if the same file has multiple hardlinks in the same directory. type InodeRefs struct { // complex INODE_REF=12 Refs []InodeRef } diff --git a/lib/btrfs/btrfsitem/item_metadata.go b/lib/btrfs/btrfsitem/item_metadata.go index db2315e..10ae994 100644 --- a/lib/btrfs/btrfsitem/item_metadata.go +++ b/lib/btrfs/btrfsitem/item_metadata.go @@ -8,7 +8,22 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" ) +// Metadata items map from regions in the logical address space to +// regions in a file. +// // Metadata is like Extent, but doesn't have .Info. +// +// Compare with: +// +// - Extents, which are the same as Metadata, but have an extra +// .Info member. +// - FileExtents, which map from regions in a file to regions in the +// logical address space. +// +// Key: +// +// key.objectid = laddr of the extent +// key.offset = length of the extent type Metadata struct { // complex METADATA_ITEM=169 Head ExtentHeader Refs []ExtentInlineRef diff --git a/lib/btrfs/btrfsitem/item_qgroupinfo.go b/lib/btrfs/btrfsitem/item_qgroupinfo.go index 6699030..2bf38f6 100644 --- a/lib/btrfs/btrfsitem/item_qgroupinfo.go +++ b/lib/btrfs/btrfsitem/item_qgroupinfo.go @@ -9,8 +9,13 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) -// key.objectid = 0 -// key.offset = ID of the qgroup +// QGroupInfo tracks the amount of space used by a given qgroup in the +// containing subvolume. +// +// Key: +// +// key.objectid = 0 +// key.offset = ID of the qgroup type QGroupInfo struct { // trivial QGROUP_INFO=242 Generation btrfsprim.Generation `bin:"off=0, siz=8"` ReferencedBytes uint64 `bin:"off=8, siz=8"` diff --git a/lib/btrfs/btrfsitem/item_qgrouplimit.go b/lib/btrfs/btrfsitem/item_qgrouplimit.go index 47f7eca..e303b04 100644 --- a/lib/btrfs/btrfsitem/item_qgrouplimit.go +++ b/lib/btrfs/btrfsitem/item_qgrouplimit.go @@ -34,8 +34,14 @@ func (f QGroupLimitFlags) String() string { return fmtutil.BitfieldString(f, qgroupLimitFlagNames, fmtutil.HexNone) } -// key.objectid = 0 -// key.offset = ID of the qgroup +// QGroupLimit configures the maximum permissible amount of space that +// a given qgroup can consume (tracked in a QGroupInfo item) on the +// containing subvolume. +// +// Key: +// +// key.objectid = 0 +// key.offset = ID of the qgroup type QGroupLimit struct { // trivial QGROUP_LIMIT=244 Flags QGroupLimitFlags `bin:"off=0, siz=8"` MaxReferenced uint64 `bin:"off=8, siz=8"` diff --git a/lib/btrfs/btrfsitem/item_qgroupstatus.go b/lib/btrfs/btrfsitem/item_qgroupstatus.go index 346c913..b140371 100644 --- a/lib/btrfs/btrfsitem/item_qgroupstatus.go +++ b/lib/btrfs/btrfsitem/item_qgroupstatus.go @@ -32,8 +32,14 @@ func (f QGroupStatusFlags) String() string { const QGroupStatusVersion uint64 = 1 -// key.objectid = 0 -// key.offset = 0 +// A QGroupStatus holds the qgroup state of a subvolume (I think that +// implies that the QGroupStatus goes in the subvolume tree that it is +// describing?). +// +// Key: +// +// key.objectid = 0 +// key.offset = 0 type QGroupStatus struct { // trivial QGROUP_STATUS=240 Version uint64 `bin:"off=0, siz=8"` Generation btrfsprim.Generation `bin:"off=8, siz=8"` diff --git a/lib/btrfs/btrfsitem/item_root.go b/lib/btrfs/btrfsitem/item_root.go index d39bd70..4ffad9a 100644 --- a/lib/btrfs/btrfsitem/item_root.go +++ b/lib/btrfs/btrfsitem/item_root.go @@ -11,10 +11,17 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/fmtutil" ) -// key.objectid = tree ID -// key.offset = either -// - 0 if objectid is one of the BTRFS_*_TREE_OBJECTID defines or a non-snapshot volume; or -// - transaction_id of when this snapshot was created +// A Root goes in the ROOT_TREE and defines one of the other trees in +// the filesystem. All trees have a Root item describing them, except +// for the ROOT_TREE, CHUNK_TREE, TREE_LOG, and BLOCK_GROUP_TREE, +// which are defined directly in the superblock. +// +// Key: +// +// key.objectid = tree ID +// key.offset = one of: +// - 0 if objectid is one of the BTRFS_*_TREE_OBJECTID defines or a non-snapshot volume; or +// - transaction_id of when this snapshot was created type Root struct { // trivial ROOT_ITEM=132 Inode Inode `bin:"off=0x000, siz=0xa0"` // ??? Generation btrfsprim.Generation `bin:"off=0x0a0, siz=0x08"` diff --git a/lib/btrfs/btrfsitem/item_rootref.go b/lib/btrfs/btrfsitem/item_rootref.go index 4179890..e40b278 100644 --- a/lib/btrfs/btrfsitem/item_rootref.go +++ b/lib/btrfs/btrfsitem/item_rootref.go @@ -12,10 +12,12 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) -// RootRefs link subvolumes parent→child for normal subvolumes and +// A RootRef links subvolumes parent→child for normal subvolumes and // base→snapshot for snapshot subvolumes. BACKREF items go the other // direction; child→parent and snapshot→base. // +// Key: +// // ROOT_REF | ROOT_BACKREF // key.objectid = ID of the parent subvolume | ID of the child subvolume // key.offset = ID of the child subvolume | ID of the parent subvolume diff --git a/lib/btrfs/btrfsitem/item_shareddataref.go b/lib/btrfs/btrfsitem/item_shareddataref.go index 6143a5c..5d88522 100644 --- a/lib/btrfs/btrfsitem/item_shareddataref.go +++ b/lib/btrfs/btrfsitem/item_shareddataref.go @@ -8,10 +8,12 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" ) -// key.objectid = laddr of the extent being referenced +// SharedDataRef is part of an Extent. // -// key.offset = laddr of the leaf node containing the FileExtent -// (EXTENT_DATA_KEY) for this reference. +// Key: +// +// key.objectid = laddr of the extent being referenced +// key.offset = laddr of the leaf node containing the FileExtent (EXTENT_DATA_KEY) for this reference. type SharedDataRef struct { // trivial SHARED_DATA_REF=184 Count int32 `bin:"off=0, siz=4"` // reference count binstruct.End `bin:"off=4"` diff --git a/lib/btrfs/btrfsitem/item_uuid.go b/lib/btrfs/btrfsitem/item_uuid.go index fca409d..a5ace33 100644 --- a/lib/btrfs/btrfsitem/item_uuid.go +++ b/lib/btrfs/btrfsitem/item_uuid.go @@ -11,11 +11,16 @@ import ( "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsprim" ) -// The Key for this item is a UUID, and the item is a subvolume IDs +// A UUIDMap item goes in the UUID_TREE and maps from a UUID to a +// btrfsprim.ObjID. +// +// The Key for this item is a UUID, and the item is a subvolume ID // that UUID maps to. // -// key.objectid = first half of UUID -// key.offset = second half of UUID +// Key: +// +// key.objectid = first half of UUID +// key.offset = second half of UUID type UUIDMap struct { // trivial UUID_SUBVOL=251 UUID_RECEIVED_SUBVOL=252 ObjID btrfsprim.ObjID `bin:"off=0, siz=8"` binstruct.End `bin:"off=8"` diff --git a/lib/btrfs/btrfsitem/items.go b/lib/btrfs/btrfsitem/items.go index 49d421f..a730447 100644 --- a/lib/btrfs/btrfsitem/items.go +++ b/lib/btrfs/btrfsitem/items.go @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: GPL-2.0-or-later +// Package btrfsitem contains the definitions of all "items" that may +// be stored in a btrfs tree. package btrfsitem import ( @@ -56,7 +58,11 @@ func (o *Error) UnmarshalBinary(dat []byte) (int, error) { return len(dat), nil } -// Rather than returning a separate error value, return an Error item. +// UnmarshalItem consumes the byte slice `dat`, unmarshaling it in to +// the item type specified by `key`. +// +// If there is an error, rather than returning a separate error value, +// return an Error item. func UnmarshalItem(key btrfsprim.Key, csumType btrfssum.CSumType, dat []byte) Item { var gotyp reflect.Type if key.ItemType == UNTYPED_KEY { |