mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 20:53:03 +02:00
dm vdo indexer: simplify sub-index parameter calculations
Pull the calculations from split_config() into compute_volume_sub_index_parameters(). For sparse indexes, this eliminates the duplication of both the configs and geometries in favor of merely having 2 sub_index_parameters structures. Also expand the sub_index_parameters structure to include the small number of fields its users rely on from both the config and the geometry. Signed-off-by: corwin <corwincoburn@google.com> Signed-off-by: Matthew Sakai <msakai@redhat.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
This commit is contained in:
parent
3a643cca41
commit
83a056da33
|
|
@ -60,6 +60,12 @@
|
|||
* the index.
|
||||
*/
|
||||
|
||||
enum sub_index_parameters_slot {
|
||||
DENSE = 0,
|
||||
HOOK = 0,
|
||||
NON_HOOK = 1,
|
||||
};
|
||||
|
||||
struct sub_index_parameters {
|
||||
/* The number of bits in address mask */
|
||||
u8 address_bits;
|
||||
|
|
@ -77,16 +83,10 @@ struct sub_index_parameters {
|
|||
size_t memory_size;
|
||||
/* The number of bytes the index should keep free at all times */
|
||||
size_t target_free_bytes;
|
||||
};
|
||||
|
||||
struct split_config {
|
||||
/* The hook subindex configuration */
|
||||
struct uds_configuration hook_config;
|
||||
struct index_geometry hook_geometry;
|
||||
|
||||
/* The non-hook subindex configuration */
|
||||
struct uds_configuration non_hook_config;
|
||||
struct index_geometry non_hook_geometry;
|
||||
/* The mean delta for the volume index */
|
||||
u32 volume_index_mean_delta;
|
||||
/* The number of threads used to process index requests */
|
||||
unsigned int zone_count;
|
||||
};
|
||||
|
||||
struct chapter_range {
|
||||
|
|
@ -196,8 +196,11 @@ unsigned int uds_get_volume_index_zone(const struct volume_index *volume_index,
|
|||
|
||||
#define DELTA_LIST_SIZE 256
|
||||
|
||||
static int compute_volume_sub_index_parameters(const struct uds_configuration *config,
|
||||
struct sub_index_parameters *params)
|
||||
static int compute_sub_index_parameters(const struct uds_configuration *config,
|
||||
u64 records_per_chapter,
|
||||
u32 chapters_per_volume,
|
||||
bool reduced,
|
||||
struct sub_index_parameters *params)
|
||||
{
|
||||
u64 entries_in_volume_index, address_span;
|
||||
u32 chapters_in_volume_index, invalid_chapters;
|
||||
|
|
@ -207,17 +210,15 @@ static int compute_volume_sub_index_parameters(const struct uds_configuration *c
|
|||
u64 index_size_in_bits;
|
||||
size_t expected_index_size;
|
||||
u64 min_delta_lists = MAX_ZONES * MAX_ZONES;
|
||||
struct index_geometry *geometry = config->geometry;
|
||||
u64 records_per_chapter = geometry->records_per_chapter;
|
||||
|
||||
params->chapter_count = geometry->chapters_per_volume;
|
||||
params->chapter_count = chapters_per_volume;
|
||||
/*
|
||||
* Make sure that the number of delta list records in the volume index does not change when
|
||||
* the volume is reduced by one chapter. This preserves the mapping from name to volume
|
||||
* index delta list.
|
||||
*/
|
||||
rounded_chapters = params->chapter_count;
|
||||
if (uds_is_reduced_index_geometry(geometry))
|
||||
if (reduced)
|
||||
rounded_chapters += 1;
|
||||
delta_list_records = records_per_chapter * rounded_chapters;
|
||||
address_count = config->volume_index_mean_delta * DELTA_LIST_SIZE;
|
||||
|
|
@ -274,9 +275,46 @@ static int compute_volume_sub_index_parameters(const struct uds_configuration *c
|
|||
params->memory_size = expected_index_size * 106 / 100;
|
||||
|
||||
params->target_free_bytes = expected_index_size / 20;
|
||||
params->volume_index_mean_delta = config->volume_index_mean_delta;
|
||||
params->zone_count = config->zone_count;
|
||||
return UDS_SUCCESS;
|
||||
}
|
||||
|
||||
static int compute_volume_sub_index_parameters(const struct uds_configuration *config,
|
||||
struct sub_index_parameters *params)
|
||||
{
|
||||
struct index_geometry *geometry = config->geometry;
|
||||
u64 sample_records;
|
||||
u64 dense_chapters;
|
||||
int result;
|
||||
bool reduced = uds_is_reduced_index_geometry(geometry);
|
||||
|
||||
if (!uds_is_sparse_index_geometry(config->geometry)) {
|
||||
return compute_sub_index_parameters(config,
|
||||
geometry->records_per_chapter,
|
||||
geometry->chapters_per_volume,
|
||||
reduced,
|
||||
¶ms[DENSE]);
|
||||
}
|
||||
|
||||
dense_chapters = geometry->chapters_per_volume - geometry->sparse_chapters_per_volume;
|
||||
sample_records = geometry->records_per_chapter / config->sparse_sample_rate;
|
||||
|
||||
result = compute_sub_index_parameters(config,
|
||||
sample_records,
|
||||
geometry->chapters_per_volume,
|
||||
reduced,
|
||||
¶ms[HOOK]);
|
||||
if (result != UDS_SUCCESS)
|
||||
return result;
|
||||
|
||||
return compute_sub_index_parameters(config,
|
||||
geometry->records_per_chapter - sample_records,
|
||||
dense_chapters,
|
||||
reduced,
|
||||
¶ms[NON_HOOK]);
|
||||
}
|
||||
|
||||
static void uninitialize_volume_sub_index(struct volume_sub_index *sub_index)
|
||||
{
|
||||
vdo_free(vdo_forget(sub_index->flush_chapters));
|
||||
|
|
@ -298,73 +336,32 @@ void uds_free_volume_index(struct volume_index *volume_index)
|
|||
}
|
||||
|
||||
|
||||
static int compute_volume_sub_index_save_bytes(const struct uds_configuration *config,
|
||||
size_t *bytes)
|
||||
static size_t compute_volume_sub_index_save_bytes(struct sub_index_parameters *params)
|
||||
{
|
||||
struct sub_index_parameters params = { .address_bits = 0 };
|
||||
int result;
|
||||
|
||||
result = compute_volume_sub_index_parameters(config, ¶ms);
|
||||
if (result != UDS_SUCCESS)
|
||||
return result;
|
||||
|
||||
*bytes = (sizeof(struct sub_index_data) + params.list_count * sizeof(u64) +
|
||||
uds_compute_delta_index_save_bytes(params.list_count,
|
||||
params.memory_size));
|
||||
return UDS_SUCCESS;
|
||||
}
|
||||
|
||||
/* This function is only useful if the configuration includes sparse chapters. */
|
||||
static void split_configuration(const struct uds_configuration *config,
|
||||
struct split_config *split)
|
||||
{
|
||||
u64 sample_rate, sample_records;
|
||||
u64 dense_chapters, sparse_chapters;
|
||||
|
||||
/* Start with copies of the base configuration. */
|
||||
split->hook_config = *config;
|
||||
split->hook_geometry = *config->geometry;
|
||||
split->hook_config.geometry = &split->hook_geometry;
|
||||
split->non_hook_config = *config;
|
||||
split->non_hook_geometry = *config->geometry;
|
||||
split->non_hook_config.geometry = &split->non_hook_geometry;
|
||||
|
||||
sample_rate = config->sparse_sample_rate;
|
||||
sparse_chapters = config->geometry->sparse_chapters_per_volume;
|
||||
dense_chapters = config->geometry->chapters_per_volume - sparse_chapters;
|
||||
sample_records = config->geometry->records_per_chapter / sample_rate;
|
||||
|
||||
/* Adjust the number of records indexed for each chapter. */
|
||||
split->hook_geometry.records_per_chapter = sample_records;
|
||||
split->non_hook_geometry.records_per_chapter -= sample_records;
|
||||
|
||||
/* Adjust the number of chapters indexed. */
|
||||
split->hook_geometry.sparse_chapters_per_volume = 0;
|
||||
split->non_hook_geometry.sparse_chapters_per_volume = 0;
|
||||
split->non_hook_geometry.chapters_per_volume = dense_chapters;
|
||||
return (sizeof(struct sub_index_data) + params->list_count * sizeof(u64) +
|
||||
uds_compute_delta_index_save_bytes(params->list_count,
|
||||
params->memory_size));
|
||||
}
|
||||
|
||||
static int compute_volume_index_save_bytes(const struct uds_configuration *config,
|
||||
size_t *bytes)
|
||||
{
|
||||
size_t hook_bytes, non_hook_bytes;
|
||||
struct split_config split;
|
||||
int result;
|
||||
struct sub_index_parameters parameters[2] = {
|
||||
{ .address_bits = 0 },
|
||||
{ .address_bits = 0 },
|
||||
};
|
||||
|
||||
if (!uds_is_sparse_index_geometry(config->geometry))
|
||||
return compute_volume_sub_index_save_bytes(config, bytes);
|
||||
|
||||
split_configuration(config, &split);
|
||||
result = compute_volume_sub_index_save_bytes(&split.hook_config, &hook_bytes);
|
||||
result = compute_volume_sub_index_parameters(config, parameters);
|
||||
if (result != UDS_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = compute_volume_sub_index_save_bytes(&split.non_hook_config,
|
||||
&non_hook_bytes);
|
||||
if (result != UDS_SUCCESS)
|
||||
return result;
|
||||
*bytes = compute_volume_sub_index_save_bytes(¶meters[HOOK]);
|
||||
if (uds_is_sparse_index_geometry(config->geometry)) {
|
||||
*bytes += compute_volume_sub_index_save_bytes(¶meters[NON_HOOK]);
|
||||
*bytes += sizeof(struct volume_index_data);
|
||||
}
|
||||
|
||||
*bytes = sizeof(struct volume_index_data) + hook_bytes + non_hook_bytes;
|
||||
return UDS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1170,48 +1167,43 @@ void uds_get_volume_index_stats(const struct volume_index *volume_index,
|
|||
stats->early_flushes += sparse_stats.early_flushes;
|
||||
}
|
||||
|
||||
static int initialize_volume_sub_index(const struct uds_configuration *config,
|
||||
static int initialize_volume_sub_index(struct sub_index_parameters *params,
|
||||
u64 volume_nonce, u8 tag,
|
||||
struct volume_sub_index *sub_index)
|
||||
{
|
||||
struct sub_index_parameters params = { .address_bits = 0 };
|
||||
unsigned int zone_count = config->zone_count;
|
||||
unsigned int zone_count = params->zone_count;
|
||||
u64 available_bytes = 0;
|
||||
unsigned int z;
|
||||
int result;
|
||||
|
||||
result = compute_volume_sub_index_parameters(config, ¶ms);
|
||||
if (result != UDS_SUCCESS)
|
||||
return result;
|
||||
|
||||
sub_index->address_bits = params.address_bits;
|
||||
sub_index->address_mask = (1u << params.address_bits) - 1;
|
||||
sub_index->chapter_bits = params.chapter_bits;
|
||||
sub_index->chapter_mask = (1u << params.chapter_bits) - 1;
|
||||
sub_index->chapter_count = params.chapter_count;
|
||||
sub_index->list_count = params.list_count;
|
||||
sub_index->address_bits = params->address_bits;
|
||||
sub_index->address_mask = (1u << params->address_bits) - 1;
|
||||
sub_index->chapter_bits = params->chapter_bits;
|
||||
sub_index->chapter_mask = (1u << params->chapter_bits) - 1;
|
||||
sub_index->chapter_count = params->chapter_count;
|
||||
sub_index->list_count = params->list_count;
|
||||
sub_index->zone_count = zone_count;
|
||||
sub_index->chapter_zone_bits = params.chapter_size_in_bits / zone_count;
|
||||
sub_index->chapter_zone_bits = params->chapter_size_in_bits / zone_count;
|
||||
sub_index->volume_nonce = volume_nonce;
|
||||
|
||||
result = uds_initialize_delta_index(&sub_index->delta_index, zone_count,
|
||||
params.list_count, params.mean_delta,
|
||||
params.chapter_bits, params.memory_size,
|
||||
params->list_count, params->mean_delta,
|
||||
params->chapter_bits, params->memory_size,
|
||||
tag);
|
||||
if (result != UDS_SUCCESS)
|
||||
return result;
|
||||
|
||||
for (z = 0; z < sub_index->delta_index.zone_count; z++)
|
||||
available_bytes += sub_index->delta_index.delta_zones[z].size;
|
||||
available_bytes -= params.target_free_bytes;
|
||||
available_bytes -= params->target_free_bytes;
|
||||
sub_index->max_zone_bits = (available_bytes * BITS_PER_BYTE) / zone_count;
|
||||
sub_index->memory_size = (sub_index->delta_index.memory_size +
|
||||
sizeof(struct volume_sub_index) +
|
||||
(params.list_count * sizeof(u64)) +
|
||||
(params->list_count * sizeof(u64)) +
|
||||
(zone_count * sizeof(struct volume_sub_index_zone)));
|
||||
|
||||
/* The following arrays are initialized to all zeros. */
|
||||
result = vdo_allocate(params.list_count, "first chapter to flush",
|
||||
result = vdo_allocate(params->list_count, "first chapter to flush",
|
||||
&sub_index->flush_chapters);
|
||||
if (result != VDO_SUCCESS)
|
||||
return result;
|
||||
|
|
@ -1222,10 +1214,13 @@ static int initialize_volume_sub_index(const struct uds_configuration *config,
|
|||
int uds_make_volume_index(const struct uds_configuration *config, u64 volume_nonce,
|
||||
struct volume_index **volume_index_ptr)
|
||||
{
|
||||
struct split_config split;
|
||||
unsigned int zone;
|
||||
struct volume_index *volume_index;
|
||||
int result;
|
||||
struct sub_index_parameters parameters[2] = {
|
||||
{ .address_bits = 0 },
|
||||
{ .address_bits = 0 },
|
||||
};
|
||||
|
||||
result = vdo_allocate(1, "volume index", &volume_index);
|
||||
if (result != VDO_SUCCESS)
|
||||
|
|
@ -1233,8 +1228,12 @@ int uds_make_volume_index(const struct uds_configuration *config, u64 volume_non
|
|||
|
||||
volume_index->zone_count = config->zone_count;
|
||||
|
||||
result = compute_volume_sub_index_parameters(config, parameters);
|
||||
if (result != UDS_SUCCESS)
|
||||
return result;
|
||||
|
||||
if (!uds_is_sparse_index_geometry(config->geometry)) {
|
||||
result = initialize_volume_sub_index(config, volume_nonce, 'm',
|
||||
result = initialize_volume_sub_index(¶meters[DENSE], volume_nonce, 'm',
|
||||
&volume_index->vi_non_hook);
|
||||
if (result != UDS_SUCCESS) {
|
||||
uds_free_volume_index(volume_index);
|
||||
|
|
@ -1257,8 +1256,7 @@ int uds_make_volume_index(const struct uds_configuration *config, u64 volume_non
|
|||
for (zone = 0; zone < config->zone_count; zone++)
|
||||
mutex_init(&volume_index->zones[zone].hook_mutex);
|
||||
|
||||
split_configuration(config, &split);
|
||||
result = initialize_volume_sub_index(&split.non_hook_config, volume_nonce, 'd',
|
||||
result = initialize_volume_sub_index(¶meters[NON_HOOK], volume_nonce, 'd',
|
||||
&volume_index->vi_non_hook);
|
||||
if (result != UDS_SUCCESS) {
|
||||
uds_free_volume_index(volume_index);
|
||||
|
|
@ -1266,7 +1264,7 @@ int uds_make_volume_index(const struct uds_configuration *config, u64 volume_non
|
|||
"Error creating non hook volume index");
|
||||
}
|
||||
|
||||
result = initialize_volume_sub_index(&split.hook_config, volume_nonce, 's',
|
||||
result = initialize_volume_sub_index(¶meters[HOOK], volume_nonce, 's',
|
||||
&volume_index->vi_hook);
|
||||
if (result != UDS_SUCCESS) {
|
||||
uds_free_volume_index(volume_index);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user