diff --git a/lib/config/config.c b/lib/config/config.c index 61e92cf65..26b2aa813 100644 --- a/lib/config/config.c +++ b/lib/config/config.c @@ -1336,8 +1336,10 @@ static struct dm_config_node *_add_def_node(struct dm_config_tree *cft, return cn; } -static int _should_skip_def_node(struct config_def_tree_spec *spec, int section_id, cfg_def_item_t *def) +static int _should_skip_def_node(struct config_def_tree_spec *spec, int section_id, int id) { + cfg_def_item_t *def = cfg_def_get_item_p(id); + if ((def->parent != section_id) || (spec->ignoreadvanced && def->flags & CFG_ADVANCED) || (spec->ignoreunsupported && def->flags & CFG_UNSUPPORTED)) @@ -1345,7 +1347,12 @@ static int _should_skip_def_node(struct config_def_tree_spec *spec, int section_ switch (spec->type) { case CFG_DEF_TREE_MISSING: - if ((def->flags & CFG_USED) || + if (!spec->check_status) { + log_error_once(INTERNAL_ERROR "couldn't determine missing " + "config nodes - unknown status of last config check."); + return 1; + } + if ((spec->check_status[id] & CFG_USED) || (def->flags & CFG_NAME_VARIABLE) || (def->since_version > spec->version)) return 1; @@ -1374,13 +1381,13 @@ static struct dm_config_node *_add_def_section_subtree(struct dm_config_tree *cf int id; for (id = 0; id < CFG_COUNT; id++) { - def = cfg_def_get_item_p(id); - if (_should_skip_def_node(spec, section_id, def)) + if (_should_skip_def_node(spec, section_id, id)) continue; if (!cn && !(cn = _add_def_node(cft, spec, parent, relay, cfg_def_get_item_p(section_id)))) goto bad; + def = cfg_def_get_item_p(id); if ((tmp = def->type == CFG_TYPE_SECTION ? _add_def_section_subtree(cft, spec, cn, relay_sub, id) : _add_def_node(cft, spec, cn, relay_sub, def))) relay_sub = tmp; diff --git a/lib/config/config.h b/lib/config/config.h index 5109a23f4..9f54af65e 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -110,6 +110,7 @@ struct config_def_tree_spec { uint16_t version; /* tree at this LVM2 version */ int ignoreadvanced; /* do not include advanced configs */ int ignoreunsupported; /* do not include unsupported configs */ + uint8_t *check_status; /* status of last tree check (currently needed for CFG_DEF_TREE_MISSING only) */ }; diff --git a/tools/dumpconfig.c b/tools/dumpconfig.c index ebee78629..3839defab 100644 --- a/tools/dumpconfig.c +++ b/tools/dumpconfig.c @@ -45,13 +45,30 @@ static struct cft_check_handle *_get_cft_check_handle(struct cmd_context *cmd) return handle; } +static int _do_def_check(struct cmd_context *cmd, struct cft_check_handle **cft_check_handle) +{ + struct cft_check_handle *handle; + + if (!(handle = _get_cft_check_handle(cmd))) + return 0; + + handle->force_check = 1; + handle->skip_if_checked = 1; + handle->suppress_messages = 1; + + config_def_check(cmd, handle); + *cft_check_handle = handle; + + return 1; +} + int dumpconfig(struct cmd_context *cmd, int argc, char **argv) { const char *file = arg_str_value(cmd, file_ARG, NULL); const char *type = arg_str_value(cmd, configtype_ARG, "current"); struct config_def_tree_spec tree_spec = {0}; struct dm_config_tree *cft = NULL; - struct cft_check_handle *cft_check_handle; + struct cft_check_handle *cft_check_handle = NULL; int r = ECMD_PROCESSED; if (arg_count(cmd, configtype_ARG) && arg_count(cmd, validate_ARG)) { @@ -105,29 +122,31 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv) if (!strcmp(type, "current")) { tree_spec.type = CFG_DEF_TREE_CURRENT; - - if (!(cft_check_handle = _get_cft_check_handle(cmd))) + if (!_do_def_check(cmd, &cft_check_handle)) return ECMD_FAILED; - - cft_check_handle->force_check = 1; - cft_check_handle->skip_if_checked = 1; - cft_check_handle->suppress_messages = 1; - - config_def_check(cmd, cft_check_handle); } - - else if (!strcmp(type, "default")) - tree_spec.type = CFG_DEF_TREE_DEFAULT; - else if (!strcmp(type, "missing")) + else if (!strcmp(type, "missing")) { tree_spec.type = CFG_DEF_TREE_MISSING; - else if (!strcmp(type, "new")) + if (!_do_def_check(cmd, &cft_check_handle)) + return ECMD_FAILED; + } + else if (!strcmp(type, "default")) { + tree_spec.type = CFG_DEF_TREE_DEFAULT; + /* default type does not require check status */ + } + else if (!strcmp(type, "new")) { tree_spec.type = CFG_DEF_TREE_NEW; + /* new type does not require check status */ + } else { log_error("Incorrect type of configuration specified. " "Expected one of: current, default, missing, new."); return EINVALID_CMD_LINE; } + if (cft_check_handle) + tree_spec.check_status = cft_check_handle->status; + if (tree_spec.type == CFG_DEF_TREE_CURRENT) cft = cmd->cft; else