Commit 427bf2c1 authored by Bruce Johnston's avatar Bruce Johnston Committed by Mikulas Patocka
Browse files

dm vdo: add geometry block encoding



Add vdo_encode_volume_geometry() to write the geometry block into a
buffer so that it can be written to disk. The corresponding decode
path already exists.

Signed-off-by: default avatarBruce Johnston <bjohnsto@redhat.com>
Reviewed-by: default avatarMatthew Sakai <msakai@redhat.com>
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
parent beced130
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -287,6 +287,62 @@ static void decode_volume_geometry(u8 *buffer, size_t *offset,
	};
}

/**
 * vdo_encode_volume_geometry() - Encode the on-disk representation of a volume geometry into a buffer.
 * @buffer: A buffer to store the encoding.
 * @geometry: The geometry to encode.
 * @version: The geometry block version to encode.
 *
 * Return: VDO_SUCCESS or an error.
 */
int vdo_encode_volume_geometry(u8 *buffer, const struct volume_geometry *geometry,
			       u32 version)
{
	int result;
	enum volume_region_id id;
	u32 checksum;
	size_t offset = 0;
	const struct header *header;

	memcpy(buffer, VDO_GEOMETRY_MAGIC_NUMBER, VDO_GEOMETRY_MAGIC_NUMBER_SIZE);
	offset += VDO_GEOMETRY_MAGIC_NUMBER_SIZE;

	header = (version > 4) ? &GEOMETRY_BLOCK_HEADER_5_0 : &GEOMETRY_BLOCK_HEADER_4_0;
	vdo_encode_header(buffer, &offset, header);

	/* This is for backwards compatibility */
	encode_u32_le(buffer, &offset, geometry->unused);
	encode_u64_le(buffer, &offset, geometry->nonce);
	memcpy(buffer + offset, (unsigned char *) &geometry->uuid, sizeof(uuid_t));
	offset += sizeof(uuid_t);

	if (version > 4)
		encode_u64_le(buffer, &offset, geometry->bio_offset);

	for (id = 0; id < VDO_VOLUME_REGION_COUNT; id++) {
		encode_u32_le(buffer, &offset, geometry->regions[id].id);
		encode_u64_le(buffer, &offset, geometry->regions[id].start_block);
	}

	encode_u32_le(buffer, &offset, geometry->index_config.mem);
	encode_u32_le(buffer, &offset, 0);

	if (geometry->index_config.sparse)
		buffer[offset++] = 1;
	else
		buffer[offset++] = 0;

	result = VDO_ASSERT(header->size == offset + sizeof(u32),
			    "should have encoded up to the geometry checksum");
	if (result != VDO_SUCCESS)
		return result;

	checksum = vdo_crc32(buffer, offset);
	encode_u32_le(buffer, &offset, checksum);

	return VDO_SUCCESS;
}

/**
 * vdo_parse_geometry_block() - Decode and validate an encoded geometry block.
 * @block: The encoded geometry block.
+2 −0
Original line number Diff line number Diff line
@@ -813,6 +813,8 @@ int vdo_initialize_volume_geometry(nonce_t nonce, uuid_t *uuid,
				   const struct index_config *index_config,
				   struct volume_geometry *geometry);

int vdo_encode_volume_geometry(u8 *buffer, const struct volume_geometry *geometry,
			       u32 version);
int __must_check vdo_parse_geometry_block(unsigned char *block,
					  struct volume_geometry *geometry);