Commit 766130e8 authored by Matthew Sakai's avatar Matthew Sakai Committed by Mike Snitzer

dm vdo: implement top-level deduplication index

The top-level deduplication index brings all the earlier components
together. The top-level index creates the separate zone structures that
enable the index to handle several requests in parallel, handles
dispatching requests to the right zones and components, and coordinates
metadata to ensure that it remain consistent. It also coordinates recovery
in the event of an unexpected index failure.

If sparse caching is enabled, the top-level index also handles the
coordination required by the sparse chapter index cache, which (unlike most
index structures) is shared among all zones.
Co-developed-by: default avatarJ. corwin Coburn <corwin@hurlbutnet.net>
Signed-off-by: default avatarJ. corwin Coburn <corwin@hurlbutnet.net>
Co-developed-by: default avatarMichael Sclafani <dm-devel@lists.linux.dev>
Signed-off-by: default avatarMichael Sclafani <dm-devel@lists.linux.dev>
Co-developed-by: default avatarThomas Jaskiewicz <tom@jaskiewicz.us>
Signed-off-by: default avatarThomas Jaskiewicz <tom@jaskiewicz.us>
Co-developed-by: default avatarBruce Johnston <bjohnsto@redhat.com>
Signed-off-by: default avatarBruce Johnston <bjohnsto@redhat.com>
Signed-off-by: default avatarMatthew Sakai <msakai@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
parent 4e7ff039
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2023 Red Hat
*/
#ifndef UDS_INDEX_H
#define UDS_INDEX_H
#include "index-layout.h"
#include "index-session.h"
#include "open-chapter.h"
#include "volume.h"
#include "volume-index.h"
/*
* The index is a high-level structure which represents the totality of the UDS index. It manages
* the queues for incoming requests and dispatches them to the appropriate sub-components like the
* volume or the volume index. It also manages administrative tasks such as saving and loading the
* index.
*
* The index is divided into a number of independent zones and assigns each request to a zone based
* on its name. Most sub-components are similarly divided into zones as well so that requests in
* each zone usually operate without interference or coordination between zones.
*/
typedef void (*index_callback_fn)(struct uds_request *request);
struct index_zone {
struct uds_index *index;
struct open_chapter_zone *open_chapter;
struct open_chapter_zone *writing_chapter;
u64 oldest_virtual_chapter;
u64 newest_virtual_chapter;
unsigned int id;
};
struct uds_index {
bool has_saved_open_chapter;
bool need_to_save;
struct index_load_context *load_context;
struct index_layout *layout;
struct volume_index *volume_index;
struct volume *volume;
unsigned int zone_count;
struct index_zone **zones;
u64 oldest_virtual_chapter;
u64 newest_virtual_chapter;
u64 last_save;
u64 prev_save;
struct chapter_writer *chapter_writer;
index_callback_fn callback;
struct uds_request_queue *triage_queue;
struct uds_request_queue *zone_queues[];
};
enum request_stage {
STAGE_TRIAGE,
STAGE_INDEX,
STAGE_MESSAGE,
};
int __must_check uds_make_index(struct configuration *config,
enum uds_open_index_type open_type,
struct index_load_context *load_context,
index_callback_fn callback, struct uds_index **new_index);
int __must_check uds_save_index(struct uds_index *index);
void uds_free_index(struct uds_index *index);
int __must_check uds_replace_index_storage(struct uds_index *index,
struct block_device *bdev);
void uds_get_index_stats(struct uds_index *index, struct uds_index_stats *counters);
void uds_enqueue_request(struct uds_request *request, enum request_stage stage);
void uds_wait_for_idle_index(struct uds_index *index);
#endif /* UDS_INDEX_H */
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2023 Red Hat
*/
#ifndef UDS_SPARSE_CACHE_H
#define UDS_SPARSE_CACHE_H
#include "geometry.h"
#include "uds.h"
/*
* The sparse cache is a cache of entire chapter indexes from sparse chapters used for searching
* for names after all other search paths have failed. It contains only complete chapter indexes;
* record pages from sparse chapters and single index pages used for resolving hooks are kept in
* the regular page cache in the volume.
*
* The most important property of this cache is the absence of synchronization for read operations.
* Safe concurrent access to the cache by the zone threads is controlled by the triage queue and
* the barrier requests it issues to the zone queues. The set of cached chapters does not and must
* not change between the carefully coordinated calls to uds_update_sparse_cache() from the zone
* threads. Outside of updates, every zone will get the same result when calling
* uds_sparse_cache_contains() as every other zone.
*/
struct index_zone;
struct sparse_cache;
int __must_check uds_make_sparse_cache(const struct geometry *geometry,
unsigned int capacity, unsigned int zone_count,
struct sparse_cache **cache_ptr);
void uds_free_sparse_cache(struct sparse_cache *cache);
bool uds_sparse_cache_contains(struct sparse_cache *cache, u64 virtual_chapter,
unsigned int zone_number);
int __must_check uds_update_sparse_cache(struct index_zone *zone, u64 virtual_chapter);
void uds_invalidate_sparse_cache(struct sparse_cache *cache);
int __must_check uds_search_sparse_cache(struct index_zone *zone,
const struct uds_record_name *name,
u64 *virtual_chapter_ptr, u16 *record_page_ptr);
#endif /* UDS_SPARSE_CACHE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment