linux/drivers/md/dm-vdo/indexer/index-layout.c

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

#include "index-layout.h"

#include <linux/random.h>

#include "logger.h"
#include "memory-alloc.h"
#include "murmurhash3.h"
#include "numeric.h"
#include "time-utils.h"

#include "config.h"
#include "open-chapter.h"
#include "volume-index.h"

/*
 * The UDS layout on storage media is divided into a number of fixed-size regions, the sizes of
 * which are computed when the index is created. Every header and region begins on 4K block
 * boundary. Save regions are further sub-divided into regions of their own.
 *
 * Each region has a kind and an instance number. Some kinds only have one instance and therefore
 * use RL_SOLE_INSTANCE (-1) as the instance number. The RL_KIND_INDEX used to use instances to
 * represent sub-indices; now, however there is only ever one sub-index and therefore one instance.
 * The RL_KIND_VOLUME_INDEX uses instances to record which zone is being saved.
 *
 * Every region header has a type and version.
 *
 *     +-+-+---------+--------+--------+-+
 *     | | |   I N D E X  0   101, 0   | |
 *     |H|C+---------+--------+--------+S|
 *     |D|f| Volume  | Save   | Save   |e|
 *     |R|g| Region  | Region | Region |a|
 *     | | | 201, -1 | 202, 0 | 202, 1 |l|
 *     +-+-+--------+---------+--------+-+
 *
 * The header contains the encoded region layout table as well as some index configuration data.
 * The sub-index region and its subdivisions are maintained in the same table.
 *
 * There are two save regions to preserve the old state in case saving the new state is incomplete.
 * They are used in alternation. Each save region is further divided into sub-regions.
 *
 *     +-+-----+------+------+-----+-----+
 *     |H| IPM | MI   | MI   |     | OC  |
 *     |D|     | zone | zone | ... |     |
 *     |R| 301 | 302  | 302  |     | 303 |
 *     | | -1  |  0   |  1   |     | -1  |
 *     +-+-----+------+------+-----+-----+
 *
 * The header contains the encoded region layout table as well as index state data for that save.
 * Each save also has a unique nonce.
 */

#define MAGIC_SIZE
#define NONCE_INFO_SIZE
#define MAX_SAVES

enum region_kind {};

/* Some region types are historical and are no longer used. */
enum region_type {};

#define RL_SOLE_INSTANCE

/*
 * Super block version 2 is the first released version.
 *
 * Super block version 3 is the normal version used from RHEL 8.2 onwards.
 *
 * Super block versions 4 through 6 were incremental development versions and
 * are not supported.
 *
 * Super block version 7 is used for volumes which have been reduced in size by one chapter in
 * order to make room to prepend LVM metadata to a volume originally created without lvm. This
 * allows the index to retain most its deduplication records.
 */
#define SUPER_VERSION_MINIMUM
#define SUPER_VERSION_CURRENT
#define SUPER_VERSION_MAXIMUM

static const u8 LAYOUT_MAGIC[MAGIC_SIZE] =;
static const u64 REGION_MAGIC =; /* 'AlbRgn01' */

struct region_header {};

struct layout_region {};

struct region_table {};

struct index_save_data {};

struct index_state_version {};

static const struct index_state_version INDEX_STATE_VERSION_301 =;

struct index_state_data301 {};

struct index_save_layout {};

struct sub_index_layout {};

struct super_block_data {};

struct index_layout {};

struct save_layout_sizes {};

static inline bool is_converted_super_block(struct super_block_data *super)
{}

static int __must_check compute_sizes(const struct uds_configuration *config,
				      struct save_layout_sizes *sls)
{}

int uds_compute_index_size(const struct uds_parameters *parameters, u64 *index_size)
{}

/* Create unique data using the current time and a pseudorandom number. */
static void create_unique_nonce_data(u8 *buffer)
{}

static u64 hash_stuff(u64 start, const void *data, size_t len)
{}

/* Generate a primary nonce from the provided data. */
static u64 generate_primary_nonce(const void *data, size_t len)
{}

/*
 * Deterministically generate a secondary nonce from an existing nonce and some arbitrary data by
 * hashing the original nonce and the data to produce a new nonce.
 */
static u64 generate_secondary_nonce(u64 nonce, const void *data, size_t len)
{}

static int __must_check open_layout_reader(struct index_layout *layout,
					   struct layout_region *lr, off_t offset,
					   struct buffered_reader **reader_ptr)
{}

static int open_region_reader(struct index_layout *layout, struct layout_region *region,
			      struct buffered_reader **reader_ptr)
{}

static int __must_check open_layout_writer(struct index_layout *layout,
					   struct layout_region *lr, off_t offset,
					   struct buffered_writer **writer_ptr)
{}

static int open_region_writer(struct index_layout *layout, struct layout_region *region,
			      struct buffered_writer **writer_ptr)
{}

