xref: /linux/drivers/md/dm-vdo/encodings.h (revision 61234f0b)
1827c6389SMatthew Sakai /* SPDX-License-Identifier: GPL-2.0-only */
2827c6389SMatthew Sakai /*
3827c6389SMatthew Sakai  * Copyright 2023 Red Hat
4827c6389SMatthew Sakai  */
5827c6389SMatthew Sakai 
6827c6389SMatthew Sakai #ifndef VDO_ENCODINGS_H
7827c6389SMatthew Sakai #define VDO_ENCODINGS_H
8827c6389SMatthew Sakai 
9827c6389SMatthew Sakai #include <linux/blk_types.h>
10827c6389SMatthew Sakai #include <linux/crc32.h>
11827c6389SMatthew Sakai #include <linux/limits.h>
12827c6389SMatthew Sakai #include <linux/uuid.h>
13827c6389SMatthew Sakai 
14827c6389SMatthew Sakai #include "numeric.h"
15827c6389SMatthew Sakai 
16827c6389SMatthew Sakai #include "constants.h"
17827c6389SMatthew Sakai #include "types.h"
18827c6389SMatthew Sakai 
19827c6389SMatthew Sakai /*
20827c6389SMatthew Sakai  * An in-memory representation of a version number for versioned structures on disk.
21827c6389SMatthew Sakai  *
22827c6389SMatthew Sakai  * A version number consists of two portions, a major version and a minor version. Any format
23827c6389SMatthew Sakai  * change which does not require an explicit upgrade step from the previous version should
24827c6389SMatthew Sakai  * increment the minor version. Any format change which either requires an explicit upgrade step,
25827c6389SMatthew Sakai  * or is wholly incompatible (i.e. can not be upgraded to), should increment the major version, and
26827c6389SMatthew Sakai  * set the minor version to 0.
27827c6389SMatthew Sakai  */
28827c6389SMatthew Sakai struct version_number {
29827c6389SMatthew Sakai 	u32 major_version;
30827c6389SMatthew Sakai 	u32 minor_version;
31827c6389SMatthew Sakai };
32827c6389SMatthew Sakai 
33827c6389SMatthew Sakai /*
34827c6389SMatthew Sakai  * A packed, machine-independent, on-disk representation of a version_number. Both fields are
35827c6389SMatthew Sakai  * stored in little-endian byte order.
36827c6389SMatthew Sakai  */
37827c6389SMatthew Sakai struct packed_version_number {
38827c6389SMatthew Sakai 	__le32 major_version;
39827c6389SMatthew Sakai 	__le32 minor_version;
40827c6389SMatthew Sakai } __packed;
41827c6389SMatthew Sakai 
42827c6389SMatthew Sakai /* The registry of component ids for use in headers */
43827c6389SMatthew Sakai #define VDO_SUPER_BLOCK 0
44827c6389SMatthew Sakai #define VDO_LAYOUT 1
45827c6389SMatthew Sakai #define VDO_RECOVERY_JOURNAL 2
46827c6389SMatthew Sakai #define VDO_SLAB_DEPOT 3
47827c6389SMatthew Sakai #define VDO_BLOCK_MAP 4
48827c6389SMatthew Sakai #define VDO_GEOMETRY_BLOCK 5
49827c6389SMatthew Sakai 
50827c6389SMatthew Sakai /* The header for versioned data stored on disk. */
51827c6389SMatthew Sakai struct header {
52827c6389SMatthew Sakai 	u32 id; /* The component this is a header for */
53827c6389SMatthew Sakai 	struct version_number version; /* The version of the data format */
54827c6389SMatthew Sakai 	size_t size; /* The size of the data following this header */
55827c6389SMatthew Sakai };
56827c6389SMatthew Sakai 
57827c6389SMatthew Sakai /* A packed, machine-independent, on-disk representation of a component header. */
58827c6389SMatthew Sakai struct packed_header {
59827c6389SMatthew Sakai 	__le32 id;
60827c6389SMatthew Sakai 	struct packed_version_number version;
61827c6389SMatthew Sakai 	__le64 size;
62827c6389SMatthew Sakai } __packed;
63827c6389SMatthew Sakai 
64827c6389SMatthew Sakai enum {
65827c6389SMatthew Sakai 	VDO_GEOMETRY_BLOCK_LOCATION = 0,
66827c6389SMatthew Sakai 	VDO_GEOMETRY_MAGIC_NUMBER_SIZE = 8,
67827c6389SMatthew Sakai 	VDO_DEFAULT_GEOMETRY_BLOCK_VERSION = 5,
68827c6389SMatthew Sakai };
69827c6389SMatthew Sakai 
70827c6389SMatthew Sakai struct index_config {
71827c6389SMatthew Sakai 	u32 mem;
72827c6389SMatthew Sakai 	u32 unused;
73827c6389SMatthew Sakai 	bool sparse;
74827c6389SMatthew Sakai } __packed;
75827c6389SMatthew Sakai 
76827c6389SMatthew Sakai enum volume_region_id {
77827c6389SMatthew Sakai 	VDO_INDEX_REGION = 0,
78827c6389SMatthew Sakai 	VDO_DATA_REGION = 1,
79827c6389SMatthew Sakai 	VDO_VOLUME_REGION_COUNT,
80827c6389SMatthew Sakai };
81827c6389SMatthew Sakai 
82827c6389SMatthew Sakai struct volume_region {
83827c6389SMatthew Sakai 	/* The ID of the region */
84827c6389SMatthew Sakai 	enum volume_region_id id;
85827c6389SMatthew Sakai 	/*
86827c6389SMatthew Sakai 	 * The absolute starting offset on the device. The region continues until the next region
87827c6389SMatthew Sakai 	 * begins.
88827c6389SMatthew Sakai 	 */
89827c6389SMatthew Sakai 	physical_block_number_t start_block;
90827c6389SMatthew Sakai } __packed;
91827c6389SMatthew Sakai 
92827c6389SMatthew Sakai struct volume_geometry {
93827c6389SMatthew Sakai 	/* For backwards compatibility */
94827c6389SMatthew Sakai 	u32 unused;
95827c6389SMatthew Sakai 	/* The nonce of this volume */
96827c6389SMatthew Sakai 	nonce_t nonce;
97827c6389SMatthew Sakai 	/* The uuid of this volume */
98827c6389SMatthew Sakai 	uuid_t uuid;
99827c6389SMatthew Sakai 	/* The block offset to be applied to bios */
100827c6389SMatthew Sakai 	block_count_t bio_offset;
101827c6389SMatthew Sakai 	/* The regions in ID order */
102827c6389SMatthew Sakai 	struct volume_region regions[VDO_VOLUME_REGION_COUNT];
103827c6389SMatthew Sakai 	/* The index config */
104827c6389SMatthew Sakai 	struct index_config index_config;
105827c6389SMatthew Sakai } __packed;
106827c6389SMatthew Sakai 
107827c6389SMatthew Sakai /* This volume geometry struct is used for sizing only */
108827c6389SMatthew Sakai struct volume_geometry_4_0 {
109827c6389SMatthew Sakai 	/* For backwards compatibility */
110827c6389SMatthew Sakai 	u32 unused;
111827c6389SMatthew Sakai 	/* The nonce of this volume */
112827c6389SMatthew Sakai 	nonce_t nonce;
113827c6389SMatthew Sakai 	/* The uuid of this volume */
114827c6389SMatthew Sakai 	uuid_t uuid;
115827c6389SMatthew Sakai 	/* The regions in ID order */
116827c6389SMatthew Sakai 	struct volume_region regions[VDO_VOLUME_REGION_COUNT];
117827c6389SMatthew Sakai 	/* The index config */
118827c6389SMatthew Sakai 	struct index_config index_config;
119827c6389SMatthew Sakai } __packed;
120827c6389SMatthew Sakai 
121827c6389SMatthew Sakai extern const u8 VDO_GEOMETRY_MAGIC_NUMBER[VDO_GEOMETRY_MAGIC_NUMBER_SIZE + 1];
122827c6389SMatthew Sakai 
123827c6389SMatthew Sakai /**
124827c6389SMatthew Sakai  * DOC: Block map entries
125827c6389SMatthew Sakai  *
126827c6389SMatthew Sakai  * The entry for each logical block in the block map is encoded into five bytes, which saves space
127827c6389SMatthew Sakai  * in both the on-disk and in-memory layouts. It consists of the 36 low-order bits of a
128827c6389SMatthew Sakai  * physical_block_number_t (addressing 256 terabytes with a 4KB block size) and a 4-bit encoding of
129827c6389SMatthew Sakai  * a block_mapping_state.
130827c6389SMatthew Sakai  *
131827c6389SMatthew Sakai  * Of the 8 high bits of the 5-byte structure:
132827c6389SMatthew Sakai  *
133827c6389SMatthew Sakai  * Bits 7..4: The four highest bits of the 36-bit physical block number
134827c6389SMatthew Sakai  * Bits 3..0: The 4-bit block_mapping_state
135827c6389SMatthew Sakai  *
136827c6389SMatthew Sakai  * The following 4 bytes are the low order bytes of the physical block number, in little-endian
137827c6389SMatthew Sakai  * order.
138827c6389SMatthew Sakai  *
139827c6389SMatthew Sakai  * Conversion functions to and from a data location are provided.
140827c6389SMatthew Sakai  */
141827c6389SMatthew Sakai struct block_map_entry {
142827c6389SMatthew Sakai #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
143827c6389SMatthew Sakai 	unsigned mapping_state : 4;
144827c6389SMatthew Sakai 	unsigned pbn_high_nibble : 4;
145827c6389SMatthew Sakai #else
146827c6389SMatthew Sakai 	unsigned pbn_high_nibble : 4;
147827c6389SMatthew Sakai 	unsigned mapping_state : 4;
148827c6389SMatthew Sakai #endif
149827c6389SMatthew Sakai 
150827c6389SMatthew Sakai 	__le32 pbn_low_word;
151827c6389SMatthew Sakai } __packed;
152827c6389SMatthew Sakai 
153827c6389SMatthew Sakai struct block_map_page_header {
154827c6389SMatthew Sakai 	__le64 nonce;
155827c6389SMatthew Sakai 	__le64 pbn;
156827c6389SMatthew Sakai 
157*571eff39SMike Snitzer 	/* May be non-zero on disk */
158827c6389SMatthew Sakai 	u8 unused_long_word[8];
159827c6389SMatthew Sakai 
160827c6389SMatthew Sakai 	/* Whether this page has been written twice to disk */
161827c6389SMatthew Sakai 	bool initialized;
162827c6389SMatthew Sakai 
163827c6389SMatthew Sakai 	/* Always zero on disk */
164827c6389SMatthew Sakai 	u8 unused_byte1;
165827c6389SMatthew Sakai 
166827c6389SMatthew Sakai 	/* May be non-zero on disk */
167827c6389SMatthew Sakai 	u8 unused_byte2;
168827c6389SMatthew Sakai 	u8 unused_byte3;
169827c6389SMatthew Sakai } __packed;
170827c6389SMatthew Sakai 
171827c6389SMatthew Sakai struct block_map_page {
172827c6389SMatthew Sakai 	struct packed_version_number version;
173827c6389SMatthew Sakai 	struct block_map_page_header header;
174827c6389SMatthew Sakai 	struct block_map_entry entries[];
175827c6389SMatthew Sakai } __packed;
176827c6389SMatthew Sakai 
177827c6389SMatthew Sakai enum block_map_page_validity {
178827c6389SMatthew Sakai 	VDO_BLOCK_MAP_PAGE_VALID,
179827c6389SMatthew Sakai 	VDO_BLOCK_MAP_PAGE_INVALID,
180827c6389SMatthew Sakai 	/* Valid page found in the wrong location on disk */
181827c6389SMatthew Sakai 	VDO_BLOCK_MAP_PAGE_BAD,
182827c6389SMatthew Sakai };
183827c6389SMatthew Sakai 
184827c6389SMatthew Sakai struct block_map_state_2_0 {
185827c6389SMatthew Sakai 	physical_block_number_t flat_page_origin;
186827c6389SMatthew Sakai 	block_count_t flat_page_count;
187827c6389SMatthew Sakai 	physical_block_number_t root_origin;
188827c6389SMatthew Sakai 	block_count_t root_count;
189827c6389SMatthew Sakai } __packed;
190827c6389SMatthew Sakai 
191827c6389SMatthew Sakai struct boundary {
192827c6389SMatthew Sakai 	page_number_t levels[VDO_BLOCK_MAP_TREE_HEIGHT];
193827c6389SMatthew Sakai };
194827c6389SMatthew Sakai 
195827c6389SMatthew Sakai extern const struct header VDO_BLOCK_MAP_HEADER_2_0;
196827c6389SMatthew Sakai 
197827c6389SMatthew Sakai /* The state of the recovery journal as encoded in the VDO super block. */
198827c6389SMatthew Sakai struct recovery_journal_state_7_0 {
199*571eff39SMike Snitzer 	/* Sequence number to start the journal */
200827c6389SMatthew Sakai 	sequence_number_t journal_start;
201*571eff39SMike Snitzer 	/* Number of logical blocks used by VDO */
202827c6389SMatthew Sakai 	block_count_t logical_blocks_used;
203*571eff39SMike Snitzer 	/* Number of block map pages allocated */
204827c6389SMatthew Sakai 	block_count_t block_map_data_blocks;
205827c6389SMatthew Sakai } __packed;
206827c6389SMatthew Sakai 
207827c6389SMatthew Sakai extern const struct header VDO_RECOVERY_JOURNAL_HEADER_7_0;
208827c6389SMatthew Sakai 
209827c6389SMatthew Sakai typedef u16 journal_entry_count_t;
210827c6389SMatthew Sakai 
211827c6389SMatthew Sakai /*
212827c6389SMatthew Sakai  * A recovery journal entry stores three physical locations: a data location that is the value of a
213827c6389SMatthew Sakai  * single mapping in the block map tree, and the two locations of the block map pages and slots
214827c6389SMatthew Sakai  * that are acquiring and releasing a reference to the location. The journal entry also stores an
215827c6389SMatthew Sakai  * operation code that says whether the mapping is for a logical block or for the block map tree
216827c6389SMatthew Sakai  * itself.
217827c6389SMatthew Sakai  */
218827c6389SMatthew Sakai struct recovery_journal_entry {
219827c6389SMatthew Sakai 	struct block_map_slot slot;
220827c6389SMatthew Sakai 	struct data_location mapping;
221827c6389SMatthew Sakai 	struct data_location unmapping;
222827c6389SMatthew Sakai 	enum journal_operation operation;
223827c6389SMatthew Sakai };
224827c6389SMatthew Sakai 
225827c6389SMatthew Sakai /* The packed, on-disk representation of a recovery journal entry. */
226827c6389SMatthew Sakai struct packed_recovery_journal_entry {
227827c6389SMatthew Sakai 	/*
228827c6389SMatthew Sakai 	 * In little-endian bit order:
229827c6389SMatthew Sakai 	 * Bits 15..12: The four highest bits of the 36-bit physical block number of the block map
230827c6389SMatthew Sakai 	 * tree page
231827c6389SMatthew Sakai 	 * Bits 11..2: The 10-bit block map page slot number
232827c6389SMatthew Sakai 	 * Bit 1..0: The journal_operation of the entry (this actually only requires 1 bit, but
233827c6389SMatthew Sakai 	 *           it is convenient to keep the extra bit as part of this field.
234827c6389SMatthew Sakai 	 */
235827c6389SMatthew Sakai #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
236827c6389SMatthew Sakai 	unsigned operation : 2;
237827c6389SMatthew Sakai 	unsigned slot_low : 6;
238827c6389SMatthew Sakai 	unsigned slot_high : 4;
239827c6389SMatthew Sakai 	unsigned pbn_high_nibble : 4;
240827c6389SMatthew Sakai #else
241827c6389SMatthew Sakai 	unsigned slot_low : 6;
242827c6389SMatthew Sakai 	unsigned operation : 2;
243827c6389SMatthew Sakai 	unsigned pbn_high_nibble : 4;
244827c6389SMatthew Sakai 	unsigned slot_high : 4;
245827c6389SMatthew Sakai #endif
246827c6389SMatthew Sakai 
247827c6389SMatthew Sakai 	/*
248827c6389SMatthew Sakai 	 * Bits 47..16: The 32 low-order bits of the block map page PBN, in little-endian byte
249827c6389SMatthew Sakai 	 * order
250827c6389SMatthew Sakai 	 */
251827c6389SMatthew Sakai 	__le32 pbn_low_word;
252827c6389SMatthew Sakai 
253827c6389SMatthew Sakai 	/*
254827c6389SMatthew Sakai 	 * Bits 87..48: The five-byte block map entry encoding the location that will be stored in
255827c6389SMatthew Sakai 	 * the block map page slot
256827c6389SMatthew Sakai 	 */
257827c6389SMatthew Sakai 	struct block_map_entry mapping;
258827c6389SMatthew Sakai 
259827c6389SMatthew Sakai 	/*
260827c6389SMatthew Sakai 	 * Bits 127..88: The five-byte block map entry encoding the location that was stored in the
261827c6389SMatthew Sakai 	 * block map page slot
262827c6389SMatthew Sakai 	 */
263827c6389SMatthew Sakai 	struct block_map_entry unmapping;
264827c6389SMatthew Sakai } __packed;
265827c6389SMatthew Sakai 
266827c6389SMatthew Sakai /* The packed, on-disk representation of an old format recovery journal entry. */
267827c6389SMatthew Sakai struct packed_recovery_journal_entry_1 {
268827c6389SMatthew Sakai 	/*
269827c6389SMatthew Sakai 	 * In little-endian bit order:
270827c6389SMatthew Sakai 	 * Bits 15..12: The four highest bits of the 36-bit physical block number of the block map
271827c6389SMatthew Sakai 	 *              tree page
272827c6389SMatthew Sakai 	 * Bits 11..2: The 10-bit block map page slot number
273827c6389SMatthew Sakai 	 * Bits 1..0: The 2-bit journal_operation of the entry
274827c6389SMatthew Sakai 	 *
275827c6389SMatthew Sakai 	 */
276827c6389SMatthew Sakai #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
277827c6389SMatthew Sakai 	unsigned operation : 2;
278827c6389SMatthew Sakai 	unsigned slot_low : 6;
279827c6389SMatthew Sakai 	unsigned slot_high : 4;
280827c6389SMatthew Sakai 	unsigned pbn_high_nibble : 4;
281827c6389SMatthew Sakai #else
282827c6389SMatthew Sakai 	unsigned slot_low : 6;
283827c6389SMatthew Sakai 	unsigned operation : 2;
284827c6389SMatthew Sakai 	unsigned pbn_high_nibble : 4;
285827c6389SMatthew Sakai 	unsigned slot_high : 4;
286827c6389SMatthew Sakai #endif
287827c6389SMatthew Sakai 
288827c6389SMatthew Sakai 	/*
289827c6389SMatthew Sakai 	 * Bits 47..16: The 32 low-order bits of the block map page PBN, in little-endian byte
290827c6389SMatthew Sakai 	 * order
291827c6389SMatthew Sakai 	 */
292827c6389SMatthew Sakai 	__le32 pbn_low_word;
293827c6389SMatthew Sakai 
294827c6389SMatthew Sakai 	/*
295827c6389SMatthew Sakai 	 * Bits 87..48: The five-byte block map entry encoding the location that was or will be
296827c6389SMatthew Sakai 	 * stored in the block map page slot
297827c6389SMatthew Sakai 	 */
298827c6389SMatthew Sakai 	struct block_map_entry block_map_entry;
299827c6389SMatthew Sakai } __packed;
300827c6389SMatthew Sakai 
301827c6389SMatthew Sakai enum journal_operation_1 {
302827c6389SMatthew Sakai 	VDO_JOURNAL_DATA_DECREMENT = 0,
303827c6389SMatthew Sakai 	VDO_JOURNAL_DATA_INCREMENT = 1,
304827c6389SMatthew Sakai 	VDO_JOURNAL_BLOCK_MAP_DECREMENT = 2,
305827c6389SMatthew Sakai 	VDO_JOURNAL_BLOCK_MAP_INCREMENT = 3,
306827c6389SMatthew Sakai } __packed;
307827c6389SMatthew Sakai 
308827c6389SMatthew Sakai struct recovery_block_header {
309827c6389SMatthew Sakai 	sequence_number_t block_map_head; /* Block map head sequence number */
310827c6389SMatthew Sakai 	sequence_number_t slab_journal_head; /* Slab journal head seq. number */
311827c6389SMatthew Sakai 	sequence_number_t sequence_number; /* Sequence number for this block */
312827c6389SMatthew Sakai 	nonce_t nonce; /* A given VDO instance's nonce */
313827c6389SMatthew Sakai 	block_count_t logical_blocks_used; /* Logical blocks in use */
314827c6389SMatthew Sakai 	block_count_t block_map_data_blocks; /* Allocated block map pages */
315827c6389SMatthew Sakai 	journal_entry_count_t entry_count; /* Number of entries written */
316827c6389SMatthew Sakai 	u8 check_byte; /* The protection check byte */
317827c6389SMatthew Sakai 	u8 recovery_count; /* Number of recoveries completed */
318827c6389SMatthew Sakai 	enum vdo_metadata_type metadata_type; /* Metadata type */
319827c6389SMatthew Sakai };
320827c6389SMatthew Sakai 
321827c6389SMatthew Sakai /*
322827c6389SMatthew Sakai  * The packed, on-disk representation of a recovery journal block header. All fields are kept in
323827c6389SMatthew Sakai  * little-endian byte order.
324827c6389SMatthew Sakai  */
325827c6389SMatthew Sakai struct packed_journal_header {
326827c6389SMatthew Sakai 	/* Block map head 64-bit sequence number */
327827c6389SMatthew Sakai 	__le64 block_map_head;
328827c6389SMatthew Sakai 
329827c6389SMatthew Sakai 	/* Slab journal head 64-bit sequence number */
330827c6389SMatthew Sakai 	__le64 slab_journal_head;
331827c6389SMatthew Sakai 
332827c6389SMatthew Sakai 	/* The 64-bit sequence number for this block */
333827c6389SMatthew Sakai 	__le64 sequence_number;
334827c6389SMatthew Sakai 
335827c6389SMatthew Sakai 	/* A given VDO instance's 64-bit nonce */
336827c6389SMatthew Sakai 	__le64 nonce;
337827c6389SMatthew Sakai 
338827c6389SMatthew Sakai 	/* 8-bit metadata type (should always be one for the recovery journal) */
339827c6389SMatthew Sakai 	u8 metadata_type;
340827c6389SMatthew Sakai 
341827c6389SMatthew Sakai 	/* 16-bit count of the entries encoded in the block */
342827c6389SMatthew Sakai 	__le16 entry_count;
343827c6389SMatthew Sakai 
344827c6389SMatthew Sakai 	/* 64-bit count of the logical blocks used when this block was opened */
345827c6389SMatthew Sakai 	__le64 logical_blocks_used;
346827c6389SMatthew Sakai 
347827c6389SMatthew Sakai 	/* 64-bit count of the block map blocks used when this block was opened */
348827c6389SMatthew Sakai 	__le64 block_map_data_blocks;
349827c6389SMatthew Sakai 
350827c6389SMatthew Sakai 	/* The protection check byte */
351827c6389SMatthew Sakai 	u8 check_byte;
352827c6389SMatthew Sakai 
353827c6389SMatthew Sakai 	/* The number of recoveries completed */
354827c6389SMatthew Sakai 	u8 recovery_count;
355827c6389SMatthew Sakai } __packed;
356827c6389SMatthew Sakai 
357827c6389SMatthew Sakai struct packed_journal_sector {
358827c6389SMatthew Sakai 	/* The protection check byte */
359827c6389SMatthew Sakai 	u8 check_byte;
360827c6389SMatthew Sakai 
361827c6389SMatthew Sakai 	/* The number of recoveries completed */
362827c6389SMatthew Sakai 	u8 recovery_count;
363827c6389SMatthew Sakai 
364827c6389SMatthew Sakai 	/* The number of entries in this sector */
365827c6389SMatthew Sakai 	u8 entry_count;
366827c6389SMatthew Sakai 
367827c6389SMatthew Sakai 	/* Journal entries for this sector */
368827c6389SMatthew Sakai 	struct packed_recovery_journal_entry entries[];
369827c6389SMatthew Sakai } __packed;
370827c6389SMatthew Sakai 
371827c6389SMatthew Sakai enum {
372827c6389SMatthew Sakai 	/* The number of entries in each sector (except the last) when filled */
373827c6389SMatthew Sakai 	RECOVERY_JOURNAL_ENTRIES_PER_SECTOR =
374827c6389SMatthew Sakai 		((VDO_SECTOR_SIZE - sizeof(struct packed_journal_sector)) /
375827c6389SMatthew Sakai 		 sizeof(struct packed_recovery_journal_entry)),
376827c6389SMatthew Sakai 	RECOVERY_JOURNAL_ENTRIES_PER_BLOCK = RECOVERY_JOURNAL_ENTRIES_PER_SECTOR * 7,
377827c6389SMatthew Sakai 	/* The number of entries in a v1 recovery journal block. */
378827c6389SMatthew Sakai 	RECOVERY_JOURNAL_1_ENTRIES_PER_BLOCK = 311,
379827c6389SMatthew Sakai 	/* The number of entries in each v1 sector (except the last) when filled */
380827c6389SMatthew Sakai 	RECOVERY_JOURNAL_1_ENTRIES_PER_SECTOR =
381827c6389SMatthew Sakai 		((VDO_SECTOR_SIZE - sizeof(struct packed_journal_sector)) /
382827c6389SMatthew Sakai 		 sizeof(struct packed_recovery_journal_entry_1)),
383827c6389SMatthew Sakai 	/* The number of entries in the last sector when a block is full */
384827c6389SMatthew Sakai 	RECOVERY_JOURNAL_1_ENTRIES_IN_LAST_SECTOR =
385827c6389SMatthew Sakai 		(RECOVERY_JOURNAL_1_ENTRIES_PER_BLOCK % RECOVERY_JOURNAL_1_ENTRIES_PER_SECTOR),
386827c6389SMatthew Sakai };
387827c6389SMatthew Sakai 
388827c6389SMatthew Sakai /* A type representing a reference count of a block. */
389827c6389SMatthew Sakai typedef u8 vdo_refcount_t;
390827c6389SMatthew Sakai 
391827c6389SMatthew Sakai /* The absolute position of an entry in a recovery journal or slab journal. */
392827c6389SMatthew Sakai struct journal_point {
393827c6389SMatthew Sakai 	sequence_number_t sequence_number;
394827c6389SMatthew Sakai 	journal_entry_count_t entry_count;
395827c6389SMatthew Sakai };
396827c6389SMatthew Sakai 
397827c6389SMatthew Sakai /* A packed, platform-independent encoding of a struct journal_point. */
398827c6389SMatthew Sakai struct packed_journal_point {
399827c6389SMatthew Sakai 	/*
400827c6389SMatthew Sakai 	 * The packed representation is the little-endian 64-bit representation of the low-order 48
401827c6389SMatthew Sakai 	 * bits of the sequence number, shifted up 16 bits, or'ed with the 16-bit entry count.
402827c6389SMatthew Sakai 	 *
403827c6389SMatthew Sakai 	 * Very long-term, the top 16 bits of the sequence number may not always be zero, as this
404827c6389SMatthew Sakai 	 * encoding assumes--see BZ 1523240.
405827c6389SMatthew Sakai 	 */
406827c6389SMatthew Sakai 	__le64 encoded_point;
407827c6389SMatthew Sakai } __packed;
408827c6389SMatthew Sakai 
409827c6389SMatthew Sakai /* Special vdo_refcount_t values. */
410827c6389SMatthew Sakai #define EMPTY_REFERENCE_COUNT 0
411827c6389SMatthew Sakai enum {
412827c6389SMatthew Sakai 	MAXIMUM_REFERENCE_COUNT = 254,
413827c6389SMatthew Sakai 	PROVISIONAL_REFERENCE_COUNT = 255,
414827c6389SMatthew Sakai };
415827c6389SMatthew Sakai 
416827c6389SMatthew Sakai enum {
417827c6389SMatthew Sakai 	COUNTS_PER_SECTOR =
418827c6389SMatthew Sakai 		((VDO_SECTOR_SIZE - sizeof(struct packed_journal_point)) / sizeof(vdo_refcount_t)),
419827c6389SMatthew Sakai 	COUNTS_PER_BLOCK = COUNTS_PER_SECTOR * VDO_SECTORS_PER_BLOCK,
420827c6389SMatthew Sakai };
421827c6389SMatthew Sakai 
422827c6389SMatthew Sakai /* The format of each sector of a reference_block on disk. */
423827c6389SMatthew Sakai struct packed_reference_sector {
424827c6389SMatthew Sakai 	struct packed_journal_point commit_point;
425827c6389SMatthew Sakai 	vdo_refcount_t counts[COUNTS_PER_SECTOR];
426827c6389SMatthew Sakai } __packed;
427827c6389SMatthew Sakai 
428827c6389SMatthew Sakai struct packed_reference_block {
429827c6389SMatthew Sakai 	struct packed_reference_sector sectors[VDO_SECTORS_PER_BLOCK];
430827c6389SMatthew Sakai };
431827c6389SMatthew Sakai 
432827c6389SMatthew Sakai struct slab_depot_state_2_0 {
433827c6389SMatthew Sakai 	struct slab_config slab_config;
434827c6389SMatthew Sakai 	physical_block_number_t first_block;
435827c6389SMatthew Sakai 	physical_block_number_t last_block;
436827c6389SMatthew Sakai 	zone_count_t zone_count;
437827c6389SMatthew Sakai } __packed;
438827c6389SMatthew Sakai 
439827c6389SMatthew Sakai extern const struct header VDO_SLAB_DEPOT_HEADER_2_0;
440827c6389SMatthew Sakai 
441827c6389SMatthew Sakai /*
442827c6389SMatthew Sakai  * vdo_slab journal blocks may have one of two formats, depending upon whether or not any of the
443827c6389SMatthew Sakai  * entries in the block are block map increments. Since the steady state for a VDO is that all of
444827c6389SMatthew Sakai  * the necessary block map pages will be allocated, most slab journal blocks will have only data
445827c6389SMatthew Sakai  * entries. Such blocks can hold more entries, hence the two formats.
446827c6389SMatthew Sakai  */
447827c6389SMatthew Sakai 
448827c6389SMatthew Sakai /* A single slab journal entry */
449827c6389SMatthew Sakai struct slab_journal_entry {
450827c6389SMatthew Sakai 	slab_block_number sbn;
451827c6389SMatthew Sakai 	enum journal_operation operation;
452827c6389SMatthew Sakai 	bool increment;
453827c6389SMatthew Sakai };
454827c6389SMatthew Sakai 
455827c6389SMatthew Sakai /* A single slab journal entry in its on-disk form */
456827c6389SMatthew Sakai typedef struct {
457827c6389SMatthew Sakai 	u8 offset_low8;
458827c6389SMatthew Sakai 	u8 offset_mid8;
459827c6389SMatthew Sakai 
460827c6389SMatthew Sakai #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
461827c6389SMatthew Sakai 	unsigned offset_high7 : 7;
462827c6389SMatthew Sakai 	unsigned increment : 1;
463827c6389SMatthew Sakai #else
464827c6389SMatthew Sakai 	unsigned increment : 1;
465827c6389SMatthew Sakai 	unsigned offset_high7 : 7;
466827c6389SMatthew Sakai #endif
467827c6389SMatthew Sakai } __packed packed_slab_journal_entry;
468827c6389SMatthew Sakai 
469827c6389SMatthew Sakai /* The unpacked representation of the header of a slab journal block */
470827c6389SMatthew Sakai struct slab_journal_block_header {
471827c6389SMatthew Sakai 	/* Sequence number for head of journal */
472827c6389SMatthew Sakai 	sequence_number_t head;
473827c6389SMatthew Sakai 	/* Sequence number for this block */
474827c6389SMatthew Sakai 	sequence_number_t sequence_number;
475827c6389SMatthew Sakai 	/* The nonce for a given VDO instance */
476827c6389SMatthew Sakai 	nonce_t nonce;
477827c6389SMatthew Sakai 	/* Recovery journal point for last entry */
478827c6389SMatthew Sakai 	struct journal_point recovery_point;
479827c6389SMatthew Sakai 	/* Metadata type */
480827c6389SMatthew Sakai 	enum vdo_metadata_type metadata_type;
481827c6389SMatthew Sakai 	/* Whether this block contains block map increments */
482827c6389SMatthew Sakai 	bool has_block_map_increments;
483827c6389SMatthew Sakai 	/* The number of entries in the block */
484827c6389SMatthew Sakai 	journal_entry_count_t entry_count;
485827c6389SMatthew Sakai };
486827c6389SMatthew Sakai 
487827c6389SMatthew Sakai /*
488827c6389SMatthew Sakai  * The packed, on-disk representation of a slab journal block header. All fields are kept in
489827c6389SMatthew Sakai  * little-endian byte order.
490827c6389SMatthew Sakai  */
491827c6389SMatthew Sakai struct packed_slab_journal_block_header {
492827c6389SMatthew Sakai 	/* 64-bit sequence number for head of journal */
493827c6389SMatthew Sakai 	__le64 head;
494827c6389SMatthew Sakai 	/* 64-bit sequence number for this block */
495827c6389SMatthew Sakai 	__le64 sequence_number;
496827c6389SMatthew Sakai 	/* Recovery journal point for the last entry, packed into 64 bits */
497827c6389SMatthew Sakai 	struct packed_journal_point recovery_point;
498827c6389SMatthew Sakai 	/* The 64-bit nonce for a given VDO instance */
499827c6389SMatthew Sakai 	__le64 nonce;
500827c6389SMatthew Sakai 	/* 8-bit metadata type (should always be two, for the slab journal) */
501827c6389SMatthew Sakai 	u8 metadata_type;
502827c6389SMatthew Sakai 	/* Whether this block contains block map increments */
503827c6389SMatthew Sakai 	bool has_block_map_increments;
504827c6389SMatthew Sakai 	/* 16-bit count of the entries encoded in the block */
505827c6389SMatthew Sakai 	__le16 entry_count;
506827c6389SMatthew Sakai } __packed;
507827c6389SMatthew Sakai 
508827c6389SMatthew Sakai enum {
509827c6389SMatthew Sakai 	VDO_SLAB_JOURNAL_PAYLOAD_SIZE =
510827c6389SMatthew Sakai 		VDO_BLOCK_SIZE - sizeof(struct packed_slab_journal_block_header),
511827c6389SMatthew Sakai 	VDO_SLAB_JOURNAL_FULL_ENTRIES_PER_BLOCK = (VDO_SLAB_JOURNAL_PAYLOAD_SIZE * 8) / 25,
512827c6389SMatthew Sakai 	VDO_SLAB_JOURNAL_ENTRY_TYPES_SIZE =
513827c6389SMatthew Sakai 		((VDO_SLAB_JOURNAL_FULL_ENTRIES_PER_BLOCK - 1) / 8) + 1,
514827c6389SMatthew Sakai 	VDO_SLAB_JOURNAL_ENTRIES_PER_BLOCK =
515827c6389SMatthew Sakai 		(VDO_SLAB_JOURNAL_PAYLOAD_SIZE / sizeof(packed_slab_journal_entry)),
516827c6389SMatthew Sakai };
517827c6389SMatthew Sakai 
518827c6389SMatthew Sakai /* The payload of a slab journal block which has block map increments */
519827c6389SMatthew Sakai struct full_slab_journal_entries {
520827c6389SMatthew Sakai 	/* The entries themselves */
521827c6389SMatthew Sakai 	packed_slab_journal_entry entries[VDO_SLAB_JOURNAL_FULL_ENTRIES_PER_BLOCK];
522827c6389SMatthew Sakai 	/* The bit map indicating which entries are block map increments */
523827c6389SMatthew Sakai 	u8 entry_types[VDO_SLAB_JOURNAL_ENTRY_TYPES_SIZE];
524827c6389SMatthew Sakai } __packed;
525827c6389SMatthew Sakai 
526827c6389SMatthew Sakai typedef union {
527827c6389SMatthew Sakai 	/* Entries which include block map increments */
528827c6389SMatthew Sakai 	struct full_slab_journal_entries full_entries;
529827c6389SMatthew Sakai 	/* Entries which are only data updates */
530827c6389SMatthew Sakai 	packed_slab_journal_entry entries[VDO_SLAB_JOURNAL_ENTRIES_PER_BLOCK];
531827c6389SMatthew Sakai 	/* Ensure the payload fills to the end of the block */
532827c6389SMatthew Sakai 	u8 space[VDO_SLAB_JOURNAL_PAYLOAD_SIZE];
533827c6389SMatthew Sakai } __packed slab_journal_payload;
534827c6389SMatthew Sakai 
535827c6389SMatthew Sakai struct packed_slab_journal_block {
536827c6389SMatthew Sakai 	struct packed_slab_journal_block_header header;
537827c6389SMatthew Sakai 	slab_journal_payload payload;
538827c6389SMatthew Sakai } __packed;
539827c6389SMatthew Sakai 
540827c6389SMatthew Sakai /* The offset of a slab journal tail block. */
541827c6389SMatthew Sakai typedef u8 tail_block_offset_t;
542827c6389SMatthew Sakai 
543827c6389SMatthew Sakai struct slab_summary_entry {
544827c6389SMatthew Sakai 	/* Bits 7..0: The offset of the tail block within the slab journal */
545827c6389SMatthew Sakai 	tail_block_offset_t tail_block_offset;
546827c6389SMatthew Sakai 
547827c6389SMatthew Sakai #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
548827c6389SMatthew Sakai 	/* Bits 13..8: A hint about the fullness of the slab */
549827c6389SMatthew Sakai 	unsigned int fullness_hint : 6;
550827c6389SMatthew Sakai 	/* Bit 14: Whether the ref_counts must be loaded from the layer */
551827c6389SMatthew Sakai 	unsigned int load_ref_counts : 1;
552827c6389SMatthew Sakai 	/* Bit 15: The believed cleanliness of this slab */
553827c6389SMatthew Sakai 	unsigned int is_dirty : 1;
554827c6389SMatthew Sakai #else
555827c6389SMatthew Sakai 	/* Bit 15: The believed cleanliness of this slab */
556827c6389SMatthew Sakai 	unsigned int is_dirty : 1;
557827c6389SMatthew Sakai 	/* Bit 14: Whether the ref_counts must be loaded from the layer */
558827c6389SMatthew Sakai 	unsigned int load_ref_counts : 1;
559827c6389SMatthew Sakai 	/* Bits 13..8: A hint about the fullness of the slab */
560827c6389SMatthew Sakai 	unsigned int fullness_hint : 6;
561827c6389SMatthew Sakai #endif
562827c6389SMatthew Sakai } __packed;
563827c6389SMatthew Sakai 
564827c6389SMatthew Sakai enum {
565827c6389SMatthew Sakai 	VDO_SLAB_SUMMARY_FULLNESS_HINT_BITS = 6,
566827c6389SMatthew Sakai 	VDO_SLAB_SUMMARY_ENTRIES_PER_BLOCK = VDO_BLOCK_SIZE / sizeof(struct slab_summary_entry),
567827c6389SMatthew Sakai 	VDO_SLAB_SUMMARY_BLOCKS_PER_ZONE = MAX_VDO_SLABS / VDO_SLAB_SUMMARY_ENTRIES_PER_BLOCK,
568827c6389SMatthew Sakai 	VDO_SLAB_SUMMARY_BLOCKS = VDO_SLAB_SUMMARY_BLOCKS_PER_ZONE * MAX_VDO_PHYSICAL_ZONES,
569827c6389SMatthew Sakai };
570827c6389SMatthew Sakai 
571827c6389SMatthew Sakai struct layout {
572827c6389SMatthew Sakai 	physical_block_number_t start;
573827c6389SMatthew Sakai 	block_count_t size;
574827c6389SMatthew Sakai 	physical_block_number_t first_free;
575827c6389SMatthew Sakai 	physical_block_number_t last_free;
576827c6389SMatthew Sakai 	size_t num_partitions;
577827c6389SMatthew Sakai 	struct partition *head;
578827c6389SMatthew Sakai };
579827c6389SMatthew Sakai 
580827c6389SMatthew Sakai struct partition {
581827c6389SMatthew Sakai 	enum partition_id id; /* The id of this partition */
582827c6389SMatthew Sakai 	physical_block_number_t offset; /* The offset into the layout of this partition */
583827c6389SMatthew Sakai 	block_count_t count; /* The number of blocks in the partition */
584827c6389SMatthew Sakai 	struct partition *next; /* A pointer to the next partition in the layout */
585827c6389SMatthew Sakai };
586827c6389SMatthew Sakai 
587827c6389SMatthew Sakai struct layout_3_0 {
588827c6389SMatthew Sakai 	physical_block_number_t first_free;
589827c6389SMatthew Sakai 	physical_block_number_t last_free;
590827c6389SMatthew Sakai 	u8 partition_count;
591827c6389SMatthew Sakai } __packed;
592827c6389SMatthew Sakai 
593827c6389SMatthew Sakai struct partition_3_0 {
594827c6389SMatthew Sakai 	enum partition_id id;
595827c6389SMatthew Sakai 	physical_block_number_t offset;
596827c6389SMatthew Sakai 	physical_block_number_t base; /* unused but retained for backwards compatibility */
597827c6389SMatthew Sakai 	block_count_t count;
598827c6389SMatthew Sakai } __packed;
599827c6389SMatthew Sakai 
600827c6389SMatthew Sakai /*
601827c6389SMatthew Sakai  * The configuration of the VDO service.
602827c6389SMatthew Sakai  */
603827c6389SMatthew Sakai struct vdo_config {
604827c6389SMatthew Sakai 	block_count_t logical_blocks; /* number of logical blocks */
605827c6389SMatthew Sakai 	block_count_t physical_blocks; /* number of physical blocks */
606827c6389SMatthew Sakai 	block_count_t slab_size; /* number of blocks in a slab */
607827c6389SMatthew Sakai 	block_count_t recovery_journal_size; /* number of recovery journal blocks */
608827c6389SMatthew Sakai 	block_count_t slab_journal_blocks; /* number of slab journal blocks */
609827c6389SMatthew Sakai };
610827c6389SMatthew Sakai 
611827c6389SMatthew Sakai /* This is the structure that captures the vdo fields saved as a super block component. */
612827c6389SMatthew Sakai struct vdo_component {
613827c6389SMatthew Sakai 	enum vdo_state state;
614827c6389SMatthew Sakai 	u64 complete_recoveries;
615827c6389SMatthew Sakai 	u64 read_only_recoveries;
616827c6389SMatthew Sakai 	struct vdo_config config;
617827c6389SMatthew Sakai 	nonce_t nonce;
618827c6389SMatthew Sakai };
619827c6389SMatthew Sakai 
620827c6389SMatthew Sakai /*
621827c6389SMatthew Sakai  * A packed, machine-independent, on-disk representation of the vdo_config in the VDO component
622827c6389SMatthew Sakai  * data in the super block.
623827c6389SMatthew Sakai  */
624827c6389SMatthew Sakai struct packed_vdo_config {
625827c6389SMatthew Sakai 	__le64 logical_blocks;
626827c6389SMatthew Sakai 	__le64 physical_blocks;
627827c6389SMatthew Sakai 	__le64 slab_size;
628827c6389SMatthew Sakai 	__le64 recovery_journal_size;
629827c6389SMatthew Sakai 	__le64 slab_journal_blocks;
630827c6389SMatthew Sakai } __packed;
631827c6389SMatthew Sakai 
632827c6389SMatthew Sakai /*
633827c6389SMatthew Sakai  * A packed, machine-independent, on-disk representation of version 41.0 of the VDO component data
634827c6389SMatthew Sakai  * in the super block.
635827c6389SMatthew Sakai  */
636827c6389SMatthew Sakai struct packed_vdo_component_41_0 {
637827c6389SMatthew Sakai 	__le32 state;
638827c6389SMatthew Sakai 	__le64 complete_recoveries;
639827c6389SMatthew Sakai 	__le64 read_only_recoveries;
640827c6389SMatthew Sakai 	struct packed_vdo_config config;
641827c6389SMatthew Sakai 	__le64 nonce;
642827c6389SMatthew Sakai } __packed;
643827c6389SMatthew Sakai 
644827c6389SMatthew Sakai /*
645827c6389SMatthew Sakai  * The version of the on-disk format of a VDO volume. This should be incremented any time the
646827c6389SMatthew Sakai  * on-disk representation of any VDO structure changes. Changes which require only online upgrade
647827c6389SMatthew Sakai  * steps should increment the minor version. Changes which require an offline upgrade or which can
648827c6389SMatthew Sakai  * not be upgraded to at all should increment the major version and set the minor version to 0.
649827c6389SMatthew Sakai  */
650827c6389SMatthew Sakai extern const struct version_number VDO_VOLUME_VERSION_67_0;
651827c6389SMatthew Sakai 
652827c6389SMatthew Sakai enum {
653827c6389SMatthew Sakai 	VDO_ENCODED_HEADER_SIZE = sizeof(struct packed_header),
654827c6389SMatthew Sakai 	BLOCK_MAP_COMPONENT_ENCODED_SIZE =
655827c6389SMatthew Sakai 		VDO_ENCODED_HEADER_SIZE + sizeof(struct block_map_state_2_0),
656827c6389SMatthew Sakai 	RECOVERY_JOURNAL_COMPONENT_ENCODED_SIZE =
657827c6389SMatthew Sakai 		VDO_ENCODED_HEADER_SIZE + sizeof(struct recovery_journal_state_7_0),
658827c6389SMatthew Sakai 	SLAB_DEPOT_COMPONENT_ENCODED_SIZE =
659827c6389SMatthew Sakai 		VDO_ENCODED_HEADER_SIZE + sizeof(struct slab_depot_state_2_0),
660827c6389SMatthew Sakai 	VDO_PARTITION_COUNT = 4,
661827c6389SMatthew Sakai 	VDO_LAYOUT_ENCODED_SIZE = (VDO_ENCODED_HEADER_SIZE +
662827c6389SMatthew Sakai 				   sizeof(struct layout_3_0) +
663827c6389SMatthew Sakai 				   (sizeof(struct partition_3_0) * VDO_PARTITION_COUNT)),
664827c6389SMatthew Sakai 	VDO_SUPER_BLOCK_FIXED_SIZE = VDO_ENCODED_HEADER_SIZE + sizeof(u32),
665827c6389SMatthew Sakai 	VDO_MAX_COMPONENT_DATA_SIZE = VDO_SECTOR_SIZE - VDO_SUPER_BLOCK_FIXED_SIZE,
666827c6389SMatthew Sakai 	VDO_COMPONENT_ENCODED_SIZE =
667827c6389SMatthew Sakai 		(sizeof(struct packed_version_number) + sizeof(struct packed_vdo_component_41_0)),
668827c6389SMatthew Sakai 	VDO_COMPONENT_DATA_OFFSET = VDO_ENCODED_HEADER_SIZE,
669827c6389SMatthew Sakai 	VDO_COMPONENT_DATA_SIZE = (sizeof(u32) +
670827c6389SMatthew Sakai 				   sizeof(struct packed_version_number) +
671827c6389SMatthew Sakai 				   VDO_COMPONENT_ENCODED_SIZE +
672827c6389SMatthew Sakai 				   VDO_LAYOUT_ENCODED_SIZE +
673827c6389SMatthew Sakai 				   RECOVERY_JOURNAL_COMPONENT_ENCODED_SIZE +
674827c6389SMatthew Sakai 				   SLAB_DEPOT_COMPONENT_ENCODED_SIZE +
675827c6389SMatthew Sakai 				   BLOCK_MAP_COMPONENT_ENCODED_SIZE),
676827c6389SMatthew Sakai };
677827c6389SMatthew Sakai 
678827c6389SMatthew Sakai /* The entirety of the component data encoded in the VDO super block. */
679827c6389SMatthew Sakai struct vdo_component_states {
680827c6389SMatthew Sakai 	/* For backwards compatibility */
681827c6389SMatthew Sakai 	u32 unused;
682827c6389SMatthew Sakai 
683827c6389SMatthew Sakai 	/* The VDO volume version */
684827c6389SMatthew Sakai 	struct version_number volume_version;
685827c6389SMatthew Sakai 
686827c6389SMatthew Sakai 	/* Components */
687827c6389SMatthew Sakai 	struct vdo_component vdo;
688827c6389SMatthew Sakai 	struct block_map_state_2_0 block_map;
689827c6389SMatthew Sakai 	struct recovery_journal_state_7_0 recovery_journal;
690827c6389SMatthew Sakai 	struct slab_depot_state_2_0 slab_depot;
691827c6389SMatthew Sakai 
692827c6389SMatthew Sakai 	/* Our partitioning of the underlying storage */
693827c6389SMatthew Sakai 	struct layout layout;
694827c6389SMatthew Sakai };
695827c6389SMatthew Sakai 
696827c6389SMatthew Sakai /**
697827c6389SMatthew Sakai  * vdo_are_same_version() - Check whether two version numbers are the same.
698827c6389SMatthew Sakai  * @version_a: The first version.
699827c6389SMatthew Sakai  * @version_b: The second version.
700827c6389SMatthew Sakai  *
701827c6389SMatthew Sakai  * Return: true if the two versions are the same.
702827c6389SMatthew Sakai  */
vdo_are_same_version(struct version_number version_a,struct version_number version_b)703827c6389SMatthew Sakai static inline bool vdo_are_same_version(struct version_number version_a,
704827c6389SMatthew Sakai 					struct version_number version_b)
705827c6389SMatthew Sakai {
706827c6389SMatthew Sakai 	return ((version_a.major_version == version_b.major_version) &&
707827c6389SMatthew Sakai 		(version_a.minor_version == version_b.minor_version));
708827c6389SMatthew Sakai }
709827c6389SMatthew Sakai 
710827c6389SMatthew Sakai /**
711827c6389SMatthew Sakai  * vdo_is_upgradable_version() - Check whether an actual version is upgradable to an expected
712827c6389SMatthew Sakai  *                               version.
713827c6389SMatthew Sakai  * @expected_version: The expected version.
714827c6389SMatthew Sakai  * @actual_version: The version being validated.
715827c6389SMatthew Sakai  *
716827c6389SMatthew Sakai  * An actual version is upgradable if its major number is expected but its minor number differs,
717827c6389SMatthew Sakai  * and the expected version's minor number is greater than the actual version's minor number.
718827c6389SMatthew Sakai  *
719827c6389SMatthew Sakai  * Return: true if the actual version is upgradable.
720827c6389SMatthew Sakai  */
vdo_is_upgradable_version(struct version_number expected_version,struct version_number actual_version)721827c6389SMatthew Sakai static inline bool vdo_is_upgradable_version(struct version_number expected_version,
722827c6389SMatthew Sakai 					     struct version_number actual_version)
723827c6389SMatthew Sakai {
724827c6389SMatthew Sakai 	return ((expected_version.major_version == actual_version.major_version) &&
725827c6389SMatthew Sakai 		(expected_version.minor_version > actual_version.minor_version));
726827c6389SMatthew Sakai }
727827c6389SMatthew Sakai 
728827c6389SMatthew Sakai int __must_check vdo_validate_header(const struct header *expected_header,
729827c6389SMatthew Sakai 				     const struct header *actual_header, bool exact_size,
730827c6389SMatthew Sakai 				     const char *component_name);
731827c6389SMatthew Sakai 
732827c6389SMatthew Sakai void vdo_encode_header(u8 *buffer, size_t *offset, const struct header *header);
733827c6389SMatthew Sakai void vdo_decode_header(u8 *buffer, size_t *offset, struct header *header);
734827c6389SMatthew Sakai 
735827c6389SMatthew Sakai /**
736827c6389SMatthew Sakai  * vdo_pack_version_number() - Convert a version_number to its packed on-disk representation.
737827c6389SMatthew Sakai  * @version: The version number to convert.
738827c6389SMatthew Sakai  *
739827c6389SMatthew Sakai  * Return: the platform-independent representation of the version
740827c6389SMatthew Sakai  */
vdo_pack_version_number(struct version_number version)741827c6389SMatthew Sakai static inline struct packed_version_number vdo_pack_version_number(struct version_number version)
742827c6389SMatthew Sakai {
743827c6389SMatthew Sakai 	return (struct packed_version_number) {
744827c6389SMatthew Sakai 		.major_version = __cpu_to_le32(version.major_version),
745827c6389SMatthew Sakai 		.minor_version = __cpu_to_le32(version.minor_version),
746827c6389SMatthew Sakai 	};
747827c6389SMatthew Sakai }
748827c6389SMatthew Sakai 
749827c6389SMatthew Sakai /**
750827c6389SMatthew Sakai  * vdo_unpack_version_number() - Convert a packed_version_number to its native in-memory
751827c6389SMatthew Sakai  *                               representation.
752827c6389SMatthew Sakai  * @version: The version number to convert.
753827c6389SMatthew Sakai  *
754827c6389SMatthew Sakai  * Return: The platform-independent representation of the version.
755827c6389SMatthew Sakai  */
vdo_unpack_version_number(struct packed_version_number version)756827c6389SMatthew Sakai static inline struct version_number vdo_unpack_version_number(struct packed_version_number version)
757827c6389SMatthew Sakai {
758827c6389SMatthew Sakai 	return (struct version_number) {
759827c6389SMatthew Sakai 		.major_version = __le32_to_cpu(version.major_version),
760827c6389SMatthew Sakai 		.minor_version = __le32_to_cpu(version.minor_version),
761827c6389SMatthew Sakai 	};
762827c6389SMatthew Sakai }
763827c6389SMatthew Sakai 
764827c6389SMatthew Sakai /**
765827c6389SMatthew Sakai  * vdo_pack_header() - Convert a component header to its packed on-disk representation.
766827c6389SMatthew Sakai  * @header: The header to convert.
767827c6389SMatthew Sakai  *
768827c6389SMatthew Sakai  * Return: the platform-independent representation of the header
769827c6389SMatthew Sakai  */
vdo_pack_header(const struct header * header)770827c6389SMatthew Sakai static inline struct packed_header vdo_pack_header(const struct header *header)
771827c6389SMatthew Sakai {
772827c6389SMatthew Sakai 	return (struct packed_header) {
773827c6389SMatthew Sakai 		.id = __cpu_to_le32(header->id),
774827c6389SMatthew Sakai 		.version = vdo_pack_version_number(header->version),
775827c6389SMatthew Sakai 		.size = __cpu_to_le64(header->size),
776827c6389SMatthew Sakai 	};
777827c6389SMatthew Sakai }
778827c6389SMatthew Sakai 
779827c6389SMatthew Sakai /**
780827c6389SMatthew Sakai  * vdo_unpack_header() - Convert a packed_header to its native in-memory representation.
781827c6389SMatthew Sakai  * @header: The header to convert.
782827c6389SMatthew Sakai  *
783827c6389SMatthew Sakai  * Return: The platform-independent representation of the version.
784827c6389SMatthew Sakai  */
vdo_unpack_header(const struct packed_header * header)785827c6389SMatthew Sakai static inline struct header vdo_unpack_header(const struct packed_header *header)
786827c6389SMatthew Sakai {
787827c6389SMatthew Sakai 	return (struct header) {
788827c6389SMatthew Sakai 		.id = __le32_to_cpu(header->id),
789827c6389SMatthew Sakai 		.version = vdo_unpack_version_number(header->version),
790827c6389SMatthew Sakai 		.size = __le64_to_cpu(header->size),
791827c6389SMatthew Sakai 	};
792827c6389SMatthew Sakai }
793827c6389SMatthew Sakai 
794827c6389SMatthew Sakai /**
795827c6389SMatthew Sakai  * vdo_get_index_region_start() - Get the start of the index region from a geometry.
796827c6389SMatthew Sakai  * @geometry: The geometry.
797827c6389SMatthew Sakai  *
798827c6389SMatthew Sakai  * Return: The start of the index region.
799827c6389SMatthew Sakai  */
800827c6389SMatthew Sakai static inline physical_block_number_t __must_check
vdo_get_index_region_start(struct volume_geometry geometry)801827c6389SMatthew Sakai vdo_get_index_region_start(struct volume_geometry geometry)
802827c6389SMatthew Sakai {
803827c6389SMatthew Sakai 	return geometry.regions[VDO_INDEX_REGION].start_block;
804827c6389SMatthew Sakai }
805827c6389SMatthew Sakai 
806827c6389SMatthew Sakai /**
807827c6389SMatthew Sakai  * vdo_get_data_region_start() - Get the start of the data region from a geometry.
808827c6389SMatthew Sakai  * @geometry: The geometry.
809827c6389SMatthew Sakai  *
810827c6389SMatthew Sakai  * Return: The start of the data region.
811827c6389SMatthew Sakai  */
812827c6389SMatthew Sakai static inline physical_block_number_t __must_check
vdo_get_data_region_start(struct volume_geometry geometry)813827c6389SMatthew Sakai vdo_get_data_region_start(struct volume_geometry geometry)
814827c6389SMatthew Sakai {
815827c6389SMatthew Sakai 	return geometry.regions[VDO_DATA_REGION].start_block;
816827c6389SMatthew Sakai }
817827c6389SMatthew Sakai 
818827c6389SMatthew Sakai /**
819827c6389SMatthew Sakai  * vdo_get_index_region_size() - Get the size of the index region from a geometry.
820827c6389SMatthew Sakai  * @geometry: The geometry.
821827c6389SMatthew Sakai  *
822827c6389SMatthew Sakai  * Return: The size of the index region.
823827c6389SMatthew Sakai  */
824827c6389SMatthew Sakai static inline physical_block_number_t __must_check
vdo_get_index_region_size(struct volume_geometry geometry)825827c6389SMatthew Sakai vdo_get_index_region_size(struct volume_geometry geometry)
826827c6389SMatthew Sakai {
827827c6389SMatthew Sakai 	return vdo_get_data_region_start(geometry) -
828827c6389SMatthew Sakai 		vdo_get_index_region_start(geometry);
829827c6389SMatthew Sakai }
830827c6389SMatthew Sakai 
831827c6389SMatthew Sakai int __must_check vdo_parse_geometry_block(unsigned char *block,
832827c6389SMatthew Sakai 					  struct volume_geometry *geometry);
833827c6389SMatthew Sakai 
vdo_is_state_compressed(const enum block_mapping_state mapping_state)834827c6389SMatthew Sakai static inline bool vdo_is_state_compressed(const enum block_mapping_state mapping_state)
835827c6389SMatthew Sakai {
836827c6389SMatthew Sakai 	return (mapping_state > VDO_MAPPING_STATE_UNCOMPRESSED);
837827c6389SMatthew Sakai }
838827c6389SMatthew Sakai 
839827c6389SMatthew Sakai static inline struct block_map_entry
vdo_pack_block_map_entry(physical_block_number_t pbn,enum block_mapping_state mapping_state)840827c6389SMatthew Sakai vdo_pack_block_map_entry(physical_block_number_t pbn, enum block_mapping_state mapping_state)
841827c6389SMatthew Sakai {
842827c6389SMatthew Sakai 	return (struct block_map_entry) {
843827c6389SMatthew Sakai 		.mapping_state = (mapping_state & 0x0F),
844827c6389SMatthew Sakai 		.pbn_high_nibble = ((pbn >> 32) & 0x0F),
845827c6389SMatthew Sakai 		.pbn_low_word = __cpu_to_le32(pbn & UINT_MAX),
846827c6389SMatthew Sakai 	};
847827c6389SMatthew Sakai }
848827c6389SMatthew Sakai 
vdo_unpack_block_map_entry(const struct block_map_entry * entry)849827c6389SMatthew Sakai static inline struct data_location vdo_unpack_block_map_entry(const struct block_map_entry *entry)
850827c6389SMatthew Sakai {
851827c6389SMatthew Sakai 	physical_block_number_t low32 = __le32_to_cpu(entry->pbn_low_word);
852827c6389SMatthew Sakai 	physical_block_number_t high4 = entry->pbn_high_nibble;
853827c6389SMatthew Sakai 
854827c6389SMatthew Sakai 	return (struct data_location) {
855827c6389SMatthew Sakai 		.pbn = ((high4 << 32) | low32),
856827c6389SMatthew Sakai 		.state = entry->mapping_state,
857827c6389SMatthew Sakai 	};
858827c6389SMatthew Sakai }
859827c6389SMatthew Sakai 
vdo_is_mapped_location(const struct data_location * location)860827c6389SMatthew Sakai static inline bool vdo_is_mapped_location(const struct data_location *location)
861827c6389SMatthew Sakai {
862827c6389SMatthew Sakai 	return (location->state != VDO_MAPPING_STATE_UNMAPPED);
863827c6389SMatthew Sakai }
864827c6389SMatthew Sakai 
vdo_is_valid_location(const struct data_location * location)865827c6389SMatthew Sakai static inline bool vdo_is_valid_location(const struct data_location *location)
866827c6389SMatthew Sakai {
867827c6389SMatthew Sakai 	if (location->pbn == VDO_ZERO_BLOCK)
868827c6389SMatthew Sakai 		return !vdo_is_state_compressed(location->state);
869827c6389SMatthew Sakai 	else
870827c6389SMatthew Sakai 		return vdo_is_mapped_location(location);
871827c6389SMatthew Sakai }
872827c6389SMatthew Sakai 
873827c6389SMatthew Sakai static inline physical_block_number_t __must_check
vdo_get_block_map_page_pbn(const struct block_map_page * page)874827c6389SMatthew Sakai vdo_get_block_map_page_pbn(const struct block_map_page *page)
875827c6389SMatthew Sakai {
876827c6389SMatthew Sakai 	return __le64_to_cpu(page->header.pbn);
877827c6389SMatthew Sakai }
878827c6389SMatthew Sakai 
879827c6389SMatthew Sakai struct block_map_page *vdo_format_block_map_page(void *buffer, nonce_t nonce,
880827c6389SMatthew Sakai 						 physical_block_number_t pbn,
881827c6389SMatthew Sakai 						 bool initialized);
882827c6389SMatthew Sakai 
883827c6389SMatthew Sakai enum block_map_page_validity __must_check vdo_validate_block_map_page(struct block_map_page *page,
884827c6389SMatthew Sakai 								      nonce_t nonce,
885827c6389SMatthew Sakai 								      physical_block_number_t pbn);
886827c6389SMatthew Sakai 
vdo_compute_block_map_page_count(block_count_t entries)887827c6389SMatthew Sakai static inline page_count_t vdo_compute_block_map_page_count(block_count_t entries)
888827c6389SMatthew Sakai {
889827c6389SMatthew Sakai 	return DIV_ROUND_UP(entries, VDO_BLOCK_MAP_ENTRIES_PER_PAGE);
890827c6389SMatthew Sakai }
891827c6389SMatthew Sakai 
892827c6389SMatthew Sakai block_count_t __must_check vdo_compute_new_forest_pages(root_count_t root_count,
893827c6389SMatthew Sakai 							struct boundary *old_sizes,
894827c6389SMatthew Sakai 							block_count_t entries,
895827c6389SMatthew Sakai 							struct boundary *new_sizes);
896827c6389SMatthew Sakai 
897827c6389SMatthew Sakai /**
898827c6389SMatthew Sakai  * vdo_pack_recovery_journal_entry() - Return the packed, on-disk representation of a recovery
899827c6389SMatthew Sakai  *                                     journal entry.
900827c6389SMatthew Sakai  * @entry: The journal entry to pack.
901827c6389SMatthew Sakai  *
902827c6389SMatthew Sakai  * Return: The packed representation of the journal entry.
903827c6389SMatthew Sakai  */
904827c6389SMatthew Sakai static inline struct packed_recovery_journal_entry
vdo_pack_recovery_journal_entry(const struct recovery_journal_entry * entry)905827c6389SMatthew Sakai vdo_pack_recovery_journal_entry(const struct recovery_journal_entry *entry)
906827c6389SMatthew Sakai {
907827c6389SMatthew Sakai 	return (struct packed_recovery_journal_entry) {
908827c6389SMatthew Sakai 		.operation = entry->operation,
909827c6389SMatthew Sakai 		.slot_low = entry->slot.slot & 0x3F,
910827c6389SMatthew Sakai 		.slot_high = (entry->slot.slot >> 6) & 0x0F,
911827c6389SMatthew Sakai 		.pbn_high_nibble = (entry->slot.pbn >> 32) & 0x0F,
912827c6389SMatthew Sakai 		.pbn_low_word = __cpu_to_le32(entry->slot.pbn & UINT_MAX),
913827c6389SMatthew Sakai 		.mapping = vdo_pack_block_map_entry(entry->mapping.pbn,
914827c6389SMatthew Sakai 						    entry->mapping.state),
915827c6389SMatthew Sakai 		.unmapping = vdo_pack_block_map_entry(entry->unmapping.pbn,
916827c6389SMatthew Sakai 						      entry->unmapping.state),
917827c6389SMatthew Sakai 	};
918827c6389SMatthew Sakai }
919827c6389SMatthew Sakai 
920827c6389SMatthew Sakai /**
921827c6389SMatthew Sakai  * vdo_unpack_recovery_journal_entry() - Unpack the on-disk representation of a recovery journal
922827c6389SMatthew Sakai  *                                       entry.
923827c6389SMatthew Sakai  * @entry: The recovery journal entry to unpack.
924827c6389SMatthew Sakai  *
925827c6389SMatthew Sakai  * Return: The unpacked entry.
926827c6389SMatthew Sakai  */
927827c6389SMatthew Sakai static inline struct recovery_journal_entry
vdo_unpack_recovery_journal_entry(const struct packed_recovery_journal_entry * entry)928827c6389SMatthew Sakai vdo_unpack_recovery_journal_entry(const struct packed_recovery_journal_entry *entry)
929827c6389SMatthew Sakai {
930827c6389SMatthew Sakai 	physical_block_number_t low32 = __le32_to_cpu(entry->pbn_low_word);
931827c6389SMatthew Sakai 	physical_block_number_t high4 = entry->pbn_high_nibble;
932827c6389SMatthew Sakai 
933827c6389SMatthew Sakai 	return (struct recovery_journal_entry) {
934827c6389SMatthew Sakai 		.operation = entry->operation,
935827c6389SMatthew Sakai 		.slot = {
936827c6389SMatthew Sakai 			.pbn = ((high4 << 32) | low32),
937827c6389SMatthew Sakai 			.slot = (entry->slot_low | (entry->slot_high << 6)),
938827c6389SMatthew Sakai 		},
939827c6389SMatthew Sakai 		.mapping = vdo_unpack_block_map_entry(&entry->mapping),
940827c6389SMatthew Sakai 		.unmapping = vdo_unpack_block_map_entry(&entry->unmapping),
941827c6389SMatthew Sakai 	};
942827c6389SMatthew Sakai }
943827c6389SMatthew Sakai 
944827c6389SMatthew Sakai const char * __must_check vdo_get_journal_operation_name(enum journal_operation operation);
945827c6389SMatthew Sakai 
946827c6389SMatthew Sakai /**
947827c6389SMatthew Sakai  * vdo_is_valid_recovery_journal_sector() - Determine whether the header of the given sector could
948827c6389SMatthew Sakai  *                                          describe a valid sector for the given journal block
949827c6389SMatthew Sakai  *                                          header.
950827c6389SMatthew Sakai  * @header: The unpacked block header to compare against.
951827c6389SMatthew Sakai  * @sector: The packed sector to check.
952827c6389SMatthew Sakai  * @sector_number: The number of the sector being checked.
953827c6389SMatthew Sakai  *
954827c6389SMatthew Sakai  * Return: true if the sector matches the block header.
955827c6389SMatthew Sakai  */
956827c6389SMatthew Sakai static inline bool __must_check
vdo_is_valid_recovery_journal_sector(const struct recovery_block_header * header,const struct packed_journal_sector * sector,u8 sector_number)957827c6389SMatthew Sakai vdo_is_valid_recovery_journal_sector(const struct recovery_block_header *header,
958827c6389SMatthew Sakai 				     const struct packed_journal_sector *sector,
959827c6389SMatthew Sakai 				     u8 sector_number)
960827c6389SMatthew Sakai {
961827c6389SMatthew Sakai 	if ((header->check_byte != sector->check_byte) ||
962827c6389SMatthew Sakai 	    (header->recovery_count != sector->recovery_count))
963827c6389SMatthew Sakai 		return false;
964827c6389SMatthew Sakai 
965827c6389SMatthew Sakai 	if (header->metadata_type == VDO_METADATA_RECOVERY_JOURNAL_2)
966827c6389SMatthew Sakai 		return sector->entry_count <= RECOVERY_JOURNAL_ENTRIES_PER_SECTOR;
967827c6389SMatthew Sakai 
968827c6389SMatthew Sakai 	if (sector_number == 7)
969827c6389SMatthew Sakai 		return sector->entry_count <= RECOVERY_JOURNAL_1_ENTRIES_IN_LAST_SECTOR;
970827c6389SMatthew Sakai 
971827c6389SMatthew Sakai 	return sector->entry_count <= RECOVERY_JOURNAL_1_ENTRIES_PER_SECTOR;
972827c6389SMatthew Sakai }
973827c6389SMatthew Sakai 
974827c6389SMatthew Sakai /**
975827c6389SMatthew Sakai  * vdo_compute_recovery_journal_block_number() - Compute the physical block number of the recovery
976827c6389SMatthew Sakai  *                                               journal block which would have a given sequence
977827c6389SMatthew Sakai  *                                               number.
978827c6389SMatthew Sakai  * @journal_size: The size of the journal.
979827c6389SMatthew Sakai  * @sequence_number: The sequence number.
980827c6389SMatthew Sakai  *
981827c6389SMatthew Sakai  * Return: The pbn of the journal block which would the specified sequence number.
982827c6389SMatthew Sakai  */
983827c6389SMatthew Sakai static inline physical_block_number_t __must_check
vdo_compute_recovery_journal_block_number(block_count_t journal_size,sequence_number_t sequence_number)984827c6389SMatthew Sakai vdo_compute_recovery_journal_block_number(block_count_t journal_size,
985827c6389SMatthew Sakai 					  sequence_number_t sequence_number)
986827c6389SMatthew Sakai {
987827c6389SMatthew Sakai 	/*
988827c6389SMatthew Sakai 	 * Since journal size is a power of two, the block number modulus can just be extracted
989827c6389SMatthew Sakai 	 * from the low-order bits of the sequence.
990827c6389SMatthew Sakai 	 */
991827c6389SMatthew Sakai 	return (sequence_number & (journal_size - 1));
992827c6389SMatthew Sakai }
993827c6389SMatthew Sakai 
994827c6389SMatthew Sakai /**
995827c6389SMatthew Sakai  * vdo_get_journal_block_sector() - Find the recovery journal sector from the block header and
996827c6389SMatthew Sakai  *                                  sector number.
997827c6389SMatthew Sakai  * @header: The header of the recovery journal block.
998827c6389SMatthew Sakai  * @sector_number: The index of the sector (1-based).
999827c6389SMatthew Sakai  *
1000827c6389SMatthew Sakai  * Return: A packed recovery journal sector.
1001827c6389SMatthew Sakai  */
1002827c6389SMatthew Sakai static inline struct packed_journal_sector * __must_check
vdo_get_journal_block_sector(struct packed_journal_header * header,int sector_number)1003827c6389SMatthew Sakai vdo_get_journal_block_sector(struct packed_journal_header *header, int sector_number)
1004827c6389SMatthew Sakai {
1005827c6389SMatthew Sakai 	char *sector_data = ((char *) header) + (VDO_SECTOR_SIZE * sector_number);
1006827c6389SMatthew Sakai 
1007827c6389SMatthew Sakai 	return (struct packed_journal_sector *) sector_data;
1008827c6389SMatthew Sakai }
1009827c6389SMatthew Sakai 
1010827c6389SMatthew Sakai /**
1011827c6389SMatthew Sakai  * vdo_pack_recovery_block_header() - Generate the packed representation of a recovery block
1012827c6389SMatthew Sakai  *                                    header.
1013827c6389SMatthew Sakai  * @header: The header containing the values to encode.
1014827c6389SMatthew Sakai  * @packed: The header into which to pack the values.
1015827c6389SMatthew Sakai  */
vdo_pack_recovery_block_header(const struct recovery_block_header * header,struct packed_journal_header * packed)1016827c6389SMatthew Sakai static inline void vdo_pack_recovery_block_header(const struct recovery_block_header *header,
1017827c6389SMatthew Sakai 						  struct packed_journal_header *packed)
1018827c6389SMatthew Sakai {
1019827c6389SMatthew Sakai 	*packed = (struct packed_journal_header) {
1020827c6389SMatthew Sakai 		.block_map_head = __cpu_to_le64(header->block_map_head),
1021827c6389SMatthew Sakai 		.slab_journal_head = __cpu_to_le64(header->slab_journal_head),
1022827c6389SMatthew Sakai 		.sequence_number = __cpu_to_le64(header->sequence_number),
1023827c6389SMatthew Sakai 		.nonce = __cpu_to_le64(header->nonce),
1024827c6389SMatthew Sakai 		.logical_blocks_used = __cpu_to_le64(header->logical_blocks_used),
1025827c6389SMatthew Sakai 		.block_map_data_blocks = __cpu_to_le64(header->block_map_data_blocks),
1026827c6389SMatthew Sakai 		.entry_count = __cpu_to_le16(header->entry_count),
1027827c6389SMatthew Sakai 		.check_byte = header->check_byte,
1028827c6389SMatthew Sakai 		.recovery_count = header->recovery_count,
1029827c6389SMatthew Sakai 		.metadata_type = header->metadata_type,
1030827c6389SMatthew Sakai 	};
1031827c6389SMatthew Sakai }
1032827c6389SMatthew Sakai 
1033827c6389SMatthew Sakai /**
1034827c6389SMatthew Sakai  * vdo_unpack_recovery_block_header() - Decode the packed representation of a recovery block
1035827c6389SMatthew Sakai  *                                      header.
1036827c6389SMatthew Sakai  * @packed: The packed header to decode.
1037827c6389SMatthew Sakai  *
1038827c6389SMatthew Sakai  * Return: The unpacked header.
1039827c6389SMatthew Sakai  */
1040827c6389SMatthew Sakai static inline struct recovery_block_header
vdo_unpack_recovery_block_header(const struct packed_journal_header * packed)1041827c6389SMatthew Sakai vdo_unpack_recovery_block_header(const struct packed_journal_header *packed)
1042827c6389SMatthew Sakai {
1043827c6389SMatthew Sakai 	return (struct recovery_block_header) {
1044827c6389SMatthew Sakai 		.block_map_head = __le64_to_cpu(packed->block_map_head),
1045827c6389SMatthew Sakai 		.slab_journal_head = __le64_to_cpu(packed->slab_journal_head),
1046827c6389SMatthew Sakai 		.sequence_number = __le64_to_cpu(packed->sequence_number),
1047827c6389SMatthew Sakai 		.nonce = __le64_to_cpu(packed->nonce),
1048827c6389SMatthew Sakai 		.logical_blocks_used = __le64_to_cpu(packed->logical_blocks_used),
1049827c6389SMatthew Sakai 		.block_map_data_blocks = __le64_to_cpu(packed->block_map_data_blocks),
1050827c6389SMatthew Sakai 		.entry_count = __le16_to_cpu(packed->entry_count),
1051827c6389SMatthew Sakai 		.check_byte = packed->check_byte,
1052827c6389SMatthew Sakai 		.recovery_count = packed->recovery_count,
1053827c6389SMatthew Sakai 		.metadata_type = packed->metadata_type,
1054827c6389SMatthew Sakai 	};
1055827c6389SMatthew Sakai }
1056827c6389SMatthew Sakai 
1057827c6389SMatthew Sakai /**
1058827c6389SMatthew Sakai  * vdo_compute_slab_count() - Compute the number of slabs a depot with given parameters would have.
1059827c6389SMatthew Sakai  * @first_block: PBN of the first data block.
1060827c6389SMatthew Sakai  * @last_block: PBN of the last data block.
1061827c6389SMatthew Sakai  * @slab_size_shift: Exponent for the number of blocks per slab.
1062827c6389SMatthew Sakai  *
1063827c6389SMatthew Sakai  * Return: The number of slabs.
1064827c6389SMatthew Sakai  */
vdo_compute_slab_count(physical_block_number_t first_block,physical_block_number_t last_block,unsigned int slab_size_shift)1065827c6389SMatthew Sakai static inline slab_count_t vdo_compute_slab_count(physical_block_number_t first_block,
1066827c6389SMatthew Sakai 						  physical_block_number_t last_block,
1067827c6389SMatthew Sakai 						  unsigned int slab_size_shift)
1068827c6389SMatthew Sakai {
1069827c6389SMatthew Sakai 	return (slab_count_t) ((last_block - first_block) >> slab_size_shift);
1070827c6389SMatthew Sakai }
1071827c6389SMatthew Sakai 
1072827c6389SMatthew Sakai int __must_check vdo_configure_slab_depot(const struct partition *partition,
1073827c6389SMatthew Sakai 					  struct slab_config slab_config,
1074827c6389SMatthew Sakai 					  zone_count_t zone_count,
1075827c6389SMatthew Sakai 					  struct slab_depot_state_2_0 *state);
1076827c6389SMatthew Sakai 
1077827c6389SMatthew Sakai int __must_check vdo_configure_slab(block_count_t slab_size,
1078827c6389SMatthew Sakai 				    block_count_t slab_journal_blocks,
1079827c6389SMatthew Sakai 				    struct slab_config *slab_config);
1080827c6389SMatthew Sakai 
1081827c6389SMatthew Sakai /**
1082827c6389SMatthew Sakai  * vdo_get_saved_reference_count_size() - Get the number of blocks required to save a reference
1083827c6389SMatthew Sakai  *                                        counts state covering the specified number of data
1084827c6389SMatthew Sakai  *                                        blocks.
1085827c6389SMatthew Sakai  * @block_count: The number of physical data blocks that can be referenced.
1086827c6389SMatthew Sakai  *
1087827c6389SMatthew Sakai  * Return: The number of blocks required to save reference counts with the given block count.
1088827c6389SMatthew Sakai  */
vdo_get_saved_reference_count_size(block_count_t block_count)1089827c6389SMatthew Sakai static inline block_count_t vdo_get_saved_reference_count_size(block_count_t block_count)
1090827c6389SMatthew Sakai {
1091827c6389SMatthew Sakai 	return DIV_ROUND_UP(block_count, COUNTS_PER_BLOCK);
1092827c6389SMatthew Sakai }
1093827c6389SMatthew Sakai 
1094827c6389SMatthew Sakai /**
1095827c6389SMatthew Sakai  * vdo_get_slab_journal_start_block() - Get the physical block number of the start of the slab
1096827c6389SMatthew Sakai  *                                      journal relative to the start block allocator partition.
1097827c6389SMatthew Sakai  * @slab_config: The slab configuration of the VDO.
1098827c6389SMatthew Sakai  * @origin: The first block of the slab.
1099827c6389SMatthew Sakai  */
1100827c6389SMatthew Sakai static inline physical_block_number_t __must_check
vdo_get_slab_journal_start_block(const struct slab_config * slab_config,physical_block_number_t origin)1101827c6389SMatthew Sakai vdo_get_slab_journal_start_block(const struct slab_config *slab_config,
1102827c6389SMatthew Sakai 				 physical_block_number_t origin)
1103827c6389SMatthew Sakai {
1104827c6389SMatthew Sakai 	return origin + slab_config->data_blocks + slab_config->reference_count_blocks;
1105827c6389SMatthew Sakai }
1106827c6389SMatthew Sakai 
1107827c6389SMatthew Sakai /**
1108827c6389SMatthew Sakai  * vdo_advance_journal_point() - Move the given journal point forward by one entry.
1109827c6389SMatthew Sakai  * @point: The journal point to adjust.
1110827c6389SMatthew Sakai  * @entries_per_block: The number of entries in one full block.
1111827c6389SMatthew Sakai  */
vdo_advance_journal_point(struct journal_point * point,journal_entry_count_t entries_per_block)1112827c6389SMatthew Sakai static inline void vdo_advance_journal_point(struct journal_point *point,
1113827c6389SMatthew Sakai 					     journal_entry_count_t entries_per_block)
1114827c6389SMatthew Sakai {
1115827c6389SMatthew Sakai 	point->entry_count++;
1116827c6389SMatthew Sakai 	if (point->entry_count == entries_per_block) {
1117827c6389SMatthew Sakai 		point->sequence_number++;
1118827c6389SMatthew Sakai 		point->entry_count = 0;
1119827c6389SMatthew Sakai 	}
1120827c6389SMatthew Sakai }
1121827c6389SMatthew Sakai 
1122827c6389SMatthew Sakai /**
1123827c6389SMatthew Sakai  * vdo_before_journal_point() - Check whether the first point precedes the second point.
1124827c6389SMatthew Sakai  * @first: The first journal point.
1125827c6389SMatthew Sakai  * @second: The second journal point.
1126827c6389SMatthew Sakai  *
1127827c6389SMatthew Sakai  * Return: true if the first point precedes the second point.
1128827c6389SMatthew Sakai  */
vdo_before_journal_point(const struct journal_point * first,const struct journal_point * second)1129827c6389SMatthew Sakai static inline bool vdo_before_journal_point(const struct journal_point *first,
1130827c6389SMatthew Sakai 					    const struct journal_point *second)
1131827c6389SMatthew Sakai {
1132827c6389SMatthew Sakai 	return ((first->sequence_number < second->sequence_number) ||
1133827c6389SMatthew Sakai 		((first->sequence_number == second->sequence_number) &&
1134827c6389SMatthew Sakai 		 (first->entry_count < second->entry_count)));
1135827c6389SMatthew Sakai }
1136827c6389SMatthew Sakai 
1137827c6389SMatthew Sakai /**
1138827c6389SMatthew Sakai  * vdo_pack_journal_point() - Encode the journal location represented by a
1139827c6389SMatthew Sakai  *                            journal_point into a packed_journal_point.
1140827c6389SMatthew Sakai  * @unpacked: The unpacked input point.
1141827c6389SMatthew Sakai  * @packed: The packed output point.
1142827c6389SMatthew Sakai  */
vdo_pack_journal_point(const struct journal_point * unpacked,struct packed_journal_point * packed)1143827c6389SMatthew Sakai static inline void vdo_pack_journal_point(const struct journal_point *unpacked,
1144827c6389SMatthew Sakai 					  struct packed_journal_point *packed)
1145827c6389SMatthew Sakai {
1146827c6389SMatthew Sakai 	packed->encoded_point =
1147827c6389SMatthew Sakai 		__cpu_to_le64((unpacked->sequence_number << 16) | unpacked->entry_count);
1148827c6389SMatthew Sakai }
1149827c6389SMatthew Sakai 
1150827c6389SMatthew Sakai /**
1151827c6389SMatthew Sakai  * vdo_unpack_journal_point() - Decode the journal location represented by a packed_journal_point
1152827c6389SMatthew Sakai  *                              into a journal_point.
1153827c6389SMatthew Sakai  * @packed: The packed input point.
1154827c6389SMatthew Sakai  * @unpacked: The unpacked output point.
1155827c6389SMatthew Sakai  */
vdo_unpack_journal_point(const struct packed_journal_point * packed,struct journal_point * unpacked)1156827c6389SMatthew Sakai static inline void vdo_unpack_journal_point(const struct packed_journal_point *packed,
1157827c6389SMatthew Sakai 					    struct journal_point *unpacked)
1158827c6389SMatthew Sakai {
1159827c6389SMatthew Sakai 	u64 native = __le64_to_cpu(packed->encoded_point);
1160827c6389SMatthew Sakai 
1161827c6389SMatthew Sakai 	unpacked->sequence_number = (native >> 16);
1162827c6389SMatthew Sakai 	unpacked->entry_count = (native & 0xffff);
1163827c6389SMatthew Sakai }
1164827c6389SMatthew Sakai 
1165827c6389SMatthew Sakai /**
1166827c6389SMatthew Sakai  * vdo_pack_slab_journal_block_header() - Generate the packed representation of a slab block
1167827c6389SMatthew Sakai  *                                        header.
1168827c6389SMatthew Sakai  * @header: The header containing the values to encode.
1169827c6389SMatthew Sakai  * @packed: The header into which to pack the values.
1170827c6389SMatthew Sakai  */
1171827c6389SMatthew Sakai static inline void
vdo_pack_slab_journal_block_header(const struct slab_journal_block_header * header,struct packed_slab_journal_block_header * packed)1172827c6389SMatthew Sakai vdo_pack_slab_journal_block_header(const struct slab_journal_block_header *header,
1173827c6389SMatthew Sakai 				   struct packed_slab_journal_block_header *packed)
1174827c6389SMatthew Sakai {
1175827c6389SMatthew Sakai 	packed->head = __cpu_to_le64(header->head);
1176827c6389SMatthew Sakai 	packed->sequence_number = __cpu_to_le64(header->sequence_number);
1177827c6389SMatthew Sakai 	packed->nonce = __cpu_to_le64(header->nonce);
1178827c6389SMatthew Sakai 	packed->entry_count = __cpu_to_le16(header->entry_count);
1179827c6389SMatthew Sakai 	packed->metadata_type = header->metadata_type;
1180827c6389SMatthew Sakai 	packed->has_block_map_increments = header->has_block_map_increments;
1181827c6389SMatthew Sakai 
1182827c6389SMatthew Sakai 	vdo_pack_journal_point(&header->recovery_point, &packed->recovery_point);
1183827c6389SMatthew Sakai }
1184827c6389SMatthew Sakai 
1185827c6389SMatthew Sakai /**
1186827c6389SMatthew Sakai  * vdo_unpack_slab_journal_block_header() - Decode the packed representation of a slab block
1187827c6389SMatthew Sakai  *                                          header.
1188827c6389SMatthew Sakai  * @packed: The packed header to decode.
1189827c6389SMatthew Sakai  * @header: The header into which to unpack the values.
1190827c6389SMatthew Sakai  */
1191827c6389SMatthew Sakai static inline void
vdo_unpack_slab_journal_block_header(const struct packed_slab_journal_block_header * packed,struct slab_journal_block_header * header)1192827c6389SMatthew Sakai vdo_unpack_slab_journal_block_header(const struct packed_slab_journal_block_header *packed,
1193827c6389SMatthew Sakai 				     struct slab_journal_block_header *header)
1194827c6389SMatthew Sakai {
1195827c6389SMatthew Sakai 	*header = (struct slab_journal_block_header) {
1196827c6389SMatthew Sakai 		.head = __le64_to_cpu(packed->head),
1197827c6389SMatthew Sakai 		.sequence_number = __le64_to_cpu(packed->sequence_number),
1198827c6389SMatthew Sakai 		.nonce = __le64_to_cpu(packed->nonce),
1199827c6389SMatthew Sakai 		.entry_count = __le16_to_cpu(packed->entry_count),
1200827c6389SMatthew Sakai 		.metadata_type = packed->metadata_type,
1201827c6389SMatthew Sakai 		.has_block_map_increments = packed->has_block_map_increments,
1202827c6389SMatthew Sakai 	};
1203827c6389SMatthew Sakai 	vdo_unpack_journal_point(&packed->recovery_point, &header->recovery_point);
1204827c6389SMatthew Sakai }
1205827c6389SMatthew Sakai 
1206827c6389SMatthew Sakai /**
1207827c6389SMatthew Sakai  * vdo_pack_slab_journal_entry() - Generate the packed encoding of a slab journal entry.
1208827c6389SMatthew Sakai  * @packed: The entry into which to pack the values.
1209827c6389SMatthew Sakai  * @sbn: The slab block number of the entry to encode.
1210827c6389SMatthew Sakai  * @is_increment: The increment flag.
1211827c6389SMatthew Sakai  */
vdo_pack_slab_journal_entry(packed_slab_journal_entry * packed,slab_block_number sbn,bool is_increment)1212827c6389SMatthew Sakai static inline void vdo_pack_slab_journal_entry(packed_slab_journal_entry *packed,
1213827c6389SMatthew Sakai 					       slab_block_number sbn, bool is_increment)
1214827c6389SMatthew Sakai {
1215827c6389SMatthew Sakai 	packed->offset_low8 = (sbn & 0x0000FF);
1216827c6389SMatthew Sakai 	packed->offset_mid8 = (sbn & 0x00FF00) >> 8;
1217827c6389SMatthew Sakai 	packed->offset_high7 = (sbn & 0x7F0000) >> 16;
1218827c6389SMatthew Sakai 	packed->increment = is_increment ? 1 : 0;
1219827c6389SMatthew Sakai }
1220827c6389SMatthew Sakai 
1221827c6389SMatthew Sakai /**
1222827c6389SMatthew Sakai  * vdo_unpack_slab_journal_entry() - Decode the packed representation of a slab journal entry.
1223827c6389SMatthew Sakai  * @packed: The packed entry to decode.
1224827c6389SMatthew Sakai  *
1225827c6389SMatthew Sakai  * Return: The decoded slab journal entry.
1226827c6389SMatthew Sakai  */
1227827c6389SMatthew Sakai static inline struct slab_journal_entry __must_check
vdo_unpack_slab_journal_entry(const packed_slab_journal_entry * packed)1228827c6389SMatthew Sakai vdo_unpack_slab_journal_entry(const packed_slab_journal_entry *packed)
1229827c6389SMatthew Sakai {
1230827c6389SMatthew Sakai 	struct slab_journal_entry entry;
1231827c6389SMatthew Sakai 
1232827c6389SMatthew Sakai 	entry.sbn = packed->offset_high7;
1233827c6389SMatthew Sakai 	entry.sbn <<= 8;
1234827c6389SMatthew Sakai 	entry.sbn |= packed->offset_mid8;
1235827c6389SMatthew Sakai 	entry.sbn <<= 8;
1236827c6389SMatthew Sakai 	entry.sbn |= packed->offset_low8;
1237827c6389SMatthew Sakai 	entry.operation = VDO_JOURNAL_DATA_REMAPPING;
1238827c6389SMatthew Sakai 	entry.increment = packed->increment;
1239827c6389SMatthew Sakai 	return entry;
1240827c6389SMatthew Sakai }
1241827c6389SMatthew Sakai 
1242827c6389SMatthew Sakai struct slab_journal_entry __must_check
1243827c6389SMatthew Sakai vdo_decode_slab_journal_entry(struct packed_slab_journal_block *block,
1244827c6389SMatthew Sakai 			      journal_entry_count_t entry_count);
1245827c6389SMatthew Sakai 
1246827c6389SMatthew Sakai /**
1247827c6389SMatthew Sakai  * vdo_get_slab_summary_hint_shift() - Compute the shift for slab summary hints.
1248827c6389SMatthew Sakai  * @slab_size_shift: Exponent for the number of blocks per slab.
1249827c6389SMatthew Sakai  *
1250827c6389SMatthew Sakai  * Return: The hint shift.
1251827c6389SMatthew Sakai  */
vdo_get_slab_summary_hint_shift(unsigned int slab_size_shift)1252827c6389SMatthew Sakai static inline u8 __must_check vdo_get_slab_summary_hint_shift(unsigned int slab_size_shift)
1253827c6389SMatthew Sakai {
1254827c6389SMatthew Sakai 	return ((slab_size_shift > VDO_SLAB_SUMMARY_FULLNESS_HINT_BITS) ?
1255827c6389SMatthew Sakai 		(slab_size_shift - VDO_SLAB_SUMMARY_FULLNESS_HINT_BITS) :
1256827c6389SMatthew Sakai 		0);
1257827c6389SMatthew Sakai }
1258827c6389SMatthew Sakai 
1259827c6389SMatthew Sakai int __must_check vdo_initialize_layout(block_count_t size,
1260827c6389SMatthew Sakai 				       physical_block_number_t offset,
1261827c6389SMatthew Sakai 				       block_count_t block_map_blocks,
1262827c6389SMatthew Sakai 				       block_count_t journal_blocks,
1263827c6389SMatthew Sakai 				       block_count_t summary_blocks,
1264827c6389SMatthew Sakai 				       struct layout *layout);
1265827c6389SMatthew Sakai 
1266827c6389SMatthew Sakai void vdo_uninitialize_layout(struct layout *layout);
1267827c6389SMatthew Sakai 
1268827c6389SMatthew Sakai int __must_check vdo_get_partition(struct layout *layout, enum partition_id id,
1269827c6389SMatthew Sakai 				   struct partition **partition_ptr);
1270827c6389SMatthew Sakai 
1271827c6389SMatthew Sakai struct partition * __must_check vdo_get_known_partition(struct layout *layout,
1272827c6389SMatthew Sakai 							enum partition_id id);
1273827c6389SMatthew Sakai 
1274827c6389SMatthew Sakai int vdo_validate_config(const struct vdo_config *config,
1275827c6389SMatthew Sakai 			block_count_t physical_block_count,
1276827c6389SMatthew Sakai 			block_count_t logical_block_count);
1277827c6389SMatthew Sakai 
1278827c6389SMatthew Sakai void vdo_destroy_component_states(struct vdo_component_states *states);
1279827c6389SMatthew Sakai 
1280827c6389SMatthew Sakai int __must_check vdo_decode_component_states(u8 *buffer,
1281827c6389SMatthew Sakai 					     struct volume_geometry *geometry,
1282827c6389SMatthew Sakai 					     struct vdo_component_states *states);
1283827c6389SMatthew Sakai 
1284827c6389SMatthew Sakai int __must_check vdo_validate_component_states(struct vdo_component_states *states,
1285827c6389SMatthew Sakai 					       nonce_t geometry_nonce,
1286827c6389SMatthew Sakai 					       block_count_t physical_size,
1287827c6389SMatthew Sakai 					       block_count_t logical_size);
1288827c6389SMatthew Sakai 
1289827c6389SMatthew Sakai void vdo_encode_super_block(u8 *buffer, struct vdo_component_states *states);
1290827c6389SMatthew Sakai int __must_check vdo_decode_super_block(u8 *buffer);
1291827c6389SMatthew Sakai 
1292827c6389SMatthew Sakai /* We start with 0L and postcondition with ~0L to match our historical usage in userspace. */
vdo_crc32(const void * buf,unsigned long len)1293827c6389SMatthew Sakai static inline u32 vdo_crc32(const void *buf, unsigned long len)
1294827c6389SMatthew Sakai {
1295827c6389SMatthew Sakai 	return (crc32(0L, buf, len) ^ ~0L);
1296827c6389SMatthew Sakai }
1297827c6389SMatthew Sakai 
1298827c6389SMatthew Sakai #endif /* VDO_ENCODINGS_H */
1299