btrfs_diskformat/core/super_block.rs
1use crate::{
2 DevItem, RootBackup,
3 constants::{CSUM_SIZE, FSID_SIZE, LABEL_SIZE, MAX_SYSTEM_CHUNK_ARRAY_SIZE, NUM_BACKUP_ROOTS},
4};
5use num_enum::{IntoPrimitive, TryFromPrimitive};
6use static_assertions::const_assert_eq;
7use strum::EnumIter;
8use zerocopy::little_endian::{U32 as U32LE, U64 as U64LE};
9use zerocopy_derive::*;
10
11/// The layout of the superblock. A valid superblock must exist for most btrfs implementations to
12/// mount the filesystem.
13///
14/// The primary superblock is located at [`PRIMARY_SUPERBLOCK_ADDR`].
15///
16/// There are additional copies of the superblock located at [`SUPERBLOCK_ADDRS`], if those addresses
17/// are valid, respectively.
18///
19///
20/// [`PRIMARY_SUPERBLOCK_ADDR`]: crate::constants::PRIMARY_SUPERBLOCK_ADDR
21/// [`SUPERBLOCK_ADDRS`]: crate::constants::SUPERBLOCK_ADDRS
22///
23/// # Resources
24///
25/// * <https://btrfs.wiki.kernel.org/index.php/Data_Structures#btrfs_super_block>
26/// * <https://btrfs.wiki.kernel.org/index.php/On-disk_Format#Superblock>
27#[derive(Copy, Clone, IntoBytes, TryFromBytes, Unaligned, KnownLayout)]
28#[repr(C, packed)]
29pub struct SuperBlock {
30 /// Checksum of everything past this field.
31 pub csum: [u8; CSUM_SIZE],
32
33 /// Filesystem UUID.
34 pub fsid: [u8; FSID_SIZE],
35
36 /// The physical address of this block.
37 pub bytenr: U64LE,
38
39 /// Flags
40 pub flags: U64LE,
41
42 /// The magic must be equal to `"_BHRfS_M"` in ASCII.
43 pub magic: U64LE,
44
45 /// The generation of the superblock. In SSD mode, not all superblocks may be updated, so the
46 /// latest generation superblock should be used.
47 pub generation: U64LE,
48
49 /// The logical address of the root tree's root.
50 pub root: U64LE,
51
52 /// The logical address of the chunk tree's root.
53 pub chunk_root: U64LE,
54
55 /// The logical address of the log tree's root.
56 pub log_root: U64LE,
57
58 /// FIXME: find out what this is!
59 pub log_root_transid: U64LE,
60
61 /// FIXME: document this!
62 pub total_bytes: U64LE,
63
64 pub bytes_used: U64LE,
65
66 /// The root directory's object ID, which is typically 6.
67 pub root_dir_objectid: U64LE,
68
69 /// The number of devices the current filesystem spans.
70 pub num_devices: U64LE,
71
72 /// The size of a sector.
73 pub sectorsize: U32LE,
74
75 pub nodesize: U32LE,
76
77 /// This is currently unused.
78 pub leafsize: U32LE,
79
80 pub stripesize: U32LE,
81
82 /// The size of [`sys_chunk_array`] found in the superblock.
83 ///
84 /// [`sys_chunk_array`]: SuperBlock::sys_chunk_array
85 pub sys_chunk_array_size: U32LE,
86
87 pub chunk_root_generation: U64LE,
88
89 pub compat_flags: U64LE,
90
91 /// Only implementations that support these flags can write to the filesystem.
92 pub compat_ro_flags: U64LE,
93
94 /// Only implementations that support these flags can use the filesystem.
95 pub incompat_flags: U64LE,
96
97 /// The checksum type.
98 ///
99 /// This should correspond with a value from [`ChecksumType`].
100 ///
101 /// [`ChecksumType`]: crate::ChecksumType
102 pub csum_type: ChecksumType,
103
104 pub root_level: u8,
105
106 pub chunk_root_level: u8,
107
108 pub log_root_level: u8,
109
110 pub dev_item: DevItem,
111
112 /// The label represented as a null-terminated UTF-8 string. May not contain `'/'` or `'\\'`.
113 pub label: [u8; LABEL_SIZE],
114
115 pub cache_generation: U64LE,
116
117 pub uuid_tree_generation: U64LE,
118
119 /// Reserved for extensibility.
120 pub _reserved: [U64LE; 30],
121
122 pub sys_chunk_array: [u8; MAX_SYSTEM_CHUNK_ARRAY_SIZE],
123
124 pub super_roots: [RootBackup; NUM_BACKUP_ROOTS],
125
126 pub _unused1: [u8; 565],
127}
128const_assert_eq!(core::mem::size_of::<SuperBlock>(), 4096);
129
130/// The hashing algorithm used for checksumming.
131#[derive(
132 Copy,
133 Clone,
134 Debug,
135 Hash,
136 PartialEq,
137 EnumIter,
138 IntoPrimitive,
139 TryFromPrimitive,
140 TryFromBytes,
141 IntoBytes,
142 KnownLayout,
143)]
144#[repr(u16)]
145pub enum ChecksumType {
146 CRC32C = 0u16.to_le(),
147 XXHASH64 = 1u16.to_le(),
148 SHA256 = 2u16.to_le(),
149 BLAKE2b = 3u16.to_le(),
150}
151const_assert_eq!(core::mem::size_of::<ChecksumType>(), 2);