static void generate_super_block_data(struct save_layout_sizes *sls,
				      struct super_block_data *super)
{}

static void define_sub_index_nonce(struct index_layout *layout)
{}

static void setup_sub_index(struct index_layout *layout, u64 start_block,
			    struct save_layout_sizes *sls)
{}

static void initialize_layout(struct index_layout *layout, struct save_layout_sizes *sls)
{}

static int __must_check make_index_save_region_table(struct index_save_layout *isl,
						     struct region_table **table_ptr)
{}

static void encode_region_table(u8 *buffer, size_t *offset, struct region_table *table)
{}

static int __must_check write_index_save_header(struct index_save_layout *isl,
						struct region_table *table,
						struct buffered_writer *writer)
{}

static int write_index_save_layout(struct index_layout *layout,
				   struct index_save_layout *isl)
{}

static void reset_index_save_layout(struct index_save_layout *isl, u64 page_map_blocks)
{}

static int __must_check invalidate_old_save(struct index_layout *layout,
					    struct index_save_layout *isl)
{}

static int discard_index_state_data(struct index_layout *layout)
{}

static int __must_check make_layout_region_table(struct index_layout *layout,
						 struct region_table **table_ptr)
{}

static int __must_check write_layout_header(struct index_layout *layout,
					    struct region_table *table,
					    struct buffered_writer *writer)
{}

static int __must_check write_uds_index_config(struct index_layout *layout,
					       struct uds_configuration *config,
					       off_t offset)
{}

static int __must_check save_layout(struct index_layout *layout, off_t offset)
{}

static int create_index_layout(struct index_layout *layout, struct uds_configuration *config)
{}

static u64 generate_index_save_nonce(u64 volume_nonce, struct index_save_layout *isl)
{}

static u64 validate_index_save_layout(struct index_save_layout *isl, u64 volume_nonce)
{}

static int find_latest_uds_index_save_slot(struct index_layout *layout,
					   struct index_save_layout **isl_ptr)
{}

int uds_discard_open_chapter(struct index_layout *layout)
{}

int uds_load_index_state(struct index_layout *layout, struct uds_index *index)
{}

static struct index_save_layout *select_oldest_index_save_layout(struct index_layout *layout)
{}

static void instantiate_index_save_layout(struct index_save_layout *isl,
					  struct super_block_data *super,
					  u64 volume_nonce, unsigned int zone_count)
{}

static int setup_uds_index_save_slot(struct index_layout *layout,
				     unsigned int zone_count,
				     struct index_save_layout **isl_ptr)
{}

static void cancel_uds_index_save(struct index_save_layout *isl)
{}

int uds_save_index_state(struct index_layout *layout, struct uds_index *index)
{}

static int __must_check load_region_table(struct buffered_reader *reader,
					  struct region_table **table_ptr)
{}

static int __must_check read_super_block_data(struct buffered_reader *reader,
					      struct index_layout *layout,
					      size_t saved_size)
{}

static int __must_check verify_region(struct layout_region *lr, u64 start_block,
				      enum region_kind kind, unsigned int instance)
{}

static int __must_check verify_sub_index(struct index_layout *layout, u64 start_block,
					 struct region_table *table)
{}

static int __must_check reconstitute_layout(struct index_layout *layout,
					    struct region_table *table, u64 first_block)
{}

static int __must_check load_super_block(struct index_layout *layout, size_t block_size,
					 u64 first_block, struct buffered_reader *reader)
{}

static int __must_check read_index_save_data(struct buffered_reader *reader,
					     struct index_save_layout *isl,
					     size_t saved_size)
{}

static int __must_check reconstruct_index_save(struct index_save_layout *isl,
					       struct region_table *table)
{}

static int __must_check load_index_save(struct index_save_layout *isl,
					struct buffered_reader *reader,
					unsigned int instance)
{}

static int __must_check load_sub_index_regions(struct index_layout *layout)
{}

static int __must_check verify_uds_index_config(struct index_layout *layout,
						struct uds_configuration *config)
{}

static int load_index_layout(struct index_layout *layout, struct uds_configuration *config)
{}

static int create_layout_factory(struct index_layout *layout,
				 const struct uds_configuration *config)
{}

int uds_make_index_layout(struct uds_configuration *config, bool new_layout,
			  struct index_layout **layout_ptr)
{}

void uds_free_index_layout(struct index_layout *layout)
{}

int uds_replace_index_layout_storage(struct index_layout *layout,
				     struct block_device *bdev)
{}

/* Obtain a dm_bufio_client for the volume region. */
int uds_open_volume_bufio(struct index_layout *layout, size_t block_size,
			  unsigned int reserved_buffers,
			  struct dm_bufio_client **client_ptr)
{}

u64 uds_get_volume_nonce(struct index_layout *layout)
{}