brintos

brintos / linux-shallow public Read only

0
0
Text · 46.3 KiB · a34ea02 Raw
1484 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2023 Red Hat4 */5 6#include "encodings.h"7 8#include <linux/log2.h>9 10#include "logger.h"11#include "memory-alloc.h"12#include "permassert.h"13 14#include "constants.h"15#include "status-codes.h"16#include "types.h"17 18/** The maximum logical space is 4 petabytes, which is 1 terablock. */19static const block_count_t MAXIMUM_VDO_LOGICAL_BLOCKS = 1024ULL * 1024 * 1024 * 1024;20 21/** The maximum physical space is 256 terabytes, which is 64 gigablocks. */22static const block_count_t MAXIMUM_VDO_PHYSICAL_BLOCKS = 1024ULL * 1024 * 1024 * 64;23 24struct geometry_block {25	char magic_number[VDO_GEOMETRY_MAGIC_NUMBER_SIZE];26	struct packed_header header;27	u32 checksum;28} __packed;29 30static const struct header GEOMETRY_BLOCK_HEADER_5_0 = {31	.id = VDO_GEOMETRY_BLOCK,32	.version = {33		.major_version = 5,34		.minor_version = 0,35	},36	/*37	 * Note: this size isn't just the payload size following the header, like it is everywhere38	 * else in VDO.39	 */40	.size = sizeof(struct geometry_block) + sizeof(struct volume_geometry),41};42 43static const struct header GEOMETRY_BLOCK_HEADER_4_0 = {44	.id = VDO_GEOMETRY_BLOCK,45	.version = {46		.major_version = 4,47		.minor_version = 0,48	},49	/*50	 * Note: this size isn't just the payload size following the header, like it is everywhere51	 * else in VDO.52	 */53	.size = sizeof(struct geometry_block) + sizeof(struct volume_geometry_4_0),54};55 56const u8 VDO_GEOMETRY_MAGIC_NUMBER[VDO_GEOMETRY_MAGIC_NUMBER_SIZE + 1] = "dmvdo001";57 58#define PAGE_HEADER_4_1_SIZE (8 + 8 + 8 + 1 + 1 + 1 + 1)59 60static const struct version_number BLOCK_MAP_4_1 = {61	.major_version = 4,62	.minor_version = 1,63};64 65const struct header VDO_BLOCK_MAP_HEADER_2_0 = {66	.id = VDO_BLOCK_MAP,67	.version = {68		.major_version = 2,69		.minor_version = 0,70	},71	.size = sizeof(struct block_map_state_2_0),72};73 74const struct header VDO_RECOVERY_JOURNAL_HEADER_7_0 = {75	.id = VDO_RECOVERY_JOURNAL,76	.version = {77			.major_version = 7,78			.minor_version = 0,79		},80	.size = sizeof(struct recovery_journal_state_7_0),81};82 83const struct header VDO_SLAB_DEPOT_HEADER_2_0 = {84	.id = VDO_SLAB_DEPOT,85	.version = {86		.major_version = 2,87		.minor_version = 0,88	},89	.size = sizeof(struct slab_depot_state_2_0),90};91 92static const struct header VDO_LAYOUT_HEADER_3_0 = {93	.id = VDO_LAYOUT,94	.version = {95		.major_version = 3,96		.minor_version = 0,97	},98	.size = sizeof(struct layout_3_0) + (sizeof(struct partition_3_0) * VDO_PARTITION_COUNT),99};100 101static const enum partition_id REQUIRED_PARTITIONS[] = {102	VDO_BLOCK_MAP_PARTITION,103	VDO_SLAB_DEPOT_PARTITION,104	VDO_RECOVERY_JOURNAL_PARTITION,105	VDO_SLAB_SUMMARY_PARTITION,106};107 108/*109 * The current version for the data encoded in the super block. This must be changed any time there110 * is a change to encoding of the component data of any VDO component.111 */112static const struct version_number VDO_COMPONENT_DATA_41_0 = {113	.major_version = 41,114	.minor_version = 0,115};116 117const struct version_number VDO_VOLUME_VERSION_67_0 = {118	.major_version = 67,119	.minor_version = 0,120};121 122static const struct header SUPER_BLOCK_HEADER_12_0 = {123	.id = VDO_SUPER_BLOCK,124	.version = {125			.major_version = 12,126			.minor_version = 0,127		},128 129	/* This is the minimum size, if the super block contains no components. */130	.size = VDO_SUPER_BLOCK_FIXED_SIZE - VDO_ENCODED_HEADER_SIZE,131};132 133/**134 * validate_version() - Check whether a version matches an expected version.135 * @expected_version: The expected version.136 * @actual_version: The version being validated.137 * @component_name: The name of the component or the calling function (for error logging).138 *139 * Logs an error describing a mismatch.140 *141 * Return: VDO_SUCCESS             if the versions are the same,142 *         VDO_UNSUPPORTED_VERSION if the versions don't match.143 */144static int __must_check validate_version(struct version_number expected_version,145					 struct version_number actual_version,146					 const char *component_name)147{148	if (!vdo_are_same_version(expected_version, actual_version)) {149		return vdo_log_error_strerror(VDO_UNSUPPORTED_VERSION,150					      "%s version mismatch, expected %d.%d, got %d.%d",151					      component_name,152					      expected_version.major_version,153					      expected_version.minor_version,154					      actual_version.major_version,155					      actual_version.minor_version);156	}157 158	return VDO_SUCCESS;159}160 161/**162 * vdo_validate_header() - Check whether a header matches expectations.163 * @expected_header: The expected header.164 * @actual_header: The header being validated.165 * @exact_size: If true, the size fields of the two headers must be the same, otherwise it is166 *              required that actual_header.size >= expected_header.size.167 * @name: The name of the component or the calling function (for error logging).168 *169 * Logs an error describing the first mismatch found.170 *171 * Return: VDO_SUCCESS             if the header meets expectations,172 *         VDO_INCORRECT_COMPONENT if the component ids don't match,173 *         VDO_UNSUPPORTED_VERSION if the versions or sizes don't match.174 */175int vdo_validate_header(const struct header *expected_header,176			const struct header *actual_header, bool exact_size,177			const char *name)178{179	int result;180 181	if (expected_header->id != actual_header->id) {182		return vdo_log_error_strerror(VDO_INCORRECT_COMPONENT,183					      "%s ID mismatch, expected %d, got %d",184					      name, expected_header->id,185					      actual_header->id);186	}187 188	result = validate_version(expected_header->version, actual_header->version,189				  name);190	if (result != VDO_SUCCESS)191		return result;192 193	if ((expected_header->size > actual_header->size) ||194	    (exact_size && (expected_header->size < actual_header->size))) {195		return vdo_log_error_strerror(VDO_UNSUPPORTED_VERSION,196					      "%s size mismatch, expected %zu, got %zu",197					      name, expected_header->size,198					      actual_header->size);199	}200 201	return VDO_SUCCESS;202}203 204static void encode_version_number(u8 *buffer, size_t *offset,205				  struct version_number version)206{207	struct packed_version_number packed = vdo_pack_version_number(version);208 209	memcpy(buffer + *offset, &packed, sizeof(packed));210	*offset += sizeof(packed);211}212 213void vdo_encode_header(u8 *buffer, size_t *offset, const struct header *header)214{215	struct packed_header packed = vdo_pack_header(header);216 217	memcpy(buffer + *offset, &packed, sizeof(packed));218	*offset += sizeof(packed);219}220 221static void decode_version_number(u8 *buffer, size_t *offset,222				  struct version_number *version)223{224	struct packed_version_number packed;225 226	memcpy(&packed, buffer + *offset, sizeof(packed));227	*offset += sizeof(packed);228	*version = vdo_unpack_version_number(packed);229}230 231void vdo_decode_header(u8 *buffer, size_t *offset, struct header *header)232{233	struct packed_header packed;234 235	memcpy(&packed, buffer + *offset, sizeof(packed));236	*offset += sizeof(packed);237 238	*header = vdo_unpack_header(&packed);239}240 241/**242 * decode_volume_geometry() - Decode the on-disk representation of a volume geometry from a buffer.243 * @buffer: A buffer to decode from.244 * @offset: The offset in the buffer at which to decode.245 * @geometry: The structure to receive the decoded fields.246 * @version: The geometry block version to decode.247 */248static void decode_volume_geometry(u8 *buffer, size_t *offset,249				   struct volume_geometry *geometry, u32 version)250{251	u32 unused, mem;252	enum volume_region_id id;253	nonce_t nonce;254	block_count_t bio_offset = 0;255	bool sparse;256 257	/* This is for backwards compatibility. */258	decode_u32_le(buffer, offset, &unused);259	geometry->unused = unused;260 261	decode_u64_le(buffer, offset, &nonce);262	geometry->nonce = nonce;263 264	memcpy((unsigned char *) &geometry->uuid, buffer + *offset, sizeof(uuid_t));265	*offset += sizeof(uuid_t);266 267	if (version > 4)268		decode_u64_le(buffer, offset, &bio_offset);269	geometry->bio_offset = bio_offset;270 271	for (id = 0; id < VDO_VOLUME_REGION_COUNT; id++) {272		physical_block_number_t start_block;273		enum volume_region_id saved_id;274 275		decode_u32_le(buffer, offset, &saved_id);276		decode_u64_le(buffer, offset, &start_block);277 278		geometry->regions[id] = (struct volume_region) {279			.id = saved_id,280			.start_block = start_block,281		};282	}283 284	decode_u32_le(buffer, offset, &mem);285	*offset += sizeof(u32);286	sparse = buffer[(*offset)++];287 288	geometry->index_config = (struct index_config) {289		.mem = mem,290		.sparse = sparse,291	};292}293 294/**295 * vdo_parse_geometry_block() - Decode and validate an encoded geometry block.296 * @block: The encoded geometry block.297 * @geometry: The structure to receive the decoded fields.298 */299int __must_check vdo_parse_geometry_block(u8 *block, struct volume_geometry *geometry)300{301	u32 checksum, saved_checksum;302	struct header header;303	size_t offset = 0;304	int result;305 306	if (memcmp(block, VDO_GEOMETRY_MAGIC_NUMBER, VDO_GEOMETRY_MAGIC_NUMBER_SIZE) != 0)307		return VDO_BAD_MAGIC;308	offset += VDO_GEOMETRY_MAGIC_NUMBER_SIZE;309 310	vdo_decode_header(block, &offset, &header);311	if (header.version.major_version <= 4) {312		result = vdo_validate_header(&GEOMETRY_BLOCK_HEADER_4_0, &header,313					     true, __func__);314	} else {315		result = vdo_validate_header(&GEOMETRY_BLOCK_HEADER_5_0, &header,316					     true, __func__);317	}318	if (result != VDO_SUCCESS)319		return result;320 321	decode_volume_geometry(block, &offset, geometry, header.version.major_version);322 323	result = VDO_ASSERT(header.size == offset + sizeof(u32),324			    "should have decoded up to the geometry checksum");325	if (result != VDO_SUCCESS)326		return result;327 328	/* Decode and verify the checksum. */329	checksum = vdo_crc32(block, offset);330	decode_u32_le(block, &offset, &saved_checksum);331 332	return ((checksum == saved_checksum) ? VDO_SUCCESS : VDO_CHECKSUM_MISMATCH);333}334 335struct block_map_page *vdo_format_block_map_page(void *buffer, nonce_t nonce,336						 physical_block_number_t pbn,337						 bool initialized)338{339	struct block_map_page *page = buffer;340 341	memset(buffer, 0, VDO_BLOCK_SIZE);342	page->version = vdo_pack_version_number(BLOCK_MAP_4_1);343	page->header.nonce = __cpu_to_le64(nonce);344	page->header.pbn = __cpu_to_le64(pbn);345	page->header.initialized = initialized;346	return page;347}348 349enum block_map_page_validity vdo_validate_block_map_page(struct block_map_page *page,350							 nonce_t nonce,351							 physical_block_number_t pbn)352{353	BUILD_BUG_ON(sizeof(struct block_map_page_header) != PAGE_HEADER_4_1_SIZE);354 355	if (!vdo_are_same_version(BLOCK_MAP_4_1,356				  vdo_unpack_version_number(page->version)) ||357	    !page->header.initialized || (nonce != __le64_to_cpu(page->header.nonce)))358		return VDO_BLOCK_MAP_PAGE_INVALID;359 360	if (pbn != vdo_get_block_map_page_pbn(page))361		return VDO_BLOCK_MAP_PAGE_BAD;362 363	return VDO_BLOCK_MAP_PAGE_VALID;364}365 366static int decode_block_map_state_2_0(u8 *buffer, size_t *offset,367				      struct block_map_state_2_0 *state)368{369	size_t initial_offset;370	block_count_t flat_page_count, root_count;371	physical_block_number_t flat_page_origin, root_origin;372	struct header header;373	int result;374 375	vdo_decode_header(buffer, offset, &header);376	result = vdo_validate_header(&VDO_BLOCK_MAP_HEADER_2_0, &header, true, __func__);377	if (result != VDO_SUCCESS)378		return result;379 380	initial_offset = *offset;381 382	decode_u64_le(buffer, offset, &flat_page_origin);383	result = VDO_ASSERT(flat_page_origin == VDO_BLOCK_MAP_FLAT_PAGE_ORIGIN,384			    "Flat page origin must be %u (recorded as %llu)",385			    VDO_BLOCK_MAP_FLAT_PAGE_ORIGIN,386			    (unsigned long long) state->flat_page_origin);387	if (result != VDO_SUCCESS)388		return result;389 390	decode_u64_le(buffer, offset, &flat_page_count);391	result = VDO_ASSERT(flat_page_count == 0,392			    "Flat page count must be 0 (recorded as %llu)",393			    (unsigned long long) state->flat_page_count);394	if (result != VDO_SUCCESS)395		return result;396 397	decode_u64_le(buffer, offset, &root_origin);398	decode_u64_le(buffer, offset, &root_count);399 400	result = VDO_ASSERT(VDO_BLOCK_MAP_HEADER_2_0.size == *offset - initial_offset,401			    "decoded block map component size must match header size");402	if (result != VDO_SUCCESS)403		return result;404 405	*state = (struct block_map_state_2_0) {406		.flat_page_origin = flat_page_origin,407		.flat_page_count = flat_page_count,408		.root_origin = root_origin,409		.root_count = root_count,410	};411 412	return VDO_SUCCESS;413}414 415static void encode_block_map_state_2_0(u8 *buffer, size_t *offset,416				       struct block_map_state_2_0 state)417{418	size_t initial_offset;419 420	vdo_encode_header(buffer, offset, &VDO_BLOCK_MAP_HEADER_2_0);421 422	initial_offset = *offset;423	encode_u64_le(buffer, offset, state.flat_page_origin);424	encode_u64_le(buffer, offset, state.flat_page_count);425	encode_u64_le(buffer, offset, state.root_origin);426	encode_u64_le(buffer, offset, state.root_count);427 428	VDO_ASSERT_LOG_ONLY(VDO_BLOCK_MAP_HEADER_2_0.size == *offset - initial_offset,429			    "encoded block map component size must match header size");430}431 432/**433 * vdo_compute_new_forest_pages() - Compute the number of pages which must be allocated at each434 *                                  level in order to grow the forest to a new number of entries.435 * @entries: The new number of entries the block map must address.436 *437 * Return: The total number of non-leaf pages required.438 */439block_count_t vdo_compute_new_forest_pages(root_count_t root_count,440					   struct boundary *old_sizes,441					   block_count_t entries,442					   struct boundary *new_sizes)443{444	page_count_t leaf_pages = max(vdo_compute_block_map_page_count(entries), 1U);445	page_count_t level_size = DIV_ROUND_UP(leaf_pages, root_count);446	block_count_t total_pages = 0;447	height_t height;448 449	for (height = 0; height < VDO_BLOCK_MAP_TREE_HEIGHT; height++) {450		block_count_t new_pages;451 452		level_size = DIV_ROUND_UP(level_size, VDO_BLOCK_MAP_ENTRIES_PER_PAGE);453		new_sizes->levels[height] = level_size;454		new_pages = level_size;455		if (old_sizes != NULL)456			new_pages -= old_sizes->levels[height];457		total_pages += (new_pages * root_count);458	}459 460	return total_pages;461}462 463/**464 * encode_recovery_journal_state_7_0() - Encode the state of a recovery journal.465 *466 * Return: VDO_SUCCESS or an error code.467 */468static void encode_recovery_journal_state_7_0(u8 *buffer, size_t *offset,469					      struct recovery_journal_state_7_0 state)470{471	size_t initial_offset;472 473	vdo_encode_header(buffer, offset, &VDO_RECOVERY_JOURNAL_HEADER_7_0);474 475	initial_offset = *offset;476	encode_u64_le(buffer, offset, state.journal_start);477	encode_u64_le(buffer, offset, state.logical_blocks_used);478	encode_u64_le(buffer, offset, state.block_map_data_blocks);479 480	VDO_ASSERT_LOG_ONLY(VDO_RECOVERY_JOURNAL_HEADER_7_0.size == *offset - initial_offset,481			    "encoded recovery journal component size must match header size");482}483 484/**485 * decode_recovery_journal_state_7_0() - Decode the state of a recovery journal saved in a buffer.486 * @buffer: The buffer containing the saved state.487 * @state: A pointer to a recovery journal state to hold the result of a successful decode.488 *489 * Return: VDO_SUCCESS or an error code.490 */491static int __must_check decode_recovery_journal_state_7_0(u8 *buffer, size_t *offset,492							  struct recovery_journal_state_7_0 *state)493{494	struct header header;495	int result;496	size_t initial_offset;497	sequence_number_t journal_start;498	block_count_t logical_blocks_used, block_map_data_blocks;499 500	vdo_decode_header(buffer, offset, &header);501	result = vdo_validate_header(&VDO_RECOVERY_JOURNAL_HEADER_7_0, &header, true,502				     __func__);503	if (result != VDO_SUCCESS)504		return result;505 506	initial_offset = *offset;507	decode_u64_le(buffer, offset, &journal_start);508	decode_u64_le(buffer, offset, &logical_blocks_used);509	decode_u64_le(buffer, offset, &block_map_data_blocks);510 511	result = VDO_ASSERT(VDO_RECOVERY_JOURNAL_HEADER_7_0.size == *offset - initial_offset,512			    "decoded recovery journal component size must match header size");513	if (result != VDO_SUCCESS)514		return result;515 516	*state = (struct recovery_journal_state_7_0) {517		.journal_start = journal_start,518		.logical_blocks_used = logical_blocks_used,519		.block_map_data_blocks = block_map_data_blocks,520	};521 522	return VDO_SUCCESS;523}524 525/**526 * vdo_get_journal_operation_name() - Get the name of a journal operation.527 * @operation: The operation to name.528 *529 * Return: The name of the operation.530 */531const char *vdo_get_journal_operation_name(enum journal_operation operation)532{533	switch (operation) {534	case VDO_JOURNAL_DATA_REMAPPING:535		return "data remapping";536 537	case VDO_JOURNAL_BLOCK_MAP_REMAPPING:538		return "block map remapping";539 540	default:541		return "unknown journal operation";542	}543}544 545/**546 * encode_slab_depot_state_2_0() - Encode the state of a slab depot into a buffer.547 */548static void encode_slab_depot_state_2_0(u8 *buffer, size_t *offset,549					struct slab_depot_state_2_0 state)550{551	size_t initial_offset;552 553	vdo_encode_header(buffer, offset, &VDO_SLAB_DEPOT_HEADER_2_0);554 555	initial_offset = *offset;556	encode_u64_le(buffer, offset, state.slab_config.slab_blocks);557	encode_u64_le(buffer, offset, state.slab_config.data_blocks);558	encode_u64_le(buffer, offset, state.slab_config.reference_count_blocks);559	encode_u64_le(buffer, offset, state.slab_config.slab_journal_blocks);560	encode_u64_le(buffer, offset, state.slab_config.slab_journal_flushing_threshold);561	encode_u64_le(buffer, offset, state.slab_config.slab_journal_blocking_threshold);562	encode_u64_le(buffer, offset, state.slab_config.slab_journal_scrubbing_threshold);563	encode_u64_le(buffer, offset, state.first_block);564	encode_u64_le(buffer, offset, state.last_block);565	buffer[(*offset)++] = state.zone_count;566 567	VDO_ASSERT_LOG_ONLY(VDO_SLAB_DEPOT_HEADER_2_0.size == *offset - initial_offset,568			    "encoded block map component size must match header size");569}570 571/**572 * decode_slab_depot_state_2_0() - Decode slab depot component state version 2.0 from a buffer.573 *574 * Return: VDO_SUCCESS or an error code.575 */576static int decode_slab_depot_state_2_0(u8 *buffer, size_t *offset,577				       struct slab_depot_state_2_0 *state)578{579	struct header header;580	int result;581	size_t initial_offset;582	struct slab_config slab_config;583	block_count_t count;584	physical_block_number_t first_block, last_block;585	zone_count_t zone_count;586 587	vdo_decode_header(buffer, offset, &header);588	result = vdo_validate_header(&VDO_SLAB_DEPOT_HEADER_2_0, &header, true,589				     __func__);590	if (result != VDO_SUCCESS)591		return result;592 593	initial_offset = *offset;594	decode_u64_le(buffer, offset, &count);595	slab_config.slab_blocks = count;596 597	decode_u64_le(buffer, offset, &count);598	slab_config.data_blocks = count;599 600	decode_u64_le(buffer, offset, &count);601	slab_config.reference_count_blocks = count;602 603	decode_u64_le(buffer, offset, &count);604	slab_config.slab_journal_blocks = count;605 606	decode_u64_le(buffer, offset, &count);607	slab_config.slab_journal_flushing_threshold = count;608 609	decode_u64_le(buffer, offset, &count);610	slab_config.slab_journal_blocking_threshold = count;611 612	decode_u64_le(buffer, offset, &count);613	slab_config.slab_journal_scrubbing_threshold = count;614 615	decode_u64_le(buffer, offset, &first_block);616	decode_u64_le(buffer, offset, &last_block);617	zone_count = buffer[(*offset)++];618 619	result = VDO_ASSERT(VDO_SLAB_DEPOT_HEADER_2_0.size == *offset - initial_offset,620			    "decoded slab depot component size must match header size");621	if (result != VDO_SUCCESS)622		return result;623 624	*state = (struct slab_depot_state_2_0) {625		.slab_config = slab_config,626		.first_block = first_block,627		.last_block = last_block,628		.zone_count = zone_count,629	};630 631	return VDO_SUCCESS;632}633 634/**635 * vdo_configure_slab_depot() - Configure the slab depot.636 * @partition: The slab depot partition637 * @slab_config: The configuration of a single slab.638 * @zone_count: The number of zones the depot will use.639 * @state: The state structure to be configured.640 *641 * Configures the slab_depot for the specified storage capacity, finding the number of data blocks642 * that will fit and still leave room for the depot metadata, then return the saved state for that643 * configuration.644 *645 * Return: VDO_SUCCESS or an error code.646 */647int vdo_configure_slab_depot(const struct partition *partition,648			     struct slab_config slab_config, zone_count_t zone_count,649			     struct slab_depot_state_2_0 *state)650{651	block_count_t total_slab_blocks, total_data_blocks;652	size_t slab_count;653	physical_block_number_t last_block;654	block_count_t slab_size = slab_config.slab_blocks;655 656	vdo_log_debug("slabDepot %s(block_count=%llu, first_block=%llu, slab_size=%llu, zone_count=%u)",657		      __func__, (unsigned long long) partition->count,658		      (unsigned long long) partition->offset,659		      (unsigned long long) slab_size, zone_count);660 661	/* We do not allow runt slabs, so we waste up to a slab's worth. */662	slab_count = (partition->count / slab_size);663	if (slab_count == 0)664		return VDO_NO_SPACE;665 666	if (slab_count > MAX_VDO_SLABS)667		return VDO_TOO_MANY_SLABS;668 669	total_slab_blocks = slab_count * slab_config.slab_blocks;670	total_data_blocks = slab_count * slab_config.data_blocks;671	last_block = partition->offset + total_slab_blocks;672 673	*state = (struct slab_depot_state_2_0) {674		.slab_config = slab_config,675		.first_block = partition->offset,676		.last_block = last_block,677		.zone_count = zone_count,678	};679 680	vdo_log_debug("slab_depot last_block=%llu, total_data_blocks=%llu, slab_count=%zu, left_over=%llu",681		      (unsigned long long) last_block,682		      (unsigned long long) total_data_blocks, slab_count,683		      (unsigned long long) (partition->count - (last_block - partition->offset)));684 685	return VDO_SUCCESS;686}687 688/**689 * vdo_configure_slab() - Measure and initialize the configuration to use for each slab.690 * @slab_size: The number of blocks per slab.691 * @slab_journal_blocks: The number of blocks for the slab journal.692 * @slab_config: The slab configuration to initialize.693 *694 * Return: VDO_SUCCESS or an error code.695 */696int vdo_configure_slab(block_count_t slab_size, block_count_t slab_journal_blocks,697		       struct slab_config *slab_config)698{699	block_count_t ref_blocks, meta_blocks, data_blocks;700	block_count_t flushing_threshold, remaining, blocking_threshold;701	block_count_t minimal_extra_space, scrubbing_threshold;702 703	if (slab_journal_blocks >= slab_size)704		return VDO_BAD_CONFIGURATION;705 706	/*707	 * This calculation should technically be a recurrence, but the total number of metadata708	 * blocks is currently less than a single block of ref_counts, so we'd gain at most one709	 * data block in each slab with more iteration.710	 */711	ref_blocks = vdo_get_saved_reference_count_size(slab_size - slab_journal_blocks);712	meta_blocks = (ref_blocks + slab_journal_blocks);713 714	/* Make sure test code hasn't configured slabs to be too small. */715	if (meta_blocks >= slab_size)716		return VDO_BAD_CONFIGURATION;717 718	/*719	 * If the slab size is very small, assume this must be a unit test and override the number720	 * of data blocks to be a power of two (wasting blocks in the slab). Many tests need their721	 * data_blocks fields to be the exact capacity of the configured volume, and that used to722	 * fall out since they use a power of two for the number of data blocks, the slab size was723	 * a power of two, and every block in a slab was a data block.724	 *725	 * TODO: Try to figure out some way of structuring testParameters and unit tests so this726	 * hack isn't needed without having to edit several unit tests every time the metadata size727	 * changes by one block.728	 */729	data_blocks = slab_size - meta_blocks;730	if ((slab_size < 1024) && !is_power_of_2(data_blocks))731		data_blocks = ((block_count_t) 1 << ilog2(data_blocks));732 733	/*734	 * Configure the slab journal thresholds. The flush threshold is 168 of 224 blocks in735	 * production, or 3/4ths, so we use this ratio for all sizes.736	 */737	flushing_threshold = ((slab_journal_blocks * 3) + 3) / 4;738	/*739	 * The blocking threshold should be far enough from the flushing threshold to not produce740	 * delays, but far enough from the end of the journal to allow multiple successive recovery741	 * failures.742	 */743	remaining = slab_journal_blocks - flushing_threshold;744	blocking_threshold = flushing_threshold + ((remaining * 5) / 7);745	/* The scrubbing threshold should be at least 2048 entries before the end of the journal. */746	minimal_extra_space = 1 + (MAXIMUM_VDO_USER_VIOS / VDO_SLAB_JOURNAL_FULL_ENTRIES_PER_BLOCK);747	scrubbing_threshold = blocking_threshold;748	if (slab_journal_blocks > minimal_extra_space)749		scrubbing_threshold = slab_journal_blocks - minimal_extra_space;750	if (blocking_threshold > scrubbing_threshold)751		blocking_threshold = scrubbing_threshold;752 753	*slab_config = (struct slab_config) {754		.slab_blocks = slab_size,755		.data_blocks = data_blocks,756		.reference_count_blocks = ref_blocks,757		.slab_journal_blocks = slab_journal_blocks,758		.slab_journal_flushing_threshold = flushing_threshold,759		.slab_journal_blocking_threshold = blocking_threshold,760		.slab_journal_scrubbing_threshold = scrubbing_threshold};761	return VDO_SUCCESS;762}763 764/**765 * vdo_decode_slab_journal_entry() - Decode a slab journal entry.766 * @block: The journal block holding the entry.767 * @entry_count: The number of the entry.768 *769 * Return: The decoded entry.770 */771struct slab_journal_entry vdo_decode_slab_journal_entry(struct packed_slab_journal_block *block,772							journal_entry_count_t entry_count)773{774	struct slab_journal_entry entry =775		vdo_unpack_slab_journal_entry(&block->payload.entries[entry_count]);776 777	if (block->header.has_block_map_increments &&778	    ((block->payload.full_entries.entry_types[entry_count / 8] &779	      ((u8) 1 << (entry_count % 8))) != 0))780		entry.operation = VDO_JOURNAL_BLOCK_MAP_REMAPPING;781 782	return entry;783}784 785/**786 * allocate_partition() - Allocate a partition and add it to a layout.787 * @layout: The layout containing the partition.788 * @id: The id of the partition.789 * @offset: The offset into the layout at which the partition begins.790 * @size: The size of the partition in blocks.791 *792 * Return: VDO_SUCCESS or an error.793 */794static int allocate_partition(struct layout *layout, u8 id,795			      physical_block_number_t offset, block_count_t size)796{797	struct partition *partition;798	int result;799 800	result = vdo_allocate(1, struct partition, __func__, &partition);801	if (result != VDO_SUCCESS)802		return result;803 804	partition->id = id;805	partition->offset = offset;806	partition->count = size;807	partition->next = layout->head;808	layout->head = partition;809 810	return VDO_SUCCESS;811}812 813/**814 * make_partition() - Create a new partition from the beginning or end of the unused space in a815 *                    layout.816 * @layout: The layout.817 * @id: The id of the partition to make.818 * @size: The number of blocks to carve out; if 0, all remaining space will be used.819 * @beginning: True if the partition should start at the beginning of the unused space.820 *821 * Return: A success or error code, particularly VDO_NO_SPACE if there are fewer than size blocks822 *         remaining.823 */824static int __must_check make_partition(struct layout *layout, enum partition_id id,825				       block_count_t size, bool beginning)826{827	int result;828	physical_block_number_t offset;829	block_count_t free_blocks = layout->last_free - layout->first_free;830 831	if (size == 0) {832		if (free_blocks == 0)833			return VDO_NO_SPACE;834		size = free_blocks;835	} else if (size > free_blocks) {836		return VDO_NO_SPACE;837	}838 839	result = vdo_get_partition(layout, id, NULL);840	if (result != VDO_UNKNOWN_PARTITION)841		return VDO_PARTITION_EXISTS;842 843	offset = beginning ? layout->first_free : (layout->last_free - size);844 845	result = allocate_partition(layout, id, offset, size);846	if (result != VDO_SUCCESS)847		return result;848 849	layout->num_partitions++;850	if (beginning)851		layout->first_free += size;852	else853		layout->last_free = layout->last_free - size;854 855	return VDO_SUCCESS;856}857 858/**859 * vdo_initialize_layout() - Lay out the partitions of a vdo.860 * @size: The entire size of the vdo.861 * @origin: The start of the layout on the underlying storage in blocks.862 * @block_map_blocks: The size of the block map partition.863 * @journal_blocks: The size of the journal partition.864 * @summary_blocks: The size of the slab summary partition.865 * @layout: The layout to initialize.866 *867 * Return: VDO_SUCCESS or an error.868 */869int vdo_initialize_layout(block_count_t size, physical_block_number_t offset,870			  block_count_t block_map_blocks, block_count_t journal_blocks,871			  block_count_t summary_blocks, struct layout *layout)872{873	int result;874	block_count_t necessary_size =875		(offset + block_map_blocks + journal_blocks + summary_blocks);876 877	if (necessary_size > size)878		return vdo_log_error_strerror(VDO_NO_SPACE,879					      "Not enough space to make a VDO");880 881	*layout = (struct layout) {882		.start = offset,883		.size = size,884		.first_free = offset,885		.last_free = size,886		.num_partitions = 0,887		.head = NULL,888	};889 890	result = make_partition(layout, VDO_BLOCK_MAP_PARTITION, block_map_blocks, true);891	if (result != VDO_SUCCESS) {892		vdo_uninitialize_layout(layout);893		return result;894	}895 896	result = make_partition(layout, VDO_SLAB_SUMMARY_PARTITION, summary_blocks,897				false);898	if (result != VDO_SUCCESS) {899		vdo_uninitialize_layout(layout);900		return result;901	}902 903	result = make_partition(layout, VDO_RECOVERY_JOURNAL_PARTITION, journal_blocks,904				false);905	if (result != VDO_SUCCESS) {906		vdo_uninitialize_layout(layout);907		return result;908	}909 910	result = make_partition(layout, VDO_SLAB_DEPOT_PARTITION, 0, true);911	if (result != VDO_SUCCESS)912		vdo_uninitialize_layout(layout);913 914	return result;915}916 917/**918 * vdo_uninitialize_layout() - Clean up a layout.919 * @layout: The layout to clean up.920 *921 * All partitions created by this layout become invalid pointers.922 */923void vdo_uninitialize_layout(struct layout *layout)924{925	while (layout->head != NULL) {926		struct partition *part = layout->head;927 928		layout->head = part->next;929		vdo_free(part);930	}931 932	memset(layout, 0, sizeof(struct layout));933}934 935/**936 * vdo_get_partition() - Get a partition by id.937 * @layout: The layout from which to get a partition.938 * @id: The id of the partition.939 * @partition_ptr: A pointer to hold the partition.940 *941 * Return: VDO_SUCCESS or an error.942 */943int vdo_get_partition(struct layout *layout, enum partition_id id,944		      struct partition **partition_ptr)945{946	struct partition *partition;947 948	for (partition = layout->head; partition != NULL; partition = partition->next) {949		if (partition->id == id) {950			if (partition_ptr != NULL)951				*partition_ptr = partition;952			return VDO_SUCCESS;953		}954	}955 956	return VDO_UNKNOWN_PARTITION;957}958 959/**960 * vdo_get_known_partition() - Get a partition by id from a validated layout.961 * @layout: The layout from which to get a partition.962 * @id: The id of the partition.963 *964 * Return: the partition965 */966struct partition *vdo_get_known_partition(struct layout *layout, enum partition_id id)967{968	struct partition *partition;969	int result = vdo_get_partition(layout, id, &partition);970 971	VDO_ASSERT_LOG_ONLY(result == VDO_SUCCESS, "layout has expected partition: %u", id);972 973	return partition;974}975 976static void encode_layout(u8 *buffer, size_t *offset, const struct layout *layout)977{978	const struct partition *partition;979	size_t initial_offset;980	struct header header = VDO_LAYOUT_HEADER_3_0;981 982	BUILD_BUG_ON(sizeof(enum partition_id) != sizeof(u8));983	VDO_ASSERT_LOG_ONLY(layout->num_partitions <= U8_MAX,984			    "layout partition count must fit in a byte");985 986	vdo_encode_header(buffer, offset, &header);987 988	initial_offset = *offset;989	encode_u64_le(buffer, offset, layout->first_free);990	encode_u64_le(buffer, offset, layout->last_free);991	buffer[(*offset)++] = layout->num_partitions;992 993	VDO_ASSERT_LOG_ONLY(sizeof(struct layout_3_0) == *offset - initial_offset,994			    "encoded size of a layout header must match structure");995 996	for (partition = layout->head; partition != NULL; partition = partition->next) {997		buffer[(*offset)++] = partition->id;998		encode_u64_le(buffer, offset, partition->offset);999		/* This field only exists for backwards compatibility */1000		encode_u64_le(buffer, offset, 0);1001		encode_u64_le(buffer, offset, partition->count);1002	}1003 1004	VDO_ASSERT_LOG_ONLY(header.size == *offset - initial_offset,1005			    "encoded size of a layout must match header size");1006}1007 1008static int decode_layout(u8 *buffer, size_t *offset, physical_block_number_t start,1009			 block_count_t size, struct layout *layout)1010{1011	struct header header;1012	struct layout_3_0 layout_header;1013	struct partition *partition;1014	size_t initial_offset;1015	physical_block_number_t first_free, last_free;1016	u8 partition_count;1017	u8 i;1018	int result;1019 1020	vdo_decode_header(buffer, offset, &header);1021	/* Layout is variable size, so only do a minimum size check here. */1022	result = vdo_validate_header(&VDO_LAYOUT_HEADER_3_0, &header, false, __func__);1023	if (result != VDO_SUCCESS)1024		return result;1025 1026	initial_offset = *offset;1027	decode_u64_le(buffer, offset, &first_free);1028	decode_u64_le(buffer, offset, &last_free);1029	partition_count = buffer[(*offset)++];1030	layout_header = (struct layout_3_0) {1031		.first_free = first_free,1032		.last_free = last_free,1033		.partition_count = partition_count,1034	};1035 1036	result = VDO_ASSERT(sizeof(struct layout_3_0) == *offset - initial_offset,1037			    "decoded size of a layout header must match structure");1038	if (result != VDO_SUCCESS)1039		return result;1040 1041	layout->start = start;1042	layout->size = size;1043	layout->first_free = layout_header.first_free;1044	layout->last_free = layout_header.last_free;1045	layout->num_partitions = layout_header.partition_count;1046 1047	if (layout->num_partitions > VDO_PARTITION_COUNT) {1048		return vdo_log_error_strerror(VDO_UNKNOWN_PARTITION,1049					      "layout has extra partitions");1050	}1051 1052	for (i = 0; i < layout->num_partitions; i++) {1053		u8 id;1054		u64 partition_offset, count;1055 1056		id = buffer[(*offset)++];1057		decode_u64_le(buffer, offset, &partition_offset);1058		*offset += sizeof(u64);1059		decode_u64_le(buffer, offset, &count);1060 1061		result = allocate_partition(layout, id, partition_offset, count);1062		if (result != VDO_SUCCESS) {1063			vdo_uninitialize_layout(layout);1064			return result;1065		}1066	}1067 1068	/* Validate that the layout has all (and only) the required partitions */1069	for (i = 0; i < VDO_PARTITION_COUNT; i++) {1070		result = vdo_get_partition(layout, REQUIRED_PARTITIONS[i], &partition);1071		if (result != VDO_SUCCESS) {1072			vdo_uninitialize_layout(layout);1073			return vdo_log_error_strerror(result,1074						      "layout is missing required partition %u",1075						      REQUIRED_PARTITIONS[i]);1076		}1077 1078		start += partition->count;1079	}1080 1081	if (start != size) {1082		vdo_uninitialize_layout(layout);1083		return vdo_log_error_strerror(UDS_BAD_STATE,1084					      "partitions do not cover the layout");1085	}1086 1087	return VDO_SUCCESS;1088}1089 1090/**1091 * pack_vdo_config() - Convert a vdo_config to its packed on-disk representation.1092 * @config: The vdo config to convert.1093 *1094 * Return: The platform-independent representation of the config.1095 */1096static struct packed_vdo_config pack_vdo_config(struct vdo_config config)1097{1098	return (struct packed_vdo_config) {1099		.logical_blocks = __cpu_to_le64(config.logical_blocks),1100		.physical_blocks = __cpu_to_le64(config.physical_blocks),1101		.slab_size = __cpu_to_le64(config.slab_size),1102		.recovery_journal_size = __cpu_to_le64(config.recovery_journal_size),1103		.slab_journal_blocks = __cpu_to_le64(config.slab_journal_blocks),1104	};1105}1106 1107/**1108 * pack_vdo_component() - Convert a vdo_component to its packed on-disk representation.1109 * @component: The VDO component data to convert.1110 *1111 * Return: The platform-independent representation of the component.1112 */1113static struct packed_vdo_component_41_0 pack_vdo_component(const struct vdo_component component)1114{1115	return (struct packed_vdo_component_41_0) {1116		.state = __cpu_to_le32(component.state),1117		.complete_recoveries = __cpu_to_le64(component.complete_recoveries),1118		.read_only_recoveries = __cpu_to_le64(component.read_only_recoveries),1119		.config = pack_vdo_config(component.config),1120		.nonce = __cpu_to_le64(component.nonce),1121	};1122}1123 1124static void encode_vdo_component(u8 *buffer, size_t *offset,1125				 struct vdo_component component)1126{1127	struct packed_vdo_component_41_0 packed;1128 1129	encode_version_number(buffer, offset, VDO_COMPONENT_DATA_41_0);1130	packed = pack_vdo_component(component);1131	memcpy(buffer + *offset, &packed, sizeof(packed));1132	*offset += sizeof(packed);1133}1134 1135/**1136 * unpack_vdo_config() - Convert a packed_vdo_config to its native in-memory representation.1137 * @config: The packed vdo config to convert.1138 *1139 * Return: The native in-memory representation of the vdo config.1140 */1141static struct vdo_config unpack_vdo_config(struct packed_vdo_config config)1142{1143	return (struct vdo_config) {1144		.logical_blocks = __le64_to_cpu(config.logical_blocks),1145		.physical_blocks = __le64_to_cpu(config.physical_blocks),1146		.slab_size = __le64_to_cpu(config.slab_size),1147		.recovery_journal_size = __le64_to_cpu(config.recovery_journal_size),1148		.slab_journal_blocks = __le64_to_cpu(config.slab_journal_blocks),1149	};1150}1151 1152/**1153 * unpack_vdo_component_41_0() - Convert a packed_vdo_component_41_0 to its native in-memory1154 *				 representation.1155 * @component: The packed vdo component data to convert.1156 *1157 * Return: The native in-memory representation of the component.1158 */1159static struct vdo_component unpack_vdo_component_41_0(struct packed_vdo_component_41_0 component)1160{1161	return (struct vdo_component) {1162		.state = __le32_to_cpu(component.state),1163		.complete_recoveries = __le64_to_cpu(component.complete_recoveries),1164		.read_only_recoveries = __le64_to_cpu(component.read_only_recoveries),1165		.config = unpack_vdo_config(component.config),1166		.nonce = __le64_to_cpu(component.nonce),1167	};1168}1169 1170/**1171 * decode_vdo_component() - Decode the component data for the vdo itself out of the super block.1172 *1173 * Return: VDO_SUCCESS or an error.1174 */1175static int decode_vdo_component(u8 *buffer, size_t *offset, struct vdo_component *component)1176{1177	struct version_number version;1178	struct packed_vdo_component_41_0 packed;1179	int result;1180 1181	decode_version_number(buffer, offset, &version);1182	result = validate_version(version, VDO_COMPONENT_DATA_41_0,1183				  "VDO component data");1184	if (result != VDO_SUCCESS)1185		return result;1186 1187	memcpy(&packed, buffer + *offset, sizeof(packed));1188	*offset += sizeof(packed);1189	*component = unpack_vdo_component_41_0(packed);1190	return VDO_SUCCESS;1191}1192 1193/**1194 * vdo_validate_config() - Validate constraints on a VDO config.1195 * @config: The VDO config.1196 * @physical_block_count: The minimum block count of the underlying storage.1197 * @logical_block_count: The expected logical size of the VDO, or 0 if the logical size may be1198 *			 unspecified.1199 *1200 * Return: A success or error code.1201 */1202int vdo_validate_config(const struct vdo_config *config,1203			block_count_t physical_block_count,1204			block_count_t logical_block_count)1205{1206	struct slab_config slab_config;1207	int result;1208 1209	result = VDO_ASSERT(config->slab_size > 0, "slab size unspecified");1210	if (result != VDO_SUCCESS)1211		return result;1212 1213	result = VDO_ASSERT(is_power_of_2(config->slab_size),1214			    "slab size must be a power of two");1215	if (result != VDO_SUCCESS)1216		return result;1217 1218	result = VDO_ASSERT(config->slab_size <= (1 << MAX_VDO_SLAB_BITS),1219			    "slab size must be less than or equal to 2^%d",1220			    MAX_VDO_SLAB_BITS);1221	if (result != VDO_SUCCESS)1222		return result;1223 1224	result = VDO_ASSERT(config->slab_journal_blocks >= MINIMUM_VDO_SLAB_JOURNAL_BLOCKS,1225			    "slab journal size meets minimum size");1226	if (result != VDO_SUCCESS)1227		return result;1228 1229	result = VDO_ASSERT(config->slab_journal_blocks <= config->slab_size,1230			    "slab journal size is within expected bound");1231	if (result != VDO_SUCCESS)1232		return result;1233 1234	result = vdo_configure_slab(config->slab_size, config->slab_journal_blocks,1235				    &slab_config);1236	if (result != VDO_SUCCESS)1237		return result;1238 1239	result = VDO_ASSERT((slab_config.data_blocks >= 1),1240			    "slab must be able to hold at least one block");1241	if (result != VDO_SUCCESS)1242		return result;1243 1244	result = VDO_ASSERT(config->physical_blocks > 0, "physical blocks unspecified");1245	if (result != VDO_SUCCESS)1246		return result;1247 1248	result = VDO_ASSERT(config->physical_blocks <= MAXIMUM_VDO_PHYSICAL_BLOCKS,1249			    "physical block count %llu exceeds maximum %llu",1250			    (unsigned long long) config->physical_blocks,1251			    (unsigned long long) MAXIMUM_VDO_PHYSICAL_BLOCKS);1252	if (result != VDO_SUCCESS)1253		return VDO_OUT_OF_RANGE;1254 1255	if (physical_block_count != config->physical_blocks) {1256		vdo_log_error("A physical size of %llu blocks was specified, not the %llu blocks configured in the vdo super block",1257			      (unsigned long long) physical_block_count,1258			      (unsigned long long) config->physical_blocks);1259		return VDO_PARAMETER_MISMATCH;1260	}1261 1262	if (logical_block_count > 0) {1263		result = VDO_ASSERT((config->logical_blocks > 0),1264				    "logical blocks unspecified");1265		if (result != VDO_SUCCESS)1266			return result;1267 1268		if (logical_block_count != config->logical_blocks) {1269			vdo_log_error("A logical size of %llu blocks was specified, but that differs from the %llu blocks configured in the vdo super block",1270				      (unsigned long long) logical_block_count,1271				      (unsigned long long) config->logical_blocks);1272			return VDO_PARAMETER_MISMATCH;1273		}1274	}1275 1276	result = VDO_ASSERT(config->logical_blocks <= MAXIMUM_VDO_LOGICAL_BLOCKS,1277			    "logical blocks too large");1278	if (result != VDO_SUCCESS)1279		return result;1280 1281	result = VDO_ASSERT(config->recovery_journal_size > 0,1282			    "recovery journal size unspecified");1283	if (result != VDO_SUCCESS)1284		return result;1285 1286	result = VDO_ASSERT(is_power_of_2(config->recovery_journal_size),1287			    "recovery journal size must be a power of two");1288	if (result != VDO_SUCCESS)1289		return result;1290 1291	return result;1292}1293 1294/**1295 * vdo_destroy_component_states() - Clean up any allocations in a vdo_component_states.1296 * @states: The component states to destroy.1297 */1298void vdo_destroy_component_states(struct vdo_component_states *states)1299{1300	if (states == NULL)1301		return;1302 1303	vdo_uninitialize_layout(&states->layout);1304}1305 1306/**1307 * decode_components() - Decode the components now that we know the component data is a version we1308 *                       understand.1309 * @buffer: The buffer being decoded.1310 * @offset: The offset to start decoding from.1311 * @geometry: The vdo geometry1312 * @states: An object to hold the successfully decoded state.1313 *1314 * Return: VDO_SUCCESS or an error.1315 */1316static int __must_check decode_components(u8 *buffer, size_t *offset,1317					  struct volume_geometry *geometry,1318					  struct vdo_component_states *states)1319{1320	int result;1321 1322	decode_vdo_component(buffer, offset, &states->vdo);1323 1324	result = decode_layout(buffer, offset, vdo_get_data_region_start(*geometry) + 1,1325			       states->vdo.config.physical_blocks, &states->layout);1326	if (result != VDO_SUCCESS)1327		return result;1328 1329	result = decode_recovery_journal_state_7_0(buffer, offset,1330						   &states->recovery_journal);1331	if (result != VDO_SUCCESS)1332		return result;1333 1334	result = decode_slab_depot_state_2_0(buffer, offset, &states->slab_depot);1335	if (result != VDO_SUCCESS)1336		return result;1337 1338	result = decode_block_map_state_2_0(buffer, offset, &states->block_map);1339	if (result != VDO_SUCCESS)1340		return result;1341 1342	VDO_ASSERT_LOG_ONLY(*offset == VDO_COMPONENT_DATA_OFFSET + VDO_COMPONENT_DATA_SIZE,1343			    "All decoded component data was used");1344	return VDO_SUCCESS;1345}1346 1347/**1348 * vdo_decode_component_states() - Decode the payload of a super block.1349 * @buffer: The buffer containing the encoded super block contents.1350 * @geometry: The vdo geometry1351 * @states: A pointer to hold the decoded states.1352 *1353 * Return: VDO_SUCCESS or an error.1354 */1355int vdo_decode_component_states(u8 *buffer, struct volume_geometry *geometry,1356				struct vdo_component_states *states)1357{1358	int result;1359	size_t offset = VDO_COMPONENT_DATA_OFFSET;1360 1361	/* This is for backwards compatibility. */1362	decode_u32_le(buffer, &offset, &states->unused);1363 1364	/* Check the VDO volume version */1365	decode_version_number(buffer, &offset, &states->volume_version);1366	result = validate_version(VDO_VOLUME_VERSION_67_0, states->volume_version,1367				  "volume");1368	if (result != VDO_SUCCESS)1369		return result;1370 1371	result = decode_components(buffer, &offset, geometry, states);1372	if (result != VDO_SUCCESS)1373		vdo_uninitialize_layout(&states->layout);1374 1375	return result;1376}1377 1378/**1379 * vdo_validate_component_states() - Validate the decoded super block configuration.1380 * @states: The state decoded from the super block.1381 * @geometry_nonce: The nonce from the geometry block.1382 * @physical_size: The minimum block count of the underlying storage.1383 * @logical_size: The expected logical size of the VDO, or 0 if the logical size may be1384 *                unspecified.1385 *1386 * Return: VDO_SUCCESS or an error if the configuration is invalid.1387 */1388int vdo_validate_component_states(struct vdo_component_states *states,1389				  nonce_t geometry_nonce, block_count_t physical_size,1390				  block_count_t logical_size)1391{1392	if (geometry_nonce != states->vdo.nonce) {1393		return vdo_log_error_strerror(VDO_BAD_NONCE,1394					      "Geometry nonce %llu does not match superblock nonce %llu",1395					      (unsigned long long) geometry_nonce,1396					      (unsigned long long) states->vdo.nonce);1397	}1398 1399	return vdo_validate_config(&states->vdo.config, physical_size, logical_size);1400}1401 1402/**1403 * vdo_encode_component_states() - Encode the state of all vdo components in the super block.1404 */1405static void vdo_encode_component_states(u8 *buffer, size_t *offset,1406					const struct vdo_component_states *states)1407{1408	/* This is for backwards compatibility. */1409	encode_u32_le(buffer, offset, states->unused);1410	encode_version_number(buffer, offset, states->volume_version);1411	encode_vdo_component(buffer, offset, states->vdo);1412	encode_layout(buffer, offset, &states->layout);1413	encode_recovery_journal_state_7_0(buffer, offset, states->recovery_journal);1414	encode_slab_depot_state_2_0(buffer, offset, states->slab_depot);1415	encode_block_map_state_2_0(buffer, offset, states->block_map);1416 1417	VDO_ASSERT_LOG_ONLY(*offset == VDO_COMPONENT_DATA_OFFSET + VDO_COMPONENT_DATA_SIZE,1418			    "All super block component data was encoded");1419}1420 1421/**1422 * vdo_encode_super_block() - Encode a super block into its on-disk representation.1423 */1424void vdo_encode_super_block(u8 *buffer, struct vdo_component_states *states)1425{1426	u32 checksum;1427	struct header header = SUPER_BLOCK_HEADER_12_0;1428	size_t offset = 0;1429 1430	header.size += VDO_COMPONENT_DATA_SIZE;1431	vdo_encode_header(buffer, &offset, &header);1432	vdo_encode_component_states(buffer, &offset, states);1433 1434	checksum = vdo_crc32(buffer, offset);1435	encode_u32_le(buffer, &offset, checksum);1436 1437	/*1438	 * Even though the buffer is a full block, to avoid the potential corruption from a torn1439	 * write, the entire encoding must fit in the first sector.1440	 */1441	VDO_ASSERT_LOG_ONLY(offset <= VDO_SECTOR_SIZE,1442			    "entire superblock must fit in one sector");1443}1444 1445/**1446 * vdo_decode_super_block() - Decode a super block from its on-disk representation.1447 */1448int vdo_decode_super_block(u8 *buffer)1449{1450	struct header header;1451	int result;1452	u32 checksum, saved_checksum;1453	size_t offset = 0;1454 1455	/* Decode and validate the header. */1456	vdo_decode_header(buffer, &offset, &header);1457	result = vdo_validate_header(&SUPER_BLOCK_HEADER_12_0, &header, false, __func__);1458	if (result != VDO_SUCCESS)1459		return result;1460 1461	if (header.size > VDO_COMPONENT_DATA_SIZE + sizeof(u32)) {1462		/*1463		 * We can't check release version or checksum until we know the content size, so we1464		 * have to assume a version mismatch on unexpected values.1465		 */1466		return vdo_log_error_strerror(VDO_UNSUPPORTED_VERSION,1467					      "super block contents too large: %zu",1468					      header.size);1469	}1470 1471	/* Skip past the component data for now, to verify the checksum. */1472	offset += VDO_COMPONENT_DATA_SIZE;1473 1474	checksum = vdo_crc32(buffer, offset);1475	decode_u32_le(buffer, &offset, &saved_checksum);1476 1477	result = VDO_ASSERT(offset == VDO_SUPER_BLOCK_FIXED_SIZE + VDO_COMPONENT_DATA_SIZE,1478			    "must have decoded entire superblock payload");1479	if (result != VDO_SUCCESS)1480		return result;1481 1482	return ((checksum != saved_checksum) ? VDO_CHECKSUM_MISMATCH : VDO_SUCCESS);1483}1484