linux/drivers/md/dm-vdo/encodings.h

/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright 2023 Red Hat
 */

#ifndef VDO_ENCODINGS_H
#define VDO_ENCODINGS_H

#include <linux/blk_types.h>
#include <linux/crc32.h>
#include <linux/limits.h>
#include <linux/uuid.h>

#include "numeric.h"

#include "constants.h"
#include "types.h"

/*
 * An in-memory representation of a version number for versioned structures on disk.
 *
 * A version number consists of two portions, a major version and a minor version. Any format
 * change which does not require an explicit upgrade step from the previous version should
 * increment the minor version. Any format change which either requires an explicit upgrade step,
 * or is wholly incompatible (i.e. can not be upgraded to), should increment the major version, and
 * set the minor version to 0.
 */
struct version_number {};

/*
 * A packed, machine-independent, on-disk representation of a version_number. Both fields are
 * stored in little-endian byte order.
 */
struct packed_version_number {} __packed;

/* The registry of component ids for use in headers */
#define VDO_SUPER_BLOCK
#define VDO_LAYOUT
#define VDO_RECOVERY_JOURNAL
#define VDO_SLAB_DEPOT
#define VDO_BLOCK_MAP
#define VDO_GEOMETRY_BLOCK

/* The header for versioned data stored on disk. */
struct header {};

/* A packed, machine-independent, on-disk representation of a component header. */
struct packed_header {} __packed;

enum {};

struct index_config {} __packed;

enum volume_region_id {};

struct volume_region {} __packed;

struct volume_geometry {} __packed;

/* This volume geometry struct is used for sizing only */
struct volume_geometry_4_0 {} __packed;

extern const u8 VDO_GEOMETRY_MAGIC_NUMBER[VDO_GEOMETRY_MAGIC_NUMBER_SIZE + 1];

/**
 * DOC: Block map entries
 *
 * The entry for each logical block in the block map is encoded into five bytes, which saves space
 * in both the on-disk and in-memory layouts. It consists of the 36 low-order bits of a
 * physical_block_number_t (addressing 256 terabytes with a 4KB block size) and a 4-bit encoding of
 * a block_mapping_state.
 *
 * Of the 8 high bits of the 5-byte structure:
 *
 * Bits 7..4: The four highest bits of the 36-bit physical block number
 * Bits 3..0: The 4-bit block_mapping_state
 *
 * The following 4 bytes are the low order bytes of the physical block number, in little-endian
 * order.
 *
 * Conversion functions to and from a data location are provided.
 */
struct block_map_entry {} __packed;

struct block_map_page_header {} __packed;

struct block_map_page {} __packed;

enum block_map_page_validity {};

struct block_map_state_2_0 {} __packed;

struct boundary {};

extern const struct header VDO_BLOCK_MAP_HEADER_2_0;

/* The state of the recovery journal as encoded in the VDO super block. */
struct recovery_journal_state_7_0 {} __packed;

extern const struct header VDO_RECOVERY_JOURNAL_HEADER_7_0;

journal_entry_count_t;

/*
 * A recovery journal entry stores three physical locations: a data location that is the value of a
 * single mapping in the block map tree, and the two locations of the block map pages and slots
 * that are acquiring and releasing a reference to the location. The journal entry also stores an
 * operation code that says whether the mapping is for a logical block or for the block map tree
 * itself.
 */
struct recovery_journal_entry {};

/* The packed, on-disk representation of a recovery journal entry. */
struct packed_recovery_journal_entry {} __packed;

/* The packed, on-disk representation of an old format recovery journal entry. */
struct packed_recovery_journal_entry_1 {} __packed;

enum journal_operation_1 {} __packed;

struct recovery_block_header {};

/*
 * The packed, on-disk representation of a recovery journal block header. All fields are kept in
 * little-endian byte order.
 */
struct packed_journal_header {} __packed;

struct packed_journal_sector {} __packed;

enum {};

/* A type representing a reference count of a block. */
vdo_refcount_t;

