summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.golangci.yml35
-rw-r--r--cmd/btrfs-rec/inspect/dumptrees/print_tree.go2
-rw-r--r--cmd/btrfs-rec/inspect/mount/mount.go5
-rw-r--r--cmd/btrfs-rec/inspect/rebuildmappings/process.go3
-rw-r--r--cmd/btrfs-rec/inspect/rebuildmappings/scan.go6
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go6
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go4
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go2
-rw-r--r--cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wanttyp.go3
-rw-r--r--cmd/btrfs-rec/main.go2
-rw-r--r--lib/binstruct/binutil/binutil.go4
-rw-r--r--lib/binstruct/unmarshal.go3
-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
-rw-r--r--lib/btrfscheck/graph.go4
-rw-r--r--lib/btrfsutil/doc.go7
-rw-r--r--lib/btrfsutil/listnodes.go8
-rw-r--r--lib/btrfsutil/print_addrspace.go2
-rw-r--r--lib/containers/doc.go7
-rw-r--r--lib/containers/intervaltree.go2
-rw-r--r--lib/containers/linkedlist.go2
-rw-r--r--lib/containers/optional.go7
-rw-r--r--lib/containers/ordered.go8
-rw-r--r--lib/containers/rbtree.go3
-rw-r--r--lib/containers/rbtree_test.go30
-rw-r--r--lib/containers/set.go2
-rw-r--r--lib/diskio/file_blockbuf.go2
-rw-r--r--lib/diskio/file_iface.go3
-rw-r--r--lib/diskio/file_state_test.go6
-rw-r--r--lib/fmtutil/fmt.go4
-rw-r--r--lib/fmtutil/fmt_test.go6
-rw-r--r--lib/maps/maputil.go4
-rw-r--r--lib/profile/cobra.go2
-rw-r--r--lib/profile/profile.go2
-rw-r--r--lib/slices/sliceutil.go12
-rw-r--r--lib/streamio/runescanner.go4
-rw-r--r--lib/textui/log.go10
-rw-r--r--lib/textui/text.go2
68 files changed, 406 insertions, 166 deletions
diff --git a/.golangci.yml b/.golangci.yml
index 38d53ee..ba58f21 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -7,7 +7,7 @@ linters:
disable:
# Deprecated
- deadcode # deprecated, replaced by 'unused'
- - exhaustivestruct # deprecated, replaced by 'exhauststruct'
+ - exhaustivestruct # deprecated, replaced by 'exhaustruct'
- golint # deprecated, replaced by 'revive'
- ifshort # deprecated
- interfacer # deprecated
@@ -19,7 +19,6 @@ linters:
# Don't support Go 1.18 generics yet
- rowserrcheck
- - sqlclosecheck
- wastedassign
- ireturn # golangci-lint doesn't claim it doesn't, but it doesn't
@@ -48,7 +47,6 @@ linters:
- exhaustruct
- gochecknoglobals
- gochecknoinits
- - revive
- testpackage
- thelper
- varnamelen
@@ -86,13 +84,38 @@ linters-settings:
require-specific: true
allow-no-explanation:
- dupword
+ revive:
+ enable-all-rules: true
+ rules:
+ - { name: call-to-gc, disabled: true }
+ - { name: exported, disabled: true } # TODO: Add doc comments to exported identifiers
+ - { name: file-header, disabled: true } # TODO: This might actually be useful for copyright
+ - { name: flag-parameter, disabled: true }
+ - { name: modifies-value-receiver, disabled: true }
+ - { name: unexported-return, disabled: true }
+ # Style.
+ - { name: banned-characters, disabled: true }
+ - { name: line-length-limit, disabled: true }
+ - { name: nested-structs, disabled: true }
+ - { name: var-naming, disabled: true }
+ # Complexity; sometimes code is just complex.
+ - { name: argument-limit, disabled: true }
+ - { name: cognitive-complexity, disabled: true }
+ - { name: cyclomatic, disabled: true }
+ - { name: function-length, disabled: true }
+ - { name: function-result-limit, disabled: true }
+ - { name: max-public-structs, disabled: true }
+ # Duplicates.
+ - { name: add-constant, disabled: true } # duplicates gomnd
+ - { name: receiver-naming, disabled: true } # duplicates stylecheck ST1016
+ - { name: unhandled-error, disabled: true } # duplicates errcheck
+ # Buggy.
+ - { name: confusing-naming, disabled: true } # false positive on methods implementing interfaces
+ - { name: import-shadowing, disabled: true } # false positive on methods
stylecheck:
checks:
- "all"
- "-ST1003" # CONST_VAL names for consistency with other btrfs code
- - "-ST1000" # TODO: get this to pass
- - "-ST1020" # TODO: get this to pass
- - "-ST1021" # TODO: get this to pass
tagliatelle:
case:
use-field-name: true
diff --git a/cmd/btrfs-rec/inspect/dumptrees/print_tree.go b/cmd/btrfs-rec/inspect/dumptrees/print_tree.go
index a0a3d46..a8c2adf 100644
--- a/cmd/btrfs-rec/inspect/dumptrees/print_tree.go
+++ b/cmd/btrfs-rec/inspect/dumptrees/print_tree.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package dumptrees is the guts of the `btrfs-rec inspect dump-trees`
+// command, which is a clone of `btrfs inspect-internal dump-tree`.
package dumptrees
import (
diff --git a/cmd/btrfs-rec/inspect/mount/mount.go b/cmd/btrfs-rec/inspect/mount/mount.go
index da0bbb6..0e8faf1 100644
--- a/cmd/btrfs-rec/inspect/mount/mount.go
+++ b/cmd/btrfs-rec/inspect/mount/mount.go
@@ -2,6 +2,9 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package mount is the guts of the `btrfs-rec inspect mount` command,
+// which mounts the filesystem read-only using FUSE; providing better
+// tolerance of filesystem corruption than the in-kernel btrfs driver.
package mount
import (
@@ -479,4 +482,4 @@ func (sv *subvolume) GetXattr(_ context.Context, op *fuseops.GetXattrOp) error {
return nil
}
-func (sv *subvolume) Destroy() {}
+func (*subvolume) Destroy() {}
diff --git a/cmd/btrfs-rec/inspect/rebuildmappings/process.go b/cmd/btrfs-rec/inspect/rebuildmappings/process.go
index 7ce3748..a93b697 100644
--- a/cmd/btrfs-rec/inspect/rebuildmappings/process.go
+++ b/cmd/btrfs-rec/inspect/rebuildmappings/process.go
@@ -2,6 +2,9 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package rebuildmappings is the guts of the `btrfs-rec inspect
+// rebuild-mappings` command, which rebuilds broken
+// chunk/dev-extent/blockgroup trees.
package rebuildmappings
import (
diff --git a/cmd/btrfs-rec/inspect/rebuildmappings/scan.go b/cmd/btrfs-rec/inspect/rebuildmappings/scan.go
index f9c3bf3..b88f01c 100644
--- a/cmd/btrfs-rec/inspect/rebuildmappings/scan.go
+++ b/cmd/btrfs-rec/inspect/rebuildmappings/scan.go
@@ -103,7 +103,7 @@ func (scanner *deviceScanner) ScanStats() scanStats {
}
}
-func newDeviceScanner(ctx context.Context, sb btrfstree.Superblock, numBytes btrfsvol.PhysicalAddr, numSectors int) btrfsutil.DeviceScanner[scanStats, ScanOneDeviceResult] {
+func newDeviceScanner(_ context.Context, sb btrfstree.Superblock, _ btrfsvol.PhysicalAddr, numSectors int) btrfsutil.DeviceScanner[scanStats, ScanOneDeviceResult] {
scanner := new(deviceScanner)
scanner.alg = sb.ChecksumType
scanner.result.FoundNodes = make(map[btrfsvol.LogicalAddr][]btrfsvol.PhysicalAddr)
@@ -112,7 +112,7 @@ func newDeviceScanner(ctx context.Context, sb btrfstree.Superblock, numBytes btr
return scanner
}
-func (scanner *deviceScanner) ScanSector(ctx context.Context, dev *btrfs.Device, paddr btrfsvol.PhysicalAddr) error {
+func (scanner *deviceScanner) ScanSector(_ context.Context, dev *btrfs.Device, paddr btrfsvol.PhysicalAddr) error {
sum, err := btrfs.ChecksumPhysical(dev, scanner.alg, paddr)
if err != nil {
return err
@@ -190,7 +190,7 @@ func (scanner *deviceScanner) ScanNode(ctx context.Context, nodeRef *diskio.Ref[
return nil
}
-func (scanner *deviceScanner) ScanDone(ctx context.Context) (ScanOneDeviceResult, error) {
+func (scanner *deviceScanner) ScanDone(_ context.Context) (ScanOneDeviceResult, error) {
scanner.result.Checksums.Sums = btrfssum.ShortSum(scanner.sums.String())
return scanner.result, nil
}
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go
index 708b504..ca1ce8c 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild.go
@@ -2,6 +2,10 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package rebuildtrees is the guts of the `btrfs-rec inspect
+// rebuild-trees` command, which rebuilds broken trees, but requires
+// already-functioning chunk/dev-extent/blockgroup trees.
+// chunk/dev-extent/blockgroup trees.
package rebuildtrees
import (
@@ -282,7 +286,7 @@ func (o *rebuilder) processSettledItemQueue(ctx context.Context) error {
ctx := dlog.WithField(ctx, "btrfs.inspect.rebuild-trees.rebuild.process.item", item.keyAndTree)
o.curKey.TreeID = item.TreeID
o.curKey.Key.Val = item.Key
- btrfscheck.HandleItem(o, ctx, item.TreeID, btrfstree.Item{
+ btrfscheck.HandleItem(ctx, o, item.TreeID, btrfstree.Item{
Key: item.Key,
Body: item.Body,
})
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
index e6a0777..a422a47 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_treecb.go
@@ -14,7 +14,7 @@ import (
)
// AddedItem implements btrfsutil.RebuiltForrestCallbacks.
-func (o *rebuilder) AddedItem(ctx context.Context, tree btrfsprim.ObjID, key btrfsprim.Key) {
+func (o *rebuilder) AddedItem(_ context.Context, tree btrfsprim.ObjID, key btrfsprim.Key) {
o.addedItemQueue.Insert(keyAndTree{
TreeID: tree,
Key: key,
@@ -22,7 +22,7 @@ func (o *rebuilder) AddedItem(ctx context.Context, tree btrfsprim.ObjID, key btr
}
// AddedRoot implements btrfsutil.RebuiltForrestCallbacks.
-func (o *rebuilder) AddedRoot(ctx context.Context, tree btrfsprim.ObjID, root btrfsvol.LogicalAddr) {
+func (o *rebuilder) AddedRoot(_ context.Context, tree btrfsprim.ObjID, _ btrfsvol.LogicalAddr) {
if retries := o.retryItemQueue[tree]; retries != nil {
o.addedItemQueue.InsertFrom(retries)
}
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go
index 4a5029e..704f4ee 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wantcb.go
@@ -20,7 +20,7 @@ import (
)
// FSErr implements btrfscheck.GraphCallbacks.
-func (o *rebuilder) FSErr(ctx context.Context, e error) {
+func (*rebuilder) FSErr(ctx context.Context, e error) {
dlog.Errorf(ctx, "filesystem error: %v", e)
}
diff --git a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wanttyp.go b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wanttyp.go
index 4aab669..8fe8a49 100644
--- a/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wanttyp.go
+++ b/cmd/btrfs-rec/inspect/rebuildtrees/rebuild_wanttyp.go
@@ -23,8 +23,9 @@ const (
offsetName
)
-// TODO(lukeshu): Delete the 'Want' type in favor of btrfstree.Search.
type Want struct {
+ // TODO(lukeshu): Delete the 'Want' type in favor of
+ // btrfstree.Search.
ObjectID btrfsprim.ObjID
ItemType btrfsprim.ItemType
OffsetType wantOffsetType
diff --git a/cmd/btrfs-rec/main.go b/cmd/btrfs-rec/main.go
index 15f1964..e433654 100644
--- a/cmd/btrfs-rec/main.go
+++ b/cmd/btrfs-rec/main.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Command btrfs-rec is used to recover (data from) a broken btrfs
+// filesystem.
package main
import (
diff --git a/lib/binstruct/binutil/binutil.go b/lib/binstruct/binutil/binutil.go
index 684237f..a5c65b5 100644
--- a/lib/binstruct/binutil/binutil.go
+++ b/lib/binstruct/binutil/binutil.go
@@ -1,7 +1,9 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package binutil provides utilities for implementing the interfaces
+// consumed by binstruct.
package binutil
import (
diff --git a/lib/binstruct/unmarshal.go b/lib/binstruct/unmarshal.go
index eae4b84..41aab9c 100644
--- a/lib/binstruct/unmarshal.go
+++ b/lib/binstruct/unmarshal.go
@@ -2,6 +2,9 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package binstruct implements simple struct-tag-based conversion
+// between Go structures and binary on-disk representations of that
+// data.
package binstruct
import (
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
diff --git a/lib/btrfscheck/graph.go b/lib/btrfscheck/graph.go
index ea51818..806f609 100644
--- a/lib/btrfscheck/graph.go
+++ b/lib/btrfscheck/graph.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package btrfscheck implements userspace utilities for checking
+// btrfs filesystems.
package btrfscheck
import (
@@ -45,7 +47,7 @@ func HandleItemWouldBeNoOp(typ btrfsprim.ItemType) bool {
}
}
-func HandleItem(o GraphCallbacks, ctx context.Context, treeID btrfsprim.ObjID, item btrfstree.Item) {
+func HandleItem(ctx context.Context, o GraphCallbacks, treeID btrfsprim.ObjID, item btrfstree.Item) {
// Notionally, just express the relationships shown in
// https://btrfs.wiki.kernel.org/index.php/File:References.png (from the page
// https://btrfs.wiki.kernel.org/index.php/Data_Structures )
diff --git a/lib/btrfsutil/doc.go b/lib/btrfsutil/doc.go
new file mode 100644
index 0000000..4d00cb3
--- /dev/null
+++ b/lib/btrfsutil/doc.go
@@ -0,0 +1,7 @@
+// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+// Package btrfsutil implements userspace utilities for working with
+// btrfs filesystems.
+package btrfsutil
diff --git a/lib/btrfsutil/listnodes.go b/lib/btrfsutil/listnodes.go
index 16300da..5505d23 100644
--- a/lib/btrfsutil/listnodes.go
+++ b/lib/btrfsutil/listnodes.go
@@ -30,7 +30,7 @@ func (s nodeStats) String() string {
var _ DeviceScanner[nodeStats, containers.Set[btrfsvol.LogicalAddr]] = (*nodeScanner)(nil)
-func newNodeScanner(ctx context.Context, sb btrfstree.Superblock, numBytes btrfsvol.PhysicalAddr, numSectors int) DeviceScanner[nodeStats, containers.Set[btrfsvol.LogicalAddr]] {
+func newNodeScanner(context.Context, btrfstree.Superblock, btrfsvol.PhysicalAddr, int) DeviceScanner[nodeStats, containers.Set[btrfsvol.LogicalAddr]] {
s := new(nodeScanner)
s.nodes = make(containers.Set[btrfsvol.LogicalAddr])
return s
@@ -40,16 +40,16 @@ func (s *nodeScanner) ScanStats() nodeStats {
return nodeStats{numNodes: len(s.nodes)}
}
-func (*nodeScanner) ScanSector(ctx context.Context, dev *btrfs.Device, paddr btrfsvol.PhysicalAddr) error {
+func (*nodeScanner) ScanSector(context.Context, *btrfs.Device, btrfsvol.PhysicalAddr) error {
return nil
}
-func (s *nodeScanner) ScanNode(ctx context.Context, nodeRef *diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Node]) error {
+func (s *nodeScanner) ScanNode(_ context.Context, nodeRef *diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Node]) error {
s.nodes.Insert(nodeRef.Data.Head.Addr)
return nil
}
-func (s *nodeScanner) ScanDone(ctx context.Context) (containers.Set[btrfsvol.LogicalAddr], error) {
+func (s *nodeScanner) ScanDone(_ context.Context) (containers.Set[btrfsvol.LogicalAddr], error) {
return s.nodes, nil
}
diff --git a/lib/btrfsutil/print_addrspace.go b/lib/btrfsutil/print_addrspace.go
index c9c51f0..ae2c492 100644
--- a/lib/btrfsutil/print_addrspace.go
+++ b/lib/btrfsutil/print_addrspace.go
@@ -49,7 +49,7 @@ func PrintPhysicalSpace(out io.Writer, fs *btrfs.FS) {
return mappings[i].PAddr.Compare(mappings[j].PAddr) < 0
})
- var prevDev btrfsvol.DeviceID = 0
+ var prevDev btrfsvol.DeviceID
var prevEnd btrfsvol.PhysicalAddr
var sumHole, sumExt btrfsvol.AddrDelta
for _, mapping := range mappings {
diff --git a/lib/containers/doc.go b/lib/containers/doc.go
new file mode 100644
index 0000000..1725e31
--- /dev/null
+++ b/lib/containers/doc.go
@@ -0,0 +1,7 @@
+// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+// Package containers implements generic (type-parameterized) datatype
+// containers.
+package containers
diff --git a/lib/containers/intervaltree.go b/lib/containers/intervaltree.go
index 7b96526..d2e2732 100644
--- a/lib/containers/intervaltree.go
+++ b/lib/containers/intervaltree.go
@@ -39,7 +39,7 @@ type IntervalTree[K Ordered[K], V any] struct {
inner RBTree[intervalValue[K, V]]
}
-func (t *IntervalTree[K, V]) attrFn(node *RBNode[intervalValue[K, V]]) {
+func (*IntervalTree[K, V]) attrFn(node *RBNode[intervalValue[K, V]]) {
max := node.Value.ValSpan.Max
if node.Left != nil && node.Left.Value.ChildSpan.Max.Compare(max) > 0 {
max = node.Left.Value.ChildSpan.Max
diff --git a/lib/containers/linkedlist.go b/lib/containers/linkedlist.go
index 7d40479..07b4760 100644
--- a/lib/containers/linkedlist.go
+++ b/lib/containers/linkedlist.go
@@ -8,7 +8,7 @@ import (
"git.lukeshu.com/go/typedsync"
)
-// LinkedListEntry[T] is an entry in a LinkedList[T].
+// LinkedListEntry [T] is an entry in a LinkedList [T].
type LinkedListEntry[T any] struct {
older, newer *LinkedListEntry[T]
Value T
diff --git a/lib/containers/optional.go b/lib/containers/optional.go
index c0e7b32..5bb7bb6 100644
--- a/lib/containers/optional.go
+++ b/lib/containers/optional.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -19,11 +19,10 @@ var (
)
func (o Optional[T]) MarshalJSON() ([]byte, error) {
- if o.OK {
- return json.Marshal(o.Val)
- } else {
+ if !o.OK {
return []byte("null"), nil
}
+ return json.Marshal(o.Val)
}
func (o *Optional[T]) UnmarshalJSON(dat []byte) error {
diff --git a/lib/containers/ordered.go b/lib/containers/ordered.go
index 1ebc17e..1289b45 100644
--- a/lib/containers/ordered.go
+++ b/lib/containers/ordered.go
@@ -12,7 +12,7 @@ type _Ordered[T any] interface {
Compare(T) int
}
-// An Ordered[T] is a type that has a
+// An Ordered is a type that has a
//
// func (a T) Compare(b T) int
//
@@ -36,10 +36,10 @@ type NativeOrdered[T constraints.Ordered] struct {
Val T
}
-// NativeCompare[T] implements the Ordered[T] Compare operation for
+// NativeCompare implements the Ordered[T] Compare operation for
// natively-ordered (integer types, float types, and string types).
-// While this operation be conceptualized as subtration,
-// NativeCompare[T] is careful to avoid integer overflow.
+// While this operation be conceptualized as subtration, NativeCompare
+// is careful to avoid integer overflow.
func NativeCompare[T constraints.Ordered](a, b T) int {
switch {
case a < b:
diff --git a/lib/containers/rbtree.go b/lib/containers/rbtree.go
index 6182150..59f63aa 100644
--- a/lib/containers/rbtree.go
+++ b/lib/containers/rbtree.go
@@ -167,9 +167,8 @@ func (t *RBTree[T]) Subrange(rangeFn func(T) int, handleFn func(*RBNode[T]) bool
_, node := t.root.search(func(v T) int {
if rangeFn(v) <= 0 {
return -1
- } else {
- return 1
}
+ return 1
})
for node != nil && rangeFn(node.Value) > 0 {
node = node.Next()
diff --git a/lib/containers/rbtree_test.go b/lib/containers/rbtree_test.go
index d2fe931..c6e7a3b 100644
--- a/lib/containers/rbtree_test.go
+++ b/lib/containers/rbtree_test.go
@@ -108,25 +108,25 @@ func checkRBTree[T constraints.Ordered](t *testing.T, expectedSet Set[T], tree *
}
func FuzzRBTree(f *testing.F) {
- Ins := uint8(0b0100_0000)
- Del := uint8(0)
+ ins := uint8(0b0100_0000)
+ del := uint8(0)
f.Add([]uint8{})
- f.Add([]uint8{Ins | 5, Del | 5})
- f.Add([]uint8{Ins | 5, Del | 6})
- f.Add([]uint8{Del | 6})
+ f.Add([]uint8{ins | 5, del | 5})
+ f.Add([]uint8{ins | 5, del | 6})
+ f.Add([]uint8{del | 6})
f.Add([]uint8{ // CLRS Figure 14.4
- Ins | 1,
- Ins | 2,
- Ins | 5,
- Ins | 7,
- Ins | 8,
- Ins | 11,
- Ins | 14,
- Ins | 15,
-
- Ins | 4,
+ ins | 1,
+ ins | 2,
+ ins | 5,
+ ins | 7,
+ ins | 8,
+ ins | 11,
+ ins | 14,
+ ins | 15,
+
+ ins | 4,
})
f.Fuzz(func(t *testing.T, dat []uint8) {
diff --git a/lib/containers/set.go b/lib/containers/set.go
index 0d9202c..074d126 100644
--- a/lib/containers/set.go
+++ b/lib/containers/set.go
@@ -14,7 +14,7 @@ import (
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
)
-// Set[T] is an unordered set of T.
+// Set is an unordered set of T.
type Set[T comparable] map[T]struct{}
var (
diff --git a/lib/diskio/file_blockbuf.go b/lib/diskio/file_blockbuf.go
index b7db849..0bb3156 100644
--- a/lib/diskio/file_blockbuf.go
+++ b/lib/diskio/file_blockbuf.go
@@ -99,5 +99,5 @@ func (bf *bufferedFile[A]) WriteAt(dat []byte, off A) (n int, err error) {
bf.blockCache.Delete(blockOffset)
}
- return
+ return n, err
}
diff --git a/lib/diskio/file_iface.go b/lib/diskio/file_iface.go
index 206db0c..d26ffcc 100644
--- a/lib/diskio/file_iface.go
+++ b/lib/diskio/file_iface.go
@@ -1,7 +1,8 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package diskio implements utilities for working with disk I/O.
package diskio
import (
diff --git a/lib/diskio/file_state_test.go b/lib/diskio/file_state_test.go
index 3f0c119..32ca705 100644
--- a/lib/diskio/file_state_test.go
+++ b/lib/diskio/file_state_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -21,11 +21,11 @@ func (r byteReaderWithName) Name() string {
return r.name
}
-func (r byteReaderWithName) Close() error {
+func (byteReaderWithName) Close() error {
return nil
}
-func (r byteReaderWithName) WriteAt([]byte, int64) (int, error) {
+func (byteReaderWithName) WriteAt([]byte, int64) (int, error) {
panic("not implemented")
}
diff --git a/lib/fmtutil/fmt.go b/lib/fmtutil/fmt.go
index b310eb6..bad4a30 100644
--- a/lib/fmtutil/fmt.go
+++ b/lib/fmtutil/fmt.go
@@ -1,7 +1,9 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package fmtutil provides utilities for implementing the interfaces
+// consumed by the "fmt" package.
package fmtutil
import (
diff --git a/lib/fmtutil/fmt_test.go b/lib/fmtutil/fmt_test.go
index 2c63c2e..6d21b3e 100644
--- a/lib/fmtutil/fmt_test.go
+++ b/lib/fmtutil/fmt_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -53,11 +53,11 @@ func (st FmtState) Flag(b int) bool {
return false
}
-func (st FmtState) Write([]byte) (int, error) {
+func (FmtState) Write([]byte) (int, error) {
panic("not implemented")
}
-func (dst *FmtState) Format(src fmt.State, verb rune) {
+func (dst *FmtState) Format(src fmt.State, _ rune) {
if width, ok := src.Width(); ok {
dst.MWidth = width
}
diff --git a/lib/maps/maputil.go b/lib/maps/maputil.go
index aeebe12..d409e70 100644
--- a/lib/maps/maputil.go
+++ b/lib/maps/maputil.go
@@ -1,7 +1,9 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package maps implements generic (type-parameterized) utilities for
+// working with simple Go maps.
package maps
import (
diff --git a/lib/profile/cobra.go b/lib/profile/cobra.go
index 3094015..9bc55dd 100644
--- a/lib/profile/cobra.go
+++ b/lib/profile/cobra.go
@@ -67,7 +67,7 @@ func (fv *flagValue) Set(filename string) error {
}
// Type implements pflag.Value.
-func (fv *flagValue) Type() string { return "filename" }
+func (*flagValue) Type() string { return "filename" }
func pStart(name string) startFunc {
return func(w io.Writer) (StopFunc, error) {
diff --git a/lib/profile/profile.go b/lib/profile/profile.go
index 27c7e61..0910e5c 100644
--- a/lib/profile/profile.go
+++ b/lib/profile/profile.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package profile implements a uniform interface for getting
+// profiling information from the Go runtime.
package profile
import (
diff --git a/lib/slices/sliceutil.go b/lib/slices/sliceutil.go
index 567f9ec..b8823d3 100644
--- a/lib/slices/sliceutil.go
+++ b/lib/slices/sliceutil.go
@@ -1,7 +1,9 @@
-// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com>
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package slices implements generic (type-parameterized) utilities
+// for working with simple Go slices.
package slices
import (
@@ -93,7 +95,7 @@ func max(a, b int) int {
return b
}
-// Search the slice for a value for which `fn(slice[i]) = 0`.
+// Search searches the slice for a value for which `fn(slice[i]) = 0`.
//
// : + + + 0 0 0 - - -
// : ^ ^ ^
@@ -121,7 +123,8 @@ func Search[T any](slice []T, fn func(T) int) (int, bool) {
return 0, false
}
-// Search the slice for the left-most value for which `fn(slice[i]) = 0`.
+// SearchLowest searches the slice for the left-most value for which
+// `fn(slice[i]) = 0`.
//
// : + + + 0 0 0 - - -
// : ^
@@ -151,7 +154,8 @@ func SearchLowest[T any](slice []T, fn func(T) int) (int, bool) {
return firstGood, true
}
-// Search the slice for the right-most value for which `fn(slice[i]) = 0`.
+// SearchHighest searches the slice for the right-most value for which
+// `fn(slice[i]) = 0`.
//
// : + + + 0 0 0 - - -
// : ^
diff --git a/lib/streamio/runescanner.go b/lib/streamio/runescanner.go
index 451f32f..203439f 100644
--- a/lib/streamio/runescanner.go
+++ b/lib/streamio/runescanner.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package streamio implements utilities for working with streaming
+// I/O.
package streamio
import (
@@ -87,7 +89,7 @@ func (rs *runeScanner) ReadRune() (r rune, size int, err error) {
rs.progressWriter.Set(rs.progress)
}
}
- return
+ return r, size, err
}
// ReadRune implements io.RuneScanner.
diff --git a/lib/textui/log.go b/lib/textui/log.go
index 0a10ef6..9aff364 100644
--- a/lib/textui/log.go
+++ b/lib/textui/log.go
@@ -35,9 +35,9 @@ type LogLevelFlag struct {
var _ pflag.Value = (*LogLevelFlag)(nil)
// Type implements pflag.Value.
-func (lvl *LogLevelFlag) Type() string { return "loglevel" }
+func (*LogLevelFlag) Type() string { return "loglevel" }
-// Type implements pflag.Value.
+// Set implements pflag.Value.
func (lvl *LogLevelFlag) Set(str string) error {
switch strings.ToLower(str) {
case "error":
@@ -56,7 +56,7 @@ func (lvl *LogLevelFlag) Set(str string) error {
return nil
}
-// Type implements pflag.Value.
+// String implements fmt.Stringer (and pflag.Value).
func (lvl *LogLevelFlag) String() string {
switch lvl.Level {
case dlog.LogLevelError:
@@ -94,7 +94,7 @@ func NewLogger(out io.Writer, lvl dlog.LogLevel) dlog.Logger {
}
// Helper implements dlog.Logger.
-func (l *logger) Helper() {}
+func (*logger) Helper() {}
// WithField implements dlog.Logger.
func (l *logger) WithField(key string, value any) dlog.Logger {
@@ -127,7 +127,7 @@ func (l *logger) StdLogger(lvl dlog.LogLevel) *log.Logger {
}
// Log implements dlog.Logger.
-func (l *logger) Log(lvl dlog.LogLevel, msg string) {
+func (*logger) Log(dlog.LogLevel, string) {
panic("should not happen: optimized log methods should be used instead")
}
diff --git a/lib/textui/text.go b/lib/textui/text.go
index c0a3c5e..538bac2 100644
--- a/lib/textui/text.go
+++ b/lib/textui/text.go
@@ -2,6 +2,8 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
+// Package textui implements utilities for emitting human-friendly
+// text on stdout and stderr.
package textui
import (