summaryrefslogtreecommitdiff
path: root/lib/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfs')
-rw-r--r--lib/btrfs/btrfsitem/item_blockgroup.go16
-rw-r--r--lib/btrfs/btrfsitem/item_chunk.go16
-rw-r--r--lib/btrfs/btrfsitem/item_dev.go8
-rw-r--r--lib/btrfs/btrfsitem/item_devextent.go19
-rw-r--r--lib/btrfs/btrfsitem/item_dir.go12
-rw-r--r--lib/btrfs/btrfsitem/item_extent.go18
-rw-r--r--lib/btrfs/btrfsitem/item_extentcsum.go8
-rw-r--r--lib/btrfs/btrfsitem/item_extentdataref.go8
-rw-r--r--lib/btrfs/btrfsitem/item_fileextent.go15
-rw-r--r--lib/btrfs/btrfsitem/item_freespacebitmap.go9
-rw-r--r--lib/btrfs/btrfsitem/item_freespaceinfo.go10
-rw-r--r--lib/btrfs/btrfsitem/item_inode.go6
-rw-r--r--lib/btrfs/btrfsitem/item_inoderef.go13
-rw-r--r--lib/btrfs/btrfsitem/item_metadata.go15
-rw-r--r--lib/btrfs/btrfsitem/item_qgroupinfo.go9
-rw-r--r--lib/btrfs/btrfsitem/item_qgrouplimit.go10
-rw-r--r--lib/btrfs/btrfsitem/item_qgroupstatus.go10
-rw-r--r--lib/btrfs/btrfsitem/item_root.go15
-rw-r--r--lib/btrfs/btrfsitem/item_rootref.go4
-rw-r--r--lib/btrfs/btrfsitem/item_shareddataref.go8
-rw-r--r--lib/btrfs/btrfsitem/item_uuid.go11
-rw-r--r--lib/btrfs/btrfsitem/items.go8
-rw-r--r--lib/btrfs/btrfsprim/key.go14
-rw-r--r--lib/btrfs/btrfsprim/misc.go2
-rw-r--r--lib/btrfs/btrfssum/csum.go2
-rw-r--r--lib/btrfs/btrfstree/btree.go2
-rw-r--r--lib/btrfs/btrfstree/btree_tree.go5
-rw-r--r--lib/btrfs/btrfstree/path.go34
-rw-r--r--lib/btrfs/btrfstree/types_node.go31
-rw-r--r--lib/btrfs/btrfsvol/lvm.go2
-rw-r--r--lib/btrfs/io1_pv.go2
-rw-r--r--lib/btrfs/io4_fs.go16
32 files changed, 263 insertions, 95 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 {
diff --git a/lib/btrfs/btrfsprim/key.go b/lib/btrfs/btrfsprim/key.go
index b07cc8c..5580c52 100644
--- a/lib/btrfs/btrfsprim/key.go
+++ b/lib/btrfs/btrfsprim/key.go
@@ -21,7 +21,10 @@ type Key struct {
const MaxOffset uint64 = math.MaxUint64
-// mimics print-tree.c:btrfs_print_key()
+// Format returns a human-friendly string representation of the Key,
+// according to which tree it appears in.
+//
+// The formatting of the key mimics print-tree.c:btrfs_print_key().
func (key Key) Format(tree ObjID) string {
switch tree {
case UUID_TREE_OBJECTID:
@@ -39,12 +42,11 @@ func (key Key) Format(tree ObjID) string {
return fmt.Sprintf("(%v %v -1)",
key.ObjectID.Format(tree),
key.ItemType)
- } else {
- return fmt.Sprintf("(%v %v %v)",
- key.ObjectID.Format(tree),
- key.ItemType,
- key.Offset)
}
+ return fmt.Sprintf("(%v %v %v)",
+ key.ObjectID.Format(tree),
+ key.ItemType,
+ key.Offset)
}
}
diff --git a/lib/btrfs/btrfsprim/misc.go b/lib/btrfs/btrfsprim/misc.go
index 38290d6..43ba306 100644
--- a/lib/btrfs/btrfsprim/misc.go
+++ b/lib/btrfs/btrfsprim/misc.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package btrfsprim contains primitive btrfs datatypes, that all
+// other btrfs sub-packages may make use of.
package btrfsprim
import (
diff --git a/lib/btrfs/btrfssum/csum.go b/lib/btrfs/btrfssum/csum.go
index 157371e..341eade 100644
--- a/lib/btrfs/btrfssum/csum.go
+++ b/lib/btrfs/btrfssum/csum.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package btrfssum contains the checksum types and algorithms that
+// btrfs uses.
package btrfssum
import (
diff --git a/lib/btrfs/btrfstree/btree.go b/lib/btrfs/btrfstree/btree.go
index 4c10ffa..89d4f9d 100644
--- a/lib/btrfs/btrfstree/btree.go
+++ b/lib/btrfs/btrfstree/btree.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package btrfstree contains core b+-tree implementation and
+// interfaces.
package btrfstree
import (
diff --git a/lib/btrfs/btrfstree/btree_tree.go b/lib/btrfs/btrfstree/btree_tree.go
index df58c0c..1e3c789 100644
--- a/lib/btrfs/btrfstree/btree_tree.go
+++ b/lib/btrfs/btrfstree/btree_tree.go
@@ -188,7 +188,8 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
return nil, nil, err
}
- if node.Data.Head.Level > 0 {
+ switch {
+ case node.Data.Head.Level > 0:
// interior node
// Search for the right-most node.Data.BodyInterior item for which
@@ -220,7 +221,7 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
ToMaxKey: toMaxKey,
})
FreeNodeRef(node)
- } else {
+ default:
// leaf node
// Search for a member of node.Data.BodyLeaf for which
diff --git a/lib/btrfs/btrfstree/path.go b/lib/btrfs/btrfstree/path.go
index 9b1a5c7..b9ab5bc 100644
--- a/lib/btrfs/btrfstree/path.go
+++ b/lib/btrfs/btrfstree/path.go
@@ -101,23 +101,22 @@ func (elem TreePathElem) writeNodeTo(w io.Writer) {
func (path TreePath) String() string {
if len(path) == 0 {
return "(empty-path)"
+ }
+ var ret strings.Builder
+ fmt.Fprintf(&ret, "%s->", path[0].FromTree.Format(btrfsprim.ROOT_TREE_OBJECTID))
+ if len(path) == 1 && path[0] == (TreePathElem{FromTree: path[0].FromTree, FromItemSlot: -1}) {
+ ret.WriteString("(empty-path)")
} else {
- var ret strings.Builder
- fmt.Fprintf(&ret, "%s->", path[0].FromTree.Format(btrfsprim.ROOT_TREE_OBJECTID))
- if len(path) == 1 && path[0] == (TreePathElem{FromTree: path[0].FromTree, FromItemSlot: -1}) {
- ret.WriteString("(empty-path)")
- } else {
- path[0].writeNodeTo(&ret)
- }
- for _, elem := range path[1:] {
- fmt.Fprintf(&ret, "[%v]", elem.FromItemSlot)
- if elem.ToNodeAddr != 0 {
- ret.WriteString("->")
- elem.writeNodeTo(&ret)
- }
+ path[0].writeNodeTo(&ret)
+ }
+ for _, elem := range path[1:] {
+ fmt.Fprintf(&ret, "[%v]", elem.FromItemSlot)
+ if elem.ToNodeAddr != 0 {
+ ret.WriteString("->")
+ elem.writeNodeTo(&ret)
}
- return ret.String()
}
+ return ret.String()
}
func (path TreePath) DeepCopy() TreePath {
@@ -128,9 +127,10 @@ func (path TreePath) Parent() TreePath {
return path[:len(path)-1]
}
-// path.Node(x) is like &path[x], but negative values of x move down
-// from the end of path (similar to how lists work in many other
-// languages, such as Python).
+// Node is returns an element from the path; `path.Node(x)` is like
+// `&path[x]`, but negative values of x move down from the end of path
+// (similar to how lists work in many other languages, such as
+// Python).
func (path TreePath) Node(x int) *TreePathElem {
if x < 0 {
x += len(path)
diff --git a/lib/btrfs/btrfstree/types_node.go b/lib/btrfs/btrfstree/types_node.go
index 150539d..8295ccb 100644
--- a/lib/btrfs/btrfstree/types_node.go
+++ b/lib/btrfs/btrfstree/types_node.go
@@ -113,20 +113,22 @@ type NodeHeader struct {
// .Head.NumItems.
func (node Node) MaxItems() uint32 {
bodyBytes := node.Size - uint32(nodeHeaderSize)
- if node.Head.Level > 0 {
+ switch {
+ case node.Head.Level > 0:
return bodyBytes / uint32(keyPointerSize)
- } else {
+ default:
return bodyBytes / uint32(itemHeaderSize)
}
}
func (node Node) MinItem() (btrfsprim.Key, bool) {
- if node.Head.Level > 0 {
+ switch {
+ case node.Head.Level > 0:
if len(node.BodyInterior) == 0 {
return btrfsprim.Key{}, false
}
return node.BodyInterior[0].Key, true
- } else {
+ default:
if len(node.BodyLeaf) == 0 {
return btrfsprim.Key{}, false
}
@@ -135,12 +137,13 @@ func (node Node) MinItem() (btrfsprim.Key, bool) {
}
func (node Node) MaxItem() (btrfsprim.Key, bool) {
- if node.Head.Level > 0 {
+ switch {
+ case node.Head.Level > 0:
if len(node.BodyInterior) == 0 {
return btrfsprim.Key{}, false
}
return node.BodyInterior[len(node.BodyInterior)-1].Key, true
- } else {
+ default:
if len(node.BodyLeaf) == 0 {
return btrfsprim.Key{}, false
}
@@ -221,15 +224,15 @@ func (node Node) MarshalBinary() ([]byte, error) {
buf := make([]byte, node.Size)
- if bs, err := binstruct.Marshal(node.Head); err != nil {
+ bs, err := binstruct.Marshal(node.Head)
+ if err != nil {
return buf, err
- } else {
- if len(bs) != nodeHeaderSize {
- return nil, fmt.Errorf("header is %v bytes but expected %v",
- len(bs), nodeHeaderSize)
- }
- copy(buf, bs)
}
+ if len(bs) != nodeHeaderSize {
+ return nil, fmt.Errorf("header is %v bytes but expected %v",
+ len(bs), nodeHeaderSize)
+ }
+ copy(buf, bs)
if node.Head.Level > 0 {
if err := node.marshalInteriorTo(buf[nodeHeaderSize:]); err != nil {
@@ -456,6 +459,8 @@ func newNodeRef[Addr ~int64]() *diskio.Ref[Addr, Node] {
return (*diskio.Ref[Addr, Node])(unsafe.Pointer(ret)) //nolint:gosec // I know it's unsafe.
}
+// ReadNode reads a node from the given file.
+//
// It is possible that both a non-nil diskio.Ref and an error are
// returned. The error returned (if non-nil) is always of type
// *NodeError[Addr]. Notable errors that may be inside of the
diff --git a/lib/btrfs/btrfsvol/lvm.go b/lib/btrfs/btrfsvol/lvm.go
index 51e2263..3834345 100644
--- a/lib/btrfs/btrfsvol/lvm.go
+++ b/lib/btrfs/btrfsvol/lvm.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package btrfsvol contains core logical-volume-management layer of
+// btrfs.
package btrfsvol
import (
diff --git a/lib/btrfs/io1_pv.go b/lib/btrfs/io1_pv.go
index 72d33f5..3b13f73 100644
--- a/lib/btrfs/io1_pv.go
+++ b/lib/btrfs/io1_pv.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package btrfs (and its sub-packages) are the core implementation of
+// the btrfs filesystem.
package btrfs
import (
diff --git a/lib/btrfs/io4_fs.go b/lib/btrfs/io4_fs.go
index e146739..b1a1232 100644
--- a/lib/btrfs/io4_fs.go
+++ b/lib/btrfs/io4_fs.go
@@ -122,7 +122,7 @@ func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) {
})
if err != nil {
val.Errs = append(val.Errs, err)
- return
+ return val
}
switch itemBody := item.Body.(type) {
@@ -135,7 +135,7 @@ func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) {
panic(fmt.Errorf("should not happen: INODE_ITEM has unexpected item type: %T", itemBody))
}
- return
+ return val
})
if val.InodeItem == nil {
return nil, val.Errs
@@ -156,7 +156,7 @@ func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
if err != nil {
val.Errs = append(val.Errs, err)
if len(items) == 0 {
- return
+ return val
}
}
for _, item := range items {
@@ -190,7 +190,7 @@ func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
val.OtherItems = append(val.OtherItems, item)
}
}
- return
+ return val
})
if val.InodeItem == nil && val.OtherItems == nil {
return nil, val.Errs
@@ -205,12 +205,12 @@ func (sv *Subvolume) LoadDir(inode btrfsprim.ObjID) (*Dir, error) {
fullInode, err := sv.LoadFullInode(inode)
if err != nil {
val.Errs = append(val.Errs, err)
- return
+ return val
}
val.FullInode = *fullInode
val.SV = sv
val.populate()
- return
+ return val
})
if val.Inode == 0 {
return nil, val.Errs
@@ -342,12 +342,12 @@ func (sv *Subvolume) LoadFile(inode btrfsprim.ObjID) (*File, error) {
fullInode, err := sv.LoadFullInode(inode)
if err != nil {
val.Errs = append(val.Errs, err)
- return
+ return val
}
val.FullInode = *fullInode
val.SV = sv
val.populate()
- return
+ return val
})
if val.Inode == 0 {
return nil, val.Errs