/* The absolute position of an entry in a recovery journal or slab journal. */
struct journal_point {};

/* A packed, platform-independent encoding of a struct journal_point. */
struct packed_journal_point {} __packed;

/* Special vdo_refcount_t values. */
#define EMPTY_REFERENCE_COUNT
enum {};

enum {};

/* The format of each sector of a reference_block on disk. */
struct packed_reference_sector {} __packed;

struct packed_reference_block {};

struct slab_depot_state_2_0 {} __packed;

extern const struct header VDO_SLAB_DEPOT_HEADER_2_0;

/*
 * vdo_slab journal blocks may have one of two formats, depending upon whether or not any of the
 * entries in the block are block map increments. Since the steady state for a VDO is that all of
 * the necessary block map pages will be allocated, most slab journal blocks will have only data
 * entries. Such blocks can hold more entries, hence the two formats.
 */

/* A single slab journal entry */
struct slab_journal_entry {};

/* A single slab journal entry in its on-disk form */
packed_slab_journal_entry;

/* The unpacked representation of the header of a slab journal block */
struct slab_journal_block_header {};

/*
 * The packed, on-disk representation of a slab journal block header. All fields are kept in
 * little-endian byte order.
 */
struct packed_slab_journal_block_header {} __packed;

enum {};

/* The payload of a slab journal block which has block map increments */
struct full_slab_journal_entries {} __packed;

slab_journal_payload;

struct packed_slab_journal_block {} __packed;

/* The offset of a slab journal tail block. */
tail_block_offset_t;

struct slab_summary_entry {} __packed;

enum {};

struct layout {};

struct partition {};

struct layout_3_0 {} __packed;

struct partition_3_0 {} __packed;

/*
 * The configuration of the VDO service.
 */
struct vdo_config {};

/* This is the structure that captures the vdo fields saved as a super block component. */
struct vdo_component {};

/*
 * A packed, machine-independent, on-disk representation of the vdo_config in the VDO component
 * data in the super block.
 */
struct packed_vdo_config {} __packed;

/*
 * A packed, machine-independent, on-disk representation of version 41.0 of the VDO component data
 * in the super block.
 */
struct packed_vdo_component_41_0 {} __packed;

/*
 * The version of the on-disk format of a VDO volume. This should be incremented any time the
 * on-disk representation of any VDO structure changes. Changes which require only online upgrade
 * steps should increment the minor version. Changes which require an offline upgrade or which can
 * not be upgraded to at all should increment the major version and set the minor version to 0.
 */
extern const struct version_number VDO_VOLUME_VERSION_67_0;

enum {};

/* The entirety of the component data encoded in the VDO super block. */
struct vdo_component_states {};

/**
 * vdo_are_same_version() - Check whether two version numbers are the same.
 * @version_a: The first version.
 * @version_b: The second version.
 *
 * Return: true if the two versions are the same.
 */
static inline bool vdo_are_same_version(struct version_number version_a,
					struct version_number version_b)
{}

/**
 * vdo_is_upgradable_version() - Check whether an actual version is upgradable to an expected
 *                               version.
 * @expected_version: The expected version.
 * @actual_version: The version being validated.
 *
 * An actual version is upgradable if its major number is expected but its minor number differs,
 * and the expected version's minor number is greater than the actual version's minor number.
 *
 * Return: true if the actual version is upgradable.
 */
static inline bool vdo_is_upgradable_version(struct version_number expected_version,
					     struct version_number actual_version)
{}

int __must_check vdo_validate_header(const struct header *expected_header,
				     const struct header *actual_header, bool exact_size,
				     const char *component_name);

void vdo_encode_header(u8 *buffer, size_t *offset, const struct header *header);
void vdo_decode_header(u8 *buffer, size_t *offset, struct header *header);

/**
 * vdo_pack_version_number() - Convert a version_number to its packed on-disk representation.
 * @version: The version number to convert.
 *
 * Return: the platform-independent representation of the version
 */
