linux/drivers/md/dm-vdo/indexer/volume-index.h

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

#ifndef UDS_VOLUME_INDEX_H
#define UDS_VOLUME_INDEX_H

#include <linux/limits.h>

#include "thread-utils.h"

#include "config.h"
#include "delta-index.h"
#include "indexer.h"

/*
 * The volume index is the primary top-level index for UDS. It contains records which map a record
 * name to the chapter where a record with that name is stored. This mapping can definitively say
 * when no record exists. However, because we only use a subset of the name for this index, it
 * cannot definitively say that a record for the entry does exist. It can only say that if a record
 * exists, it will be in a particular chapter. The request can then be dispatched to that chapter
 * for further processing.
 *
 * If the volume_index_record does not actually match the record name, the index can store a more
 * specific collision record to disambiguate the new entry from the existing one. Index entries are
 * managed with volume_index_record structures.
 */

#define NO_CHAPTER

struct volume_index_stats {};

struct volume_sub_index_zone {} __aligned();

struct volume_sub_index {};

struct volume_index_zone {} __aligned();

struct volume_index {};

/*
 * The volume_index_record structure is used to facilitate processing of a record name. A client
 * first calls uds_get_volume_index_record() to find the volume index record for a record name. The
 * fields of the record can then be examined to determine the state of the record.
 *
 * If is_found is false, then the index did not find an entry for the record name. Calling
 * uds_put_volume_index_record() will insert a new entry for that name at the proper place.
 *
 * If is_found is true, then we did find an entry for the record name, and the virtual_chapter and
 * is_collision fields reflect the entry found. Subsequently, a call to
 * uds_remove_volume_index_record() will remove the entry, a call to
 * uds_set_volume_index_record_chapter() will update the existing entry, and a call to
 * uds_put_volume_index_record() will insert a new collision record after the existing entry.
 */
struct volume_index_record {};

int __must_check uds_make_volume_index(const struct uds_configuration *config,
				       u64 volume_nonce,
				       struct volume_index **volume_index);

void uds_free_volume_index(struct volume_index *volume_index);

int __must_check uds_compute_volume_index_save_blocks(const struct uds_configuration *config,
						      size_t block_size,
						      u64 *block_count);

unsigned int __must_check uds_get_volume_index_zone(const struct volume_index *volume_index,
						    const struct uds_record_name *name);

bool __must_check uds_is_volume_index_sample(const struct volume_index *volume_index,
					     const struct uds_record_name *name);

/*
 * This function is only used to manage sparse cache membership. Most requests should use
 * uds_get_volume_index_record() to look up index records instead.
 */
u64 __must_check uds_lookup_volume_index_name(const struct volume_index *volume_index,
					      const struct uds_record_name *name);

int __must_check uds_get_volume_index_record(struct volume_index *volume_index,
					     const struct uds_record_name *name,
					     struct volume_index_record *record);

int __must_check uds_put_volume_index_record(struct volume_index_record *record,
					     u64 virtual_chapter);

int __must_check uds_remove_volume_index_record(struct volume_index_record *record);

int __must_check uds_set_volume_index_record_chapter(struct volume_index_record *record,
						     u64 virtual_chapter);

void uds_set_volume_index_open_chapter(struct volume_index *volume_index,
				       u64 virtual_chapter);

void uds_set_volume_index_zone_open_chapter(struct volume_index *volume_index,
					    unsigned int zone_number,
					    u64 virtual_chapter);

int __must_check uds_load_volume_index(struct volume_index *volume_index,
				       struct buffered_reader **readers,
				       unsigned int reader_count);

int __must_check uds_save_volume_index(struct volume_index *volume_index,
				       struct buffered_writer **writers,
				       unsigned int writer_count);

void uds_get_volume_index_stats(const struct volume_index *volume_index,
				struct volume_index_stats *stats);

#endif /* UDS_VOLUME_INDEX_H */