All of lore.kernel.org
 help / color / mirror / Atom feed
* master - config: make it possible to run several instances of configuration check at once
@ 2013-07-02 13:32 Peter Rajnoha
  0 siblings, 0 replies; only message in thread
From: Peter Rajnoha @ 2013-07-02 13:32 UTC (permalink / raw)
  To: lvm-devel

Gitweb:        http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f1c292cc38f4ba2e8d9b7272bc1a1ce17bd729a5
Commit:        f1c292cc38f4ba2e8d9b7272bc1a1ce17bd729a5
Parent:        8769033e078c79ee4167c5186d7407d1729fd8a4
Author:        Peter Rajnoha <prajnoha@redhat.com>
AuthorDate:    Wed Jun 26 14:53:57 2013 +0200
Committer:     Peter Rajnoha <prajnoha@redhat.com>
CommitterDate: Tue Jul 2 15:22:11 2013 +0200

config: make it possible to run several instances of configuration check at once

Before, the status of the configuration check (config_def_check fn call)
was saved directly in global configuration definitinion array (as part
of the cfg_def_item_t/flags)

This patch introduces the "struct cft_check_handle" that defines
configuration check parameters as well as separate place to store
the status (status here means CFG_USED and CFG_VALID flags, formerly
saved in cfg_def_item_t/flags). This struct can hold config check
parameters as well as the status for each config tree separately,
thus making it possible to run several instances of config_def_check
without interference.
---
 lib/commands/toolcontext.c |   29 +++++++++++--
 lib/commands/toolcontext.h |    2 +
 lib/config/config.c        |  103 +++++++++++++++++++++----------------------
 lib/config/config.h        |   21 +++++++--
 tools/dumpconfig.c         |   36 ++++++++++++++-
 5 files changed, 127 insertions(+), 64 deletions(-)

diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index b7e3d46..4919b93 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -263,6 +263,29 @@ static int _check_disable_udev(const char *msg) {
 	return 0;
 }
 
+static int _check_config(struct cmd_context *cmd)
+{
+	if (!find_config_tree_bool(cmd, config_checks_CFG, NULL))
+		return 1;
+
+	if (!cmd->cft_check_handle) {
+		if (!(cmd->cft_check_handle = dm_pool_zalloc(cmd->libmem, sizeof(*cmd->cft_check_handle)))) {
+			log_error("Configuration check handle allocation failed.");
+			return 0;
+		}
+	}
+
+	cmd->cft_check_handle->cft = cmd->cft;
+
+	if (!config_def_check(cmd, cmd->cft_check_handle) &&
+	    find_config_tree_bool(cmd, config_abort_on_errors_CFG, NULL)) {
+		log_error("LVM configuration invalid.");
+		return 0;
+	}
+
+	return 1;
+}
+
 static int _process_config(struct cmd_context *cmd)
 {
 	mode_t old_umask;
@@ -275,10 +298,8 @@ static int _process_config(struct cmd_context *cmd)
 	int udev_disabled = 0;
 	char sysfs_dir[PATH_MAX];
 
-	if (!config_def_check(cmd, 0, 0, 0) && find_config_tree_bool(cmd, config_abort_on_errors_CFG, NULL)) {
-		log_error("LVM configuration invalid.");
-		return 0;
-	}
+	if (!_check_config(cmd))
+		return_0;
 
 	/* umask */
 	cmd->default_settings.umask = find_config_tree_int(cmd, global_umask_CFG, NULL);
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 42a4e54..2d90138 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -102,7 +102,9 @@ struct cmd_context {
 	struct profile_params *profile_params; /* profile handling params including loaded profile configs */
 	struct dm_config_tree *cft; /* the whole cascade: CONFIG_STRING -> CONFIG_PROFILE -> CONFIG_FILE/CONFIG_MERGED_FILES */
 	int config_initialized; /* used to reinitialize config if previous init was not successful */
+
 	struct dm_hash_table *cft_def_hash; /* config definition hash used for validity check (item type + item recognized) */
+	struct cft_check_handle *cft_check_handle;
 
 	/* selected settings with original default/configured value which can be changed during cmd processing */
 	struct config_info default_settings;
diff --git a/lib/config/config.c b/lib/config/config.c
index 6398eb0..2934b5a 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -584,12 +584,13 @@ static int _config_def_check_node_single_value(const char *rp, const struct dm_c
 	return 1;
 }
 
-static int _config_def_check_node_value(const char *rp, const struct dm_config_value *v,
-					const cfg_def_item_t *def, int suppress_messages)
+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)
 {
 	if (!v) {
 		if (def->type != CFG_TYPE_SECTION) {
-			_log_type_error(rp, CFG_TYPE_SECTION, def->type, suppress_messages);
+			_log_type_error(rp, CFG_TYPE_SECTION, def->type, handle->suppress_messages);
 			return 0;
 		}
 		return 1;
@@ -597,13 +598,13 @@ static int _config_def_check_node_value(const char *rp, const struct dm_config_v
 
 	if (v->next) {
 		if (!(def->type & CFG_TYPE_ARRAY)) {
-			_log_type_error(rp, CFG_TYPE_ARRAY, def->type, suppress_messages);
+			_log_type_error(rp, CFG_TYPE_ARRAY, def->type, handle->suppress_messages);
 			return 0;
 		}
 	}
 
 	do {
-		if (!_config_def_check_node_single_value(rp, v, def, suppress_messages))
+		if (!_config_def_check_node_single_value(rp, v, def, handle->suppress_messages))
 			return 0;
 		v = v->next;
 	} while (v);
@@ -611,9 +612,10 @@ static int _config_def_check_node_value(const char *rp, const struct dm_config_v
 	return 1;
 }
 
-static int _config_def_check_node(const char *vp, char *pvp, char *rp, char *prp,
+static int _config_def_check_node(struct cft_check_handle *handle,
+				  const char *vp, char *pvp, char *rp, char *prp,
 				  size_t buf_size, struct dm_config_node *cn,
-				  struct dm_hash_table *ht, int suppress_messages)
+				  struct dm_hash_table *ht)
 {
 	cfg_def_item_t *def;
 	int sep = vp != pvp; /* don't use '/' separator for top-level node */
@@ -628,7 +630,7 @@ static int _config_def_check_node(const char *vp, char *pvp, char *rp, char *prp
 	if (!(def = (cfg_def_item_t *) dm_hash_lookup(ht, vp))) {
 		/* If the node is not a section but a setting, fail now. */
 		if (cn->v) {
-			log_warn_suppress(suppress_messages,
+			log_warn_suppress(handle->suppress_messages,
 				"Configuration setting \"%s\" unknown.", rp);
 			cn->id = -1;
 			return 0;
@@ -639,38 +641,38 @@ static int _config_def_check_node(const char *vp, char *pvp, char *rp, char *prp
 		/* The real path without '#' is still stored in rp variable. */
 		pvp[sep] = '#', pvp[sep + 1] = '\0';
 		if (!(def = (cfg_def_item_t *) dm_hash_lookup(ht, vp))) {
-			log_warn_suppress(suppress_messages,
+			log_warn_suppress(handle->suppress_messages,
 				"Configuration section \"%s\" unknown.", rp);
 			cn->id = -1;
 			return 0;
 		}
 	}
 
-	def->flags |= CFG_USED;
+	handle->status[def->id] |= CFG_USED;
 	cn->id = def->id;
 
-	if (!_config_def_check_node_value(rp, cn->v, def, suppress_messages))
-	return 0;
+	if (!_config_def_check_node_value(handle, rp, cn->v, def))
+		return 0;
 
-	def->flags |= CFG_VALID;
+	handle->status[def->id] |= CFG_VALID;
 	return 1;
 }
 
-static int _config_def_check_tree(const char *vp, char *pvp, char *rp, char *prp,
+static int _config_def_check_tree(struct cft_check_handle *handle,
+				  const char *vp, char *pvp, char *rp, char *prp,
 				  size_t buf_size, struct dm_config_node *root,
-				  struct dm_hash_table *ht, int suppress_messages)
+				  struct dm_hash_table *ht)
 {
 	struct dm_config_node *cn;
 	int valid, r = 1;
 	size_t len;
 
 	for (cn = root->child; cn; cn = cn->sib) {
-		if ((valid = _config_def_check_node(vp, pvp, rp, prp, buf_size,
-					cn, ht, suppress_messages)) && !cn->v) {
+		if ((valid = _config_def_check_node(handle, vp, pvp, rp, prp,
+					buf_size, cn, ht)) && !cn->v) {
 			len = strlen(rp);
-			valid = _config_def_check_tree(vp, pvp + strlen(pvp),
-					rp, prp + len, buf_size - len, cn, ht,
-					suppress_messages);
+			valid = _config_def_check_tree(handle, vp, pvp + strlen(pvp),
+					rp, prp + len, buf_size - len, cn, ht);
 		}
 		if (!valid)
 			r = 0;
@@ -679,7 +681,7 @@ static int _config_def_check_tree(const char *vp, char *pvp, char *rp, char *prp
 	return r;
 }
 
-int config_def_check(struct cmd_context *cmd, int force, int skip, int suppress_messages)
+int config_def_check(struct cmd_context *cmd, struct cft_check_handle *handle)
 {
 	cfg_def_item_t *def;
 	struct dm_config_node *cn;
@@ -695,28 +697,21 @@ int config_def_check(struct cmd_context *cmd, int force, int skip, int suppress_
 	 */
 
 	/*
-	 * If the check has already been done and 'skip' is set,
+	 * If the check has already been done and 'skip_if_checked' is set,
 	 * skip the actual check and use last result if available.
 	 * If not available, we must do the check. The global status
 	 * is stored in root node.
 	 */
-	def = cfg_def_get_item_p(root_CFG_SECTION);
-	if (skip && (def->flags & CFG_USED))
-		return def->flags & CFG_VALID;
-
-	/* Clear 'used' and 'valid' status flags. */
-	for (id = 0; id < CFG_COUNT; id++) {
-		def = cfg_def_get_item_p(id);
-		def->flags &= ~(CFG_USED | CFG_VALID);
-	}
+	if (handle->skip_if_checked && (handle->status[root_CFG_SECTION] & CFG_USED))
+		return handle->status[root_CFG_SECTION] & CFG_VALID;
 
-	if (!force && !find_config_tree_bool(cmd, config_checks_CFG, NULL)) {
-		if (cmd->cft_def_hash) {
-			dm_hash_destroy(cmd->cft_def_hash);
-			cmd->cft_def_hash = NULL;
-		}
+	/* Nothing to do if checks are disabled and also not forced. */
+	if (!handle->force_check && !find_config_tree_bool(cmd, config_checks_CFG, NULL))
 		return 1;
-	}
+
+	/* Clear 'used' and 'valid' status flags. */
+	for (id = 0; id < CFG_COUNT; id++)
+		handle->status[id] &= ~(CFG_USED | CFG_VALID);
 
 	/*
 	 * Create a hash of all possible configuration
@@ -743,44 +738,46 @@ int config_def_check(struct cmd_context *cmd, int force, int skip, int suppress_
 		}
 	}
 
-	cfg_def_get_item_p(root_CFG_SECTION)->flags |= CFG_USED;
+	/*
+	 * Mark this handle as used so next time we know that the check
+	 * has already been done and so we can just reuse the previous
+	 * status instead of running this whole check again.
+	 */
+	handle->status[root_CFG_SECTION] |= CFG_USED;
 
 	/*
 	 * Allow only sections as top-level elements.
 	 * Iterate top-level sections and dive deeper.
 	 * If any of subsequent checks fails, the whole check fails.
 	 */
-	for (cn = cmd->cft->root; cn; cn = cn->sib) {
+	for (cn = handle->cft->root; cn; cn = cn->sib) {
 		if (!cn->v) {
 			/* top level node: vp=vp, rp=rp */
-			if (!_config_def_check_node(vp, vp, rp, rp,
+			if (!_config_def_check_node(handle, vp, vp, rp, rp,
 						    CFG_PATH_MAX_LEN,
-						    cn, cmd->cft_def_hash,
-						    suppress_messages)) {
+						    cn, cmd->cft_def_hash)) {
 				r = 0; continue;
 			}
 			rplen = strlen(rp);
-			if (!_config_def_check_tree(vp, vp + strlen(vp),
+			if (!_config_def_check_tree(handle,
+						    vp, vp + strlen(vp),
 						    rp, rp + rplen,
 						    CFG_PATH_MAX_LEN - rplen,
-						    cn, cmd->cft_def_hash,
-						    suppress_messages))
+						    cn, cmd->cft_def_hash))
 				r = 0;
 		} else {
-			log_error_suppress(suppress_messages,
+			log_error_suppress(handle->suppress_messages,
 				"Configuration setting \"%s\" invalid. "
 				"It's not part of any section.", cn->key);
 			r = 0;
 		}
 	}
 out:
-	if (r) {
-		cfg_def_get_item_p(root_CFG_SECTION)->flags |= CFG_VALID;
-		def->flags |= CFG_VALID;
-	} else {
-		cfg_def_get_item_p(root_CFG_SECTION)->flags &= ~CFG_VALID;
-		def->flags &= ~CFG_VALID;
-	}
+	if (r)
+		handle->status[root_CFG_SECTION] |= CFG_VALID;
+	else
+		handle->status[root_CFG_SECTION] &= ~CFG_VALID;
+
 	return r;
 }
 
diff --git a/lib/config/config.h b/lib/config/config.h
index fe4c31d..51c777a 100644
--- a/lib/config/config.h
+++ b/lib/config/config.h
@@ -80,10 +80,6 @@ typedef union {
 #define CFG_ADVANCED		0x04
 /* whether the configuraton item is not officially supported */
 #define CFG_UNSUPPORTED		0x08
-/* helper flag to mark the item as used in a config tree instance */
-#define CFG_USED		0x10
-/* helper flag to mark the item as valid in a config tree instance */
-#define CFG_VALID		0x20
 
 /* configuration definition item structure */
 typedef struct cfg_def_item {
@@ -114,6 +110,12 @@ struct config_def_tree_spec {
 	int ignoreunsupported;		/* do not include unsupported configs */
 };
 
+
+/* flag to mark the item as used in a config tree instance during validation */
+#define CFG_USED		0x01
+/* flag to mark the item as valid in a config tree instance during validation */
+#define CFG_VALID		0x02
+
 /*
  * Register ID for each possible item in the configuration tree.
  */
@@ -131,8 +133,17 @@ struct profile *add_profile(struct cmd_context *cmd, const char *profile_name);
 int load_profile(struct cmd_context *cmd, struct profile *profile);
 int load_pending_profiles(struct cmd_context *cmd);
 
+/* configuration check handle for each instance of the validation check */
+struct cft_check_handle {
+	struct dm_config_tree *cft;	/* the tree for which the check is done */
+	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 */
+	uint8_t status[CFG_COUNT];	/* flags for each configuration item - the result of the check */
+};
+
 int config_def_get_path(char *buf, size_t buf_size, int id);
-int config_def_check(struct cmd_context *cmd, int force, int skip, int suppress_messages);
+int config_def_check(struct cmd_context *cmd, struct cft_check_handle *handle);
 
 int override_config_tree_from_string(struct cmd_context *cmd, const char *config_settings);
 int override_config_tree_from_profile(struct cmd_context *cmd, struct profile *profile);
diff --git a/tools/dumpconfig.c b/tools/dumpconfig.c
index 9ba451e..2d6cbe3 100644
--- a/tools/dumpconfig.c
+++ b/tools/dumpconfig.c
@@ -31,6 +31,22 @@ static int _get_vsn(struct cmd_context *cmd, unsigned int *major,
 	return 1;
 }
 
+static struct cft_check_handle *_get_cft_check_handle(struct cmd_context *cmd)
+{
+	struct cft_check_handle *handle = cmd->cft_check_handle;
+
+	if (!handle) {
+		if (!(handle = dm_pool_zalloc(cmd->libmem, sizeof(*cmd->cft_check_handle)))) {
+			log_error("Configuration check handle allocation failed.");
+			return NULL;
+		}
+		handle->cft = cmd->cft;
+		cmd->cft_check_handle = handle;
+	}
+
+	return handle;
+}
+
 int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
 {
 	const char *file = arg_str_value(cmd, file_ARG, NULL);
@@ -38,6 +54,7 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
 	unsigned int major, minor, patchlevel;
 	struct config_def_tree_spec tree_spec = {0};
 	struct dm_config_tree *cft = cmd->cft;
+	struct cft_check_handle *cft_check_handle;
 	int r = ECMD_PROCESSED;
 
 	if (arg_count(cmd, configtype_ARG) && arg_count(cmd, validate_ARG)) {
@@ -57,7 +74,14 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
 		tree_spec.ignoreunsupported = 1;
 
 	if (arg_count(cmd, validate_ARG)) {
-		if (config_def_check(cmd, 1, 1, 0)) {
+		if (!(cft_check_handle = _get_cft_check_handle(cmd)))
+			return ECMD_FAILED;
+
+		cft_check_handle->force_check = 1;
+		cft_check_handle->skip_if_checked = 1;
+		cft_check_handle->suppress_messages = 0;
+
+		if (config_def_check(cmd, cft_check_handle)) {
 			log_print("LVM configuration valid.");
 			return ECMD_PROCESSED;
 		} else {
@@ -72,7 +96,15 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
 			return EINVALID_CMD_LINE;
 		}
 		tree_spec.type = CFG_DEF_TREE_CURRENT;
-		config_def_check(cmd, 1, 1, 1);
+
+		if (!(cft_check_handle = _get_cft_check_handle(cmd)))
+			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"))



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2013-07-02 13:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-02 13:32 master - config: make it possible to run several instances of configuration check at once Peter Rajnoha

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.