summaryrefslogtreecommitdiff
path: root/cmd/btrfs-dbg/types.go
blob: 3cd348d752d1a0dc9ff2a9b506bf2f0f6a1b4f12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package main

import (
	"encoding/binary"
	"encoding/hex"
	"hash/crc32"
	"strings"
	"time"

	"lukeshu.com/btrfs-tools/pkg/binstruct"
)

type (
	PhysicalAddr int64
	LogicalAddr  int64
	ObjID        int64
	CSum         [0x20]byte
	UUID         [16]byte
)

func (uuid UUID) String() string {
	str := hex.EncodeToString(uuid[:])
	return strings.Join([]string{
		str[:8],
		str[8:12],
		str[12:16],
		str[16:20],
		str[20:32],
	}, "-")
}

func crc32c(data []byte) CSum {
	sum := crc32.Update(0xFFFFFFFF, crc32.MakeTable(0x1EDC6F41), data)
	var buf CSum
	binary.LittleEndian.PutUint32(buf[:], sum)
	return buf
}

type Key struct {
	ObjectID      ObjID  `bin:"off=0, siz=8, desc=Object ID. Each tree has its own set of Object IDs."`
	ItemType      uint8  `bin:"off=8, siz=1, desc=Item type."`
	Offset        uint64 `bin:"off=9, siz=8, desc=Offset. The meaning depends on the item type."`
	binstruct.End `bin:"off=11"`
}

type Time struct {
	Sec           int64  `bin:"off=0, siz=8, desc=Number of seconds since 1970-01-01T00:00:00Z."`
	NSec          uint64 `bin:"off=8, siz=4, desc=Number of nanoseconds since the beginning of the second."`
	binstruct.End `bin:"off=c"`
}

func (t Time) ToStd() time.Time {
	return time.Unix(t.Sec, int64(t.NSec))
}

type Superblock struct {
	Checksum   CSum         `bin:"off=0,  siz=20, desc=Checksum of everything past this field (from 20 to 1000)"`
	FSUUID     UUID         `bin:"off=20, siz=10, desc=FS UUID"`
	Self       PhysicalAddr `bin:"off=30, siz=8,  desc=physical address of this block (different for mirrors)"`
	Flags      uint64       `bin:"off=38, siz=8,  desc=flags"`
	Magic      [8]byte      `bin:"off=40, siz=8,  desc=magic ('_BHRfS_M')"`
	Generation uint64       `bin:"off=48, siz=8,  desc=generation"`

	RootTree  LogicalAddr `bin:"off=50, siz=8,  desc=logical address of the root tree root"`
	ChunkTree LogicalAddr `bin:"off=58, siz=8,  desc=logical address of the chunk tree root"`
	LogTree   LogicalAddr `bin:"off=60, siz=8,  desc=logical address of the log tree root"`

	LogRootTransID  uint64 `bin:"off=68, siz=8, desc=log_root_transid"`
	TotalBytes      uint64 `bin:"off=70, siz=8, desc=total_bytes"`
	BytesUsed       uint64 `bin:"off=78, siz=8, desc=bytes_used"`
	RootDirObjectID uint64 `bin:"off=80, siz=8, desc=root_dir_objectid (usually 6)"`
	NumDevices      uint64 `bin:"off=88, siz=8, desc=num_devices"`

	SectorSize        uint32 `bin:"off=90, siz=4, desc=sectorsize"`
	NodeSize          uint32 `bin:"off=94, siz=4, desc=nodesize"`
	LeafSize          uint32 `bin:"off=98, siz=4, desc=leafsize"`
	StripeSize        uint32 `bin:"off=9c, siz=4, desc=stripesize"`
	SysChunkArraySize uint32 `bin:"off=a0, siz=4, desc=sys_chunk_array_size"`

	ChunkRootGeneration uint64 `bin:"off=a4, siz=8, desc=chunk_root_generation"`
	CompatFlags         uint64 `bin:"off=ac, siz=8, desc=compat_flags"`
	CompatROFlags       uint64 `bin:"off=b4, siz=8, desc=compat_ro_flags - only implementations that support the flags can write to the filesystem"`
	IncompatFlags       uint64 `bin:"off=bc, siz=8, desc=incompat_flags - only implementations that support the flags can use the filesystem"`
	ChecksumType        uint16 `bin:"off=c4, siz=2, desc=csum_type - Btrfs currently uses the CRC32c little-endian hash function with seed -1."`

	RootLevel  uint8 `bin:"off=c6, siz=1, desc=root_level"`
	ChunkLevel uint8 `bin:"off=c7, siz=1, desc=chunk_root_level"`
	LogLevel   uint8 `bin:"off=c8, siz=1, desc=log_root_level"`

	DevItem            DevItem     `bin:"off=c9,  siz=62,  desc=DEV_ITEM data for this device"`
	Label              [0x100]byte `bin:"off=12b, siz=100, desc=label (may not contain '/' or '\\')"`
	CacheGeneration    uint64      `bin:"off=22b, siz=8,   desc=cache_generation"`
	UUIDTreeGeneration uint64      `bin:"off=233, siz=8,   desc=uuid_tree_generation"`

	Reserved [0xf0]byte `bin:"off=23b, siz=f0,  desc=reserved /* future expansion */"`

	TODOSysChunkArray [0x800]byte `bin:"off=32b, siz=800, desc=sys_chunk_array:(n bytes valid) Contains (KEY . CHUNK_ITEM) pairs for all SYSTEM chunks. This is needed to bootstrap the mapping from logical addresses to physical. "`
	TODOSuperRoots    [0x2a0]byte `bin:"off=b2b, siz=2a0, desc=Contain super_roots (4 btrfs_root_backup)"`

	Unused [0x235]byte `bin:"off=dcb, siz=235, desc=current unused"`

	binstruct.End `bin:"off=1000"`
}

