#ifndef UDS_VOLUME_H
#define UDS_VOLUME_H
#include <linux/atomic.h>
#include <linux/cache.h>
#include <linux/dm-bufio.h>
#include <linux/limits.h>
#include "permassert.h"
#include "thread-utils.h"
#include "chapter-index.h"
#include "config.h"
#include "geometry.h"
#include "indexer.h"
#include "index-layout.h"
#include "index-page-map.h"
#include "radix-sort.h"
#include "sparse-cache.h"
enum index_lookup_mode {
LOOKUP_NORMAL,
LOOKUP_FOR_REBUILD,
};
struct queued_read {
bool invalid;
bool reserved;
u32 physical_page;
struct uds_request *first_request;
struct uds_request *last_request;
};
struct __aligned(L1_CACHE_BYTES) search_pending_counter {
u64 atomic_value;
};
struct cached_page {
bool read_pending;
u32 physical_page;
s64 last_used;
struct dm_buffer *buffer;
struct delta_index_page index_page;
};
struct page_cache {
unsigned int zone_count;
u32 indexable_pages;
u16 cache_slots;
u16 *index;
struct cached_page *cache;
struct search_pending_counter *search_pending_counters;
struct queued_read *read_queue;
u16 read_queue_first;
u16 read_queue_next_read;
u16 read_queue_last;
atomic64_t clock;
};
struct volume {
struct index_geometry *geometry;
struct dm_bufio_client *client;
u64 nonce;
size_t cache_size;
const struct uds_volume_record **record_pointers;
struct radix_sorter *radix_sorter;
struct sparse_cache *sparse_cache;
struct page_cache page_cache;
struct index_page_map *index_page_map;
struct mutex read_threads_mutex;
struct cond_var read_threads_cond;
struct cond_var read_threads_read_done_cond;
struct thread **reader_threads;
unsigned int read_thread_count;
bool read_threads_exiting;
enum index_lookup_mode lookup_mode;
unsigned int reserved_buffers;
};
int __must_check uds_make_volume(const struct uds_configuration *config,
struct index_layout *layout,
struct volume **new_volume);
void uds_free_volume(struct volume *volume);
int __must_check uds_replace_volume_storage(struct volume *volume,
struct index_layout *layout,
struct block_device *bdev);
int __must_check uds_find_volume_chapter_boundaries(struct volume *volume,
u64 *lowest_vcn, u64 *highest_vcn,
bool *is_empty);
int __must_check uds_search_volume_page_cache(struct volume *volume,
struct uds_request *request,
bool *found);
int __must_check uds_search_volume_page_cache_for_rebuild(struct volume *volume,
const struct uds_record_name *name,
u64 virtual_chapter,
bool *found);
int __must_check uds_search_cached_record_page(struct volume *volume,
struct uds_request *request, u32 chapter,
u16 record_page_number, bool *found);
void uds_forget_chapter(struct volume *volume, u64 chapter);
int __must_check uds_write_chapter(struct volume *volume,
struct open_chapter_index *chapter_index,
const struct uds_volume_record records[]);
void uds_prefetch_volume_chapter(const struct volume *volume, u32 chapter);
int __must_check uds_read_chapter_index_from_volume(const struct volume *volume,
u64 virtual_chapter,
struct dm_buffer *volume_buffers[],
struct delta_index_page index_pages[]);
int __must_check uds_get_volume_record_page(struct volume *volume, u32 chapter,
u32 page_number, u8 **data_ptr);
int __must_check uds_get_volume_index_page(struct volume *volume, u32 chapter,
u32 page_number,
struct delta_index_page **page_ptr);
#endif