1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

text_import: introduce text_import_values

When reading values out of tree node, we can look for them with
help of binary search.

For this bsearch functionality however config values must be
alphabetically sorted!

However overal this patch is not giving major speedup as we are
actually going through config_node many times to extract individual
pieces.
This commit is contained in:
Zdenek Kabelac 2024-10-14 23:16:01 +02:00
parent a953fd9968
commit 785572fb65
4 changed files with 174 additions and 10 deletions

View File

@ -375,7 +375,7 @@ static int _read_segment(struct cmd_context *cmd,
uint32_t area_count = 0u;
struct lv_segment *seg;
const struct dm_config_node *sn_child = sn->child;
const struct dm_config_value *cv;
const struct dm_config_value *cv = NULL;
uint32_t area_extents, start_extent, extent_count, reshape_count, data_copies;
struct segment_type *segtype;
const char *segtype_str;
@ -385,7 +385,7 @@ static int _read_segment(struct cmd_context *cmd,
log_error("Empty segment section.");
return 0;
}
#if 0
if (!_read_int32(sn_child, "start_extent", &start_extent)) {
log_error("Couldn't read 'start_extent' for segment '%s' "
"of logical volume %s.", sn->key, lv->name);
@ -423,6 +423,41 @@ static int _read_segment(struct cmd_context *cmd,
return 0;
}
/* Optional tags */
dm_config_get_list(sn_child, "tags", &cv);
#else
segtype_str = SEG_TYPE_NAME_STRIPED;
reshape_count = 0;
data_copies = 1;
struct config_values v[] = {
{ "data_copies", CONFIG_VALUE_UINT32, &data_copies },
{ "extent_count", CONFIG_VALUE_UINT32, &extent_count, 1 },
{ "reshape_count", CONFIG_VALUE_UINT32, &reshape_count },
{ "start_extent", CONFIG_VALUE_UINT32, &start_extent, 1 },
{ "tags", CONFIG_VALUE_LIST, &cv },
{ "type", CONFIG_VALUE_STRING, &segtype_str },
};
if (!text_import_values(sn_child, DM_ARRAY_SIZE(v), v)) {
log_error("Could not read segment values for %s.",
display_lvname(lv));
return 0;
}
/* Locally duplicate to parse out status flag bits */
if (!(segtype_with_flags = dm_pool_strdup(mem, segtype_str))) {
log_error("Cannot duplicate segtype string.");
return 0;
}
if (!read_segtype_lvflags(&lv->status, segtype_with_flags)) {
log_error("Couldn't read segtype for logical volume %s.",
display_lvname(lv));
return 0;
}
#endif
if (!(segtype = get_segtype_from_string(cmd, segtype_with_flags)))
return_0;
@ -447,13 +482,11 @@ static int _read_segment(struct cmd_context *cmd,
return_0;
/* Optional tags */
if (dm_config_get_list(sn_child, "tags", &cv) &&
!(_read_str_list(mem, &seg->tags, cv))) {
if (cv && !(_read_str_list(mem, &seg->tags, cv))) {
log_error("Couldn't read tags for a segment of %s/%s.",
lv->vg->name, lv->name);
return 0;
}
/*
* Insert into correct part of segment list.
*/
@ -540,6 +573,60 @@ int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
return 1;
}
static int _compare_config_values_s(const void *a, const void *b)
{
return strcmp(((const struct config_values*)a)->path,
((const struct config_values*)b)->path);
}
/*
* Read set of values out of config tree nodes
*
* config_values are expected to be in Alphabetic order for use with bsearch!!
*/
int text_import_values(const struct dm_config_node *cn,
size_t values_count, struct config_values *values)
{
struct config_values *found;
unsigned i;
while (cn) {
struct config_values findme = { .path = cn->key };
found = bsearch(&findme, values, values_count,
sizeof(struct config_values),
_compare_config_values_s);
if (found) {
switch (found->type) {
case CONFIG_VALUE_STRING:
*(const char**)(found->result) = cn->v->v.str;
break;
case CONFIG_VALUE_UINT64:
*(uint64_t*)(found->result) = (uint64_t)cn->v->v.i;
break;
case CONFIG_VALUE_UINT32:
*(uint32_t*)(found->result) = (uint32_t)cn->v->v.i;
break;
case CONFIG_VALUE_LIST:
*(struct dm_config_value**)(found->result) = cn->v;
break;
}
--(found->mandatory);
}
cn = cn->sib;
}
for (i = 0 ; i < values_count; ++i)
if (values[i].mandatory > 0) {
log_error("Required option %s is missing!", values[i].path);
return 0;
}
return 1;
}
static int _read_segments(struct cmd_context *cmd,
struct format_type *fmt,
struct format_instance *fid,

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2024 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@ -25,4 +25,21 @@ struct dm_config_node;
int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
const struct dm_config_value *cv, uint64_t status);
typedef enum {
CONFIG_VALUE_STRING,
CONFIG_VALUE_UINT64,
CONFIG_VALUE_UINT32,
CONFIG_VALUE_LIST,
} config_value_t;
struct config_values {
const char *path; /* option name/path to look for */
config_value_t type; /* type of resulting value */
void *result; /* where to place resulting value of given type */
int mandatory; /* If this path is missing in config node, import fails */
};
int text_import_values(const struct dm_config_node *cn,
size_t values_count, struct config_values *values);
#endif

View File

@ -72,7 +72,28 @@ static int _striped_text_import_area_count(const struct dm_config_node *sn, uint
static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn)
{
const struct dm_config_value *cv;
#if 1
uint32_t stripe_size = 0;
struct config_values v[] = {
{ "stripe_size", CONFIG_VALUE_UINT32, &stripe_size },
{ "stripes", CONFIG_VALUE_LIST, &cv },
};
if (!text_import_values(sn, DM_ARRAY_SIZE(v), v)) {
log_error("Could not read segment values for");
return 0;
}
if (seg->area_count != 1) {
if (!stripe_size) {
log_error("Couldn't read stripe_size for segment %s "
"of logical volume %s.", dm_config_parent_name(sn), seg->lv->name);
return 0;
}
seg->stripe_size = stripe_size;
}
#else
if ((seg->area_count != 1) &&
!dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) {
log_error("Couldn't read stripe_size for segment %s "
@ -85,6 +106,7 @@ static int _striped_text_import(struct lv_segment *seg, const struct dm_config_n
"of logical volume %s.", dm_config_parent_name(sn), seg->lv->name);
return 0;
}
#endif
seg->area_len /= seg->area_count;

View File

@ -21,6 +21,7 @@
#include "lib/config/config.h"
#include "lib/activate/activate.h"
#include "lib/datastruct/str_list.h"
#include "lib/format_text/text_import.h"
/* Dm kernel module name for thin provisioning */
static const char _thin_pool_module[] = "thin-pool";
@ -468,9 +469,46 @@ static void _thin_display(const struct lv_segment *seg)
static int _thin_text_import(struct lv_segment *seg,
const struct dm_config_node *sn)
{
const char *lv_name;
struct logical_volume *pool_lv, *origin = NULL, *external_lv = NULL, *merge_lv = NULL;
const char *pool_name = NULL, *origin_name = NULL, *external_name = NULL, *merge_name = NULL;
struct logical_volume *pool_lv, *origin_lv = NULL, *external_lv = NULL, *merge_lv = NULL;
struct generic_logical_volume *indirect_origin = NULL;
int64_t transaction_id = -1, device_id = -1;
struct config_values v[] = {
{ "device_id", CONFIG_VALUE_UINT64, &device_id, 1 },
{ "external_origin", CONFIG_VALUE_STRING, &external_name },
{ "merge", CONFIG_VALUE_STRING, &merge_name },
{ "origin", CONFIG_VALUE_STRING, &origin_name },
{ "thin_pool", CONFIG_VALUE_STRING, &pool_name, 1 },
{ "transaction_id", CONFIG_VALUE_UINT64, &transaction_id, 1 },
};
if (!text_import_values(sn, DM_ARRAY_SIZE(v), v))
return SEG_LOG_ERROR("Could not read segment values for");
seg->transaction_id = (uint64_t)transaction_id;
seg->device_id = (uint64_t)device_id;
if (seg->device_id > DM_THIN_MAX_DEVICE_ID)
return SEG_LOG_ERROR("Unsupported value %u for device_id",
seg->device_id);
if (!pool_name)
return SEG_LOG_ERROR("Thin pool must be a string in");
if (!(pool_lv = find_lv(seg->lv->vg, pool_name)))
return SEG_LOG_ERROR("Unknown thin pool %s in", pool_name);
if (origin_name &&
!(origin_lv = find_lv(seg->lv->vg, origin_name)))
return SEG_LOG_ERROR("Unknown origin %s in", origin_name);
if (merge_name &&
!(merge_lv = find_lv(seg->lv->vg, merge_name)))
return SEG_LOG_ERROR("Unknown merge lv %s in", merge_name);
if (external_name &&
!(external_lv = find_lv(seg->lv->vg, external_name)))
return SEG_LOG_ERROR("Unknown external origin %s in", external_name);
#if 0
if (!dm_config_get_str(sn, "thin_pool", &lv_name))
return SEG_LOG_ERROR("Thin pool must be a string in");
@ -510,8 +548,8 @@ static int _thin_text_import(struct lv_segment *seg,
if (!(external_lv = find_lv(seg->lv->vg, lv_name)))
return SEG_LOG_ERROR("Unknown external origin %s in", lv_name);
}
if (!attach_pool_lv(seg, pool_lv, origin, indirect_origin, merge_lv))
#endif
if (!attach_pool_lv(seg, pool_lv, origin_lv, indirect_origin, merge_lv))
return_0;
if (!attach_thin_external_origin(seg, external_lv))