static inline struct packed_version_number vdo_pack_version_number(struct version_number version)
{}

/**
 * vdo_unpack_version_number() - Convert a packed_version_number to its native in-memory
 *                               representation.
 * @version: The version number to convert.
 *
 * Return: The platform-independent representation of the version.
 */
static inline struct version_number vdo_unpack_version_number(struct packed_version_number version)
{}

/**
 * vdo_pack_header() - Convert a component header to its packed on-disk representation.
 * @header: The header to convert.
 *
 * Return: the platform-independent representation of the header
 */
static inline struct packed_header vdo_pack_header(const struct header *header)
{}

/**
 * vdo_unpack_header() - Convert a packed_header to its native in-memory representation.
 * @header: The header to convert.
 *
 * Return: The platform-independent representation of the version.
 */
static inline struct header vdo_unpack_header(const struct packed_header *header)
{}

/**
 * vdo_get_index_region_start() - Get the start of the index region from a geometry.
 * @geometry: The geometry.
 *
 * Return: The start of the index region.
 */
static inline physical_block_number_t __must_check
vdo_get_index_region_start(struct volume_geometry geometry)
{}

/**
 * vdo_get_data_region_start() - Get the start of the data region from a geometry.
 * @geometry: The geometry.
 *
 * Return: The start of the data region.
 */
static inline physical_block_number_t __must_check
vdo_get_data_region_start(struct volume_geometry geometry)
{}

/**
 * vdo_get_index_region_size() - Get the size of the index region from a geometry.
 * @geometry: The geometry.
 *
 * Return: The size of the index region.
 */
static inline physical_block_number_t __must_check
vdo_get_index_region_size(struct volume_geometry geometry)
{}

int __must_check vdo_parse_geometry_block(unsigned char *block,
					  struct volume_geometry *geometry);

static inline bool vdo_is_state_compressed(const enum block_mapping_state mapping_state)
{}

static inline struct block_map_entry
vdo_pack_block_map_entry(physical_block_number_t pbn, enum block_mapping_state mapping_state)
{}

static inline struct data_location vdo_unpack_block_map_entry(const struct block_map_entry *entry)
{}

static inline bool vdo_is_mapped_location(const struct data_location *location)
{}

static inline bool vdo_is_valid_location(const struct data_location *location)
{}

static inline physical_block_number_t __must_check
vdo_get_block_map_page_pbn(const struct block_map_page *page)
{}

struct block_map_page *vdo_format_block_map_page(void *buffer, nonce_t nonce,
						 physical_block_number_t pbn,
						 bool initialized);

enum block_map_page_validity __must_check vdo_validate_block_map_page(struct block_map_page *page,
								      nonce_t nonce,
								      physical_block_number_t pbn);

static inline page_count_t vdo_compute_block_map_page_count(block_count_t entries)
{}

block_count_t __must_check vdo_compute_new_forest_pages(root_count_t root_count,
							struct boundary *old_sizes,
							block_count_t entries,
							struct boundary *new_sizes);

/**
 * vdo_pack_recovery_journal_entry() - Return the packed, on-disk representation of a recovery
 *                                     journal entry.
 * @entry: The journal entry to pack.
 *
 * Return: The packed representation of the journal entry.
 */
static inline struct packed_recovery_journal_entry
vdo_pack_recovery_journal_entry(const struct recovery_journal_entry *entry)
{}

/**
 * vdo_unpack_recovery_journal_entry() - Unpack the on-disk representation of a recovery journal
 *                                       entry.
 * @entry: The recovery journal entry to unpack.
 *
 * Return: The unpacked entry.
 */
static inline struct recovery_journal_entry
vdo_unpack_recovery_journal_entry(const struct packed_recovery_journal_entry *entry)
{}

const char * __must_check vdo_get_journal_operation_name(enum journal_operation operation);

