mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
config: add support for comparing used config values with default ones
This commit is contained in:
parent
630e0af14e
commit
76ff38fa5c
@ -30,6 +30,8 @@
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
static const char *_config_source_names[] = {
|
||||
[CONFIG_UNDEFINED] = "undefined",
|
||||
@ -681,10 +683,84 @@ static int _config_def_check_node_single_value(struct cft_check_handle *handle,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _check_value_differs_from_default(struct cft_check_handle *handle,
|
||||
const struct dm_config_value *v,
|
||||
const cfg_def_item_t *def,
|
||||
struct dm_config_value *v_def)
|
||||
{
|
||||
struct dm_config_value *v_def_array, *v_def_iter;
|
||||
int diff = 0, id;
|
||||
int64_t i;
|
||||
float f;
|
||||
const char *str;
|
||||
|
||||
/* if default value is undefined, the value used differs from default */
|
||||
if (def->flags & CFG_DEFAULT_UNDEFINED) {
|
||||
diff = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!v_def && (def->type & CFG_TYPE_ARRAY)) {
|
||||
if (!(v_def_array = v_def_iter = _get_def_array_values(handle->cft, def)))
|
||||
return_0;
|
||||
do {
|
||||
/* iterate over each element of the array and check its value */
|
||||
if ((v->type != v_def_iter->type) ||
|
||||
_check_value_differs_from_default(handle, v, def, v_def_iter))
|
||||
break;
|
||||
v_def_iter = v_def_iter->next;
|
||||
v = v->next;
|
||||
} while (v_def_iter && v);
|
||||
diff = v || v_def_iter;
|
||||
dm_pool_free(handle->cft->mem, v_def_array);
|
||||
} else {
|
||||
switch (v->type) {
|
||||
case DM_CFG_INT:
|
||||
/* int value can be a real int but it can also represent bool */
|
||||
i = v_def ? v_def->v.i
|
||||
: def->type & CFG_TYPE_BOOL ?
|
||||
cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_BOOL, NULL) :
|
||||
cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_INT, NULL);
|
||||
diff = i != v->v.i;
|
||||
break;
|
||||
case DM_CFG_FLOAT:
|
||||
f = v_def ? v_def->v.f
|
||||
: cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_FLOAT, NULL);
|
||||
diff = fabs(f - v->v.f) < FLT_EPSILON;
|
||||
break;
|
||||
case DM_CFG_STRING:
|
||||
/* string value can be a real string but it can also represent bool */
|
||||
if (v_def ? v_def->type == DM_CFG_INT : def->type == CFG_TYPE_BOOL) {
|
||||
i = v_def ? v_def->v.i
|
||||
: cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_BOOL, NULL);
|
||||
diff = i != v->v.i;
|
||||
} else {
|
||||
str = v_def ? v_def->v.str
|
||||
: cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_STRING, NULL);
|
||||
diff = strcmp(str, v->v.str);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "inconsistent state reached in _check_value_differs_from_default");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (diff) {
|
||||
/* mark whole path from bottom to top with CFG_DIFF */
|
||||
for (id = def->id; id && !(handle->status[id] & CFG_DIFF); id = _cfg_def_items[id].parent)
|
||||
handle->status[id] |= CFG_DIFF;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int _config_def_check_node_value(struct cft_check_handle *handle,
|
||||
const char *rp, const struct dm_config_value *v,
|
||||
const cfg_def_item_t *def)
|
||||
{
|
||||
const struct dm_config_value *v_iter;
|
||||
|
||||
if (!v) {
|
||||
if (def->type != CFG_TYPE_SECTION) {
|
||||
_log_type_error(rp, CFG_TYPE_SECTION, def->type, handle->suppress_messages);
|
||||
@ -700,11 +776,15 @@ static int _config_def_check_node_value(struct cft_check_handle *handle,
|
||||
}
|
||||
}
|
||||
|
||||
v_iter = v;
|
||||
do {
|
||||
if (!_config_def_check_node_single_value(handle, rp, v, def))
|
||||
if (!_config_def_check_node_single_value(handle, rp, v_iter, def))
|
||||
return 0;
|
||||
v = v->next;
|
||||
} while (v);
|
||||
v_iter = v_iter->next;
|
||||
} while (v_iter);
|
||||
|
||||
if (handle->check_diff)
|
||||
_check_value_differs_from_default(handle, v, def, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -819,7 +899,7 @@ int config_def_check(struct cft_check_handle *handle)
|
||||
|
||||
/* Clear 'used' and 'valid' status flags. */
|
||||
for (id = 0; id < CFG_COUNT; id++)
|
||||
handle->status[id] &= ~(CFG_USED | CFG_VALID);
|
||||
handle->status[id] &= ~(CFG_USED | CFG_VALID | CFG_DIFF);
|
||||
|
||||
/*
|
||||
* Create a hash of all possible configuration
|
||||
|
@ -141,6 +141,8 @@ struct config_def_tree_spec {
|
||||
#define CFG_USED 0x01
|
||||
/* flag to mark the item as valid in a config tree instance during validation */
|
||||
#define CFG_VALID 0x02
|
||||
/* flag to mark the item as having the value different from default one */
|
||||
#define CFG_DIFF 0x04
|
||||
|
||||
/*
|
||||
* Register ID for each possible item in the configuration tree.
|
||||
@ -171,6 +173,7 @@ struct cft_check_handle {
|
||||
unsigned force_check:1; /* force check even if disabled by config/checks setting */
|
||||
unsigned skip_if_checked:1; /* skip the check if already done before - return last state */
|
||||
unsigned suppress_messages:1; /* suppress messages during the check if config item is found invalid */
|
||||
unsigned check_diff:1; /* check if the value used differs from default one */
|
||||
uint8_t status[CFG_COUNT]; /* flags for each configuration item - the result of the check */
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user