func (sb Superblock) CalculateChecksum() (CSum, error) {
	data, err := binstruct.Marshal(sb)
	if err != nil {
		return CSum{}, err
	}
	return crc32c(data[0x20:]), nil
}

type DevItem struct {
	DeviceID uint64 `bin:"off=0,    siz=8,  desc=device id"`

	NumBytes     uint64 `bin:"off=8,    siz=8,  desc=number of bytes"`
	NumBytesUsed uint64 `bin:"off=10,   siz=8,  desc=number of bytes used"`

	IOOptimalAlign uint32 `bin:"off=18,   siz=4,  desc=optimal I/O align"`
	IOOptimalWidth uint32 `bin:"off=1c,   siz=4,  desc=optimal I/O width"`
	IOMinSize      uint32 `bin:"off=20,   siz=4,  desc=minimal I/O size (sector size)"`

	Type        uint64 `bin:"off=24,   siz=8,  desc=type"`
	Generation  uint64 `bin:"off=2c,   siz=8,  desc=generation"`
	StartOffset uint64 `bin:"off=34,   siz=8,  desc=start offset"`
	DevGroup    uint32 `bin:"off=3c,   siz=4,  desc=dev group"`
	SeekSpeed   uint8  `bin:"off=40,   siz=1,  desc=seek speed"`
	Bandwidth   uint8  `bin:"off=41,   siz=1,  desc=bandwidth"`

	DevUUID UUID `bin:"off=42,   siz=10,         desc=device UUID"`
	FSUUID  UUID `bin:"off=52,   siz=10,         desc=FS UUID"`

	binstruct.End `bin:"off=62"`
}

type ChunkItem struct {
	// Maps logical address to physical.
	Size           uint64 `bin:"off=0,  siz=8, desc=size of chunk (bytes)"`
	Root           ObjID  `bin:"off=8,  siz=8, desc=root referencing this chunk (2)"`
	StripeLen      uint64 `bin:"off=10, siz=8, desc=stripe length"`
	Type           uint64 `bin:"off=18, siz=8, desc=type (same as flags for block group?)"`
	IOOptimalAlign uint32 `bin:"off=20, siz=4, desc=optimal io alignment"`
	IOOptimalWidth uint32 `bin:"off=24, siz=4, desc=optimal io width"`
	IoMinSize      uint32 `bin:"off=28, siz=4, desc=minimal io size (sector size)"`
	NumStripes     uint16 `bin:"off=2c, siz=2, desc=number of stripes"`
	SubStripes     uint16 `bin:"off=2e, siz=2, desc=sub stripes"`
	binstruct.End  `bin:"off=30"`
}

type ChunkItemStripe struct {
	// Stripes follow (for each number of stripes):
	DeviceID      ObjID  `bin:"off=0,  siz=8,  desc=device id"`
	Offset        uint64 `bin:"off=8,  siz=8,  desc=offset"`
	DeviceUUID    UUID   `bin:"off=10, siz=10, desc=device UUID"`
	binstruct.End `bin:"off=20"`
}