/**
 * vdo_is_valid_recovery_journal_sector() - Determine whether the header of the given sector could
 *                                          describe a valid sector for the given journal block
 *                                          header.
 * @header: The unpacked block header to compare against.
 * @sector: The packed sector to check.
 * @sector_number: The number of the sector being checked.
 *
 * Return: true if the sector matches the block header.
 */
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)
{}

/**
 * vdo_compute_recovery_journal_block_number() - Compute the physical block number of the recovery
 *                                               journal block which would have a given sequence
 *                                               number.
 * @journal_size: The size of the journal.
 * @sequence_number: The sequence number.
 *
 * Return: The pbn of the journal block which would the specified sequence number.
 */
static inline physical_block_number_t __must_check
vdo_compute_recovery_journal_block_number(block_count_t journal_size,
					  sequence_number_t sequence_number)
{}

/**
 * vdo_get_journal_block_sector() - Find the recovery journal sector from the block header and
 *                                  sector number.
 * @header: The header of the recovery journal block.
 * @sector_number: The index of the sector (1-based).
 *
 * Return: A packed recovery journal sector.
 */
static inline struct packed_journal_sector * __must_check
vdo_get_journal_block_sector(struct packed_journal_header *header, int sector_number)
{}

/**
 * vdo_pack_recovery_block_header() - Generate the packed representation of a recovery block
 *                                    header.
 * @header: The header containing the values to encode.
 * @packed: The header into which to pack the values.
 */
static inline void vdo_pack_recovery_block_header(const struct recovery_block_header *header,
						  struct packed_journal_header *packed)
{}

/**
 * vdo_unpack_recovery_block_header() - Decode the packed representation of a recovery block
 *                                      header.
 * @packed: The packed header to decode.
 *
 * Return: The unpacked header.
 */
static inline struct recovery_block_header
vdo_unpack_recovery_block_header(const struct packed_journal_header *packed)
{}

/**
 * vdo_compute_slab_count() - Compute the number of slabs a depot with given parameters would have.
 * @first_block: PBN of the first data block.
 * @last_block: PBN of the last data block.
 * @slab_size_shift: Exponent for the number of blocks per slab.
 *
 * Return: The number of slabs.
 */
static inline slab_count_t vdo_compute_slab_count(physical_block_number_t first_block,
						  physical_block_number_t last_block,
						  unsigned int slab_size_shift)
{}

int __must_check vdo_configure_slab_depot(const struct partition *partition,
					  struct slab_config slab_config,
					  zone_count_t zone_count,
					  struct slab_depot_state_2_0 *state);

int __must_check vdo_configure_slab(block_count_t slab_size,
				    block_count_t slab_journal_blocks,
				    struct slab_config *slab_config);

/**
 * vdo_get_saved_reference_count_size() - Get the number of blocks required to save a reference
 *                                        counts state covering the specified number of data
 *                                        blocks.
 * @block_count: The number of physical data blocks that can be referenced.
 *
 * Return: The number of blocks required to save reference counts with the given block count.
 */
static inline block_count_t vdo_get_saved_reference_count_size(block_count_t block_count)
{}

/**
 * vdo_get_slab_journal_start_block() - Get the physical block number of the start of the slab
 *                                      journal relative to the start block allocator partition.
 * @slab_config: The slab configuration of the VDO.
 * @origin: The first block of the slab.
 */
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)
{}

/**
 * vdo_advance_journal_point() - Move the given journal point forward by one entry.
 * @point: The journal point to adjust.
 * @entries_per_block: The number of entries in one full block.
 */
static inline void vdo_advance_journal_point(struct journal_point *point,
					     journal_entry_count_t entries_per_block)
{}

/**
 * vdo_before_journal_point() - Check whether the first point precedes the second point.
 * @first: The first journal point.
 * @second: The second journal point.
 *
 * Return: true if the first point precedes the second point.
 */
static inline bool vdo_before_journal_point(const struct journal_point *first,
					    const struct journal_point *second)
{}

