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

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

#ifndef INDEXER_H
#define INDEXER_H

#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/wait.h>

#include "funnel-queue.h"

/*
 * UDS public API
 *
 * The Universal Deduplication System (UDS) is an efficient name-value store. When used for
 * deduplicating storage, the names are generally hashes of data blocks and the associated data is
 * where that block is located on the underlying storage medium. The stored names are expected to
 * be randomly distributed among the space of possible names. If this assumption is violated, the
 * UDS index will store fewer names than normal but will otherwise continue to work. The data
 * associated with each name can be any 16-byte value.
 *
 * A client must first create an index session to interact with an index. Once created, the session
 * can be shared among multiple threads or users. When a session is destroyed, it will also close
 * and save any associated index.
 *
 * To make a request, a client must allocate a uds_request structure and set the required fields
 * before launching it. UDS will invoke the provided callback to complete the request. After the
 * callback has been called, the uds_request structure can be freed or reused for a new request.
 * There are five types of requests:
 *
 * A UDS_UPDATE request will associate the provided name with the provided data. Any previous data
 * associated with that name will be discarded.
 *
 * A UDS_QUERY request will return the data associated with the provided name, if any. The entry
 * for the name will also be marked as most recent, as if the data had been updated.
 *
 * A UDS_POST request is a combination of UDS_QUERY and UDS_UPDATE. If there is already data
 * associated with the provided name, that data is returned. If there is no existing association,
 * the name is associated with the newly provided data. This request is equivalent to a UDS_QUERY
 * request followed by a UDS_UPDATE request if no data is found, but it is much more efficient.
 *
 * A UDS_QUERY_NO_UPDATE request will return the data associated with the provided name, but will
 * not change the recency of the entry for the name. This request is primarily useful for testing,
 * to determine whether an entry exists without changing the internal state of the index.
 *
 * A UDS_DELETE request removes any data associated with the provided name. This operation is
 * generally not necessary, because the index will automatically discard its oldest entries once it
 * becomes full.
 */

/* General UDS constants and structures */

enum uds_request_type {};

enum uds_open_index_type {};

enum {};

/*
 * A type representing a UDS memory configuration which is either a positive integer number of
 * gigabytes or one of the six special constants for configurations smaller than one gigabyte.
 */
uds_memory_config_size_t;

enum {};

struct uds_record_name {};

struct uds_record_data {};

struct uds_volume_record {};

struct uds_parameters {};

/*
 * These statistics capture characteristics of the current index, including resource usage and
 * requests processed since the index was opened.
 */
struct uds_index_stats {};

enum uds_index_region {} __packed;

/* Zone message requests are used to communicate between index zones. */
enum uds_zone_message_type {} __packed;

struct uds_zone_message {};

struct uds_index_session;
struct uds_index;
struct uds_request;

/* Once this callback has been invoked, the uds_request structure can be reused or freed. */
uds_request_callback_fn;

struct uds_request {};

/* Compute the number of bytes needed to store an index. */
int __must_check uds_compute_index_size(const struct uds_parameters *parameters,
					u64 *index_size);

/* A session is required for most index operations. */
int __must_check uds_create_index_session(struct uds_index_session **session);

/* Destroying an index session also closes and saves the associated index. */
int uds_destroy_index_session(struct uds_index_session *session);

/*
 * Create or open an index with an existing session. This operation fails if the index session is
 * suspended, or if there is already an open index.
 */
int __must_check uds_open_index(enum uds_open_index_type open_type,
				const struct uds_parameters *parameters,
				struct uds_index_session *session);

/*
 * Wait until all callbacks for index operations are complete, and prevent new index operations
 * from starting. New index operations will fail with EBUSY until the session is resumed. Also
 * optionally saves the index.
 */
int __must_check uds_suspend_index_session(struct uds_index_session *session, bool save);

/*
 * Allow new index operations for an index, whether it was suspended or not. If the index is
 * suspended and the supplied block device differs from the current backing store, the index will
 * start using the new backing store instead.
 */
int __must_check uds_resume_index_session(struct uds_index_session *session,
					  struct block_device *bdev);

/* Wait until all outstanding index operations are complete. */
int __must_check uds_flush_index_session(struct uds_index_session *session);

/* Close an index. This operation fails if the index session is suspended. */
int __must_check uds_close_index(struct uds_index_session *session);

/* Get index statistics since the last time the index was opened. */
int __must_check uds_get_index_session_stats(struct uds_index_session *session,
					     struct uds_index_stats *stats);

/* This function will fail if any required field of the request is not set. */
int __must_check uds_launch_request(struct uds_request *request);

struct cond_var {};

static inline void uds_init_cond(struct cond_var *cv)
{}

static inline void uds_signal_cond(struct cond_var *cv)
{}

static inline void uds_broadcast_cond(struct cond_var *cv)
{}

void uds_wait_cond(struct cond_var *cv, struct mutex *mutex);

#endif /* INDEXER_H */