/**
 * vdo_pack_journal_point() - Encode the journal location represented by a
 *                            journal_point into a packed_journal_point.
 * @unpacked: The unpacked input point.
 * @packed: The packed output point.
 */
static inline void vdo_pack_journal_point(const struct journal_point *unpacked,
					  struct packed_journal_point *packed)
{}

/**
 * vdo_unpack_journal_point() - Decode the journal location represented by a packed_journal_point
 *                              into a journal_point.
 * @packed: The packed input point.
 * @unpacked: The unpacked output point.
 */
static inline void vdo_unpack_journal_point(const struct packed_journal_point *packed,
					    struct journal_point *unpacked)
{}

/**
 * vdo_pack_slab_journal_block_header() - Generate the packed representation of a slab block
 *                                        header.
 * @header: The header containing the values to encode.
 * @packed: The header into which to pack the values.
 */
static inline void
vdo_pack_slab_journal_block_header(const struct slab_journal_block_header *header,
				   struct packed_slab_journal_block_header *packed)
{}

/**
 * vdo_unpack_slab_journal_block_header() - Decode the packed representation of a slab block
 *                                          header.
 * @packed: The packed header to decode.
 * @header: The header into which to unpack the values.
 */
static inline void
vdo_unpack_slab_journal_block_header(const struct packed_slab_journal_block_header *packed,
				     struct slab_journal_block_header *header)
{}

/**
 * vdo_pack_slab_journal_entry() - Generate the packed encoding of a slab journal entry.
 * @packed: The entry into which to pack the values.
 * @sbn: The slab block number of the entry to encode.
 * @is_increment: The increment flag.
 */
static inline void vdo_pack_slab_journal_entry(packed_slab_journal_entry *packed,
					       slab_block_number sbn, bool is_increment)
{}

/**
 * vdo_unpack_slab_journal_entry() - Decode the packed representation of a slab journal entry.
 * @packed: The packed entry to decode.
 *
 * Return: The decoded slab journal entry.
 */
static inline struct slab_journal_entry __must_check
vdo_unpack_slab_journal_entry(const packed_slab_journal_entry *packed)
{}

struct slab_journal_entry __must_check
vdo_decode_slab_journal_entry(struct packed_slab_journal_block *block,
			      journal_entry_count_t entry_count);

/**
 * vdo_get_slab_summary_hint_shift() - Compute the shift for slab summary hints.
 * @slab_size_shift: Exponent for the number of blocks per slab.
 *
 * Return: The hint shift.
 */
static inline u8 __must_check vdo_get_slab_summary_hint_shift(unsigned int slab_size_shift)
{}

int __must_check vdo_initialize_layout(block_count_t size,
				       physical_block_number_t offset,
				       block_count_t block_map_blocks,
				       block_count_t journal_blocks,
				       block_count_t summary_blocks,
				       struct layout *layout);

void vdo_uninitialize_layout(struct layout *layout);

int __must_check vdo_get_partition(struct layout *layout, enum partition_id id,
				   struct partition **partition_ptr);

struct partition * __must_check vdo_get_known_partition(struct layout *layout,
							enum partition_id id);

int vdo_validate_config(const struct vdo_config *config,
			block_count_t physical_block_count,
			block_count_t logical_block_count);

void vdo_destroy_component_states(struct vdo_component_states *states);

int __must_check vdo_decode_component_states(u8 *buffer,
					     struct volume_geometry *geometry,
					     struct vdo_component_states *states);

int __must_check vdo_validate_component_states(struct vdo_component_states *states,
					       nonce_t geometry_nonce,
					       block_count_t physical_size,
					       block_count_t logical_size);

void vdo_encode_super_block(u8 *buffer, struct vdo_component_states *states);
int __must_check vdo_decode_super_block(u8 *buffer);

/* We start with 0L and postcondition with ~0L to match our historical usage in userspace. */
static inline u32 vdo_crc32(const void *buf, unsigned long len)
{}

#endif /* VDO_ENCODINGS_H */