[PATCH] Add ability to reload corosync.conf (first draft, RFC))

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 exec/cfg.c                 | 187 ++++++++++++++++++++++++-
 exec/coroparse.c           |  90 ++++++------
 exec/logconfig.c           |  28 ++++
 exec/main.c                |   2 +-
 exec/main.h                |   3 +-
 exec/totemconfig.c         | 335 +++++++++++++++++++++++++++++++--------------
 include/corosync/cfg.h     |   5 +-
 include/corosync/ipc_cfg.h |  14 +-
 lib/cfg.c                  |  41 +++++-
 tools/corosync-cfgtool.c   |  31 ++++-
 10 files changed, 578 insertions(+), 158 deletions(-)

diff --git a/exec/cfg.c b/exec/cfg.c
index 503cde1..f3b2ce0 100644
--- a/exec/cfg.c
+++ b/exec/cfg.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005-2006 MontaVista Software, Inc.
- * Copyright (c) 2006-2012 Red Hat, Inc.
+ * Copyright (c) 2006-2013 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -64,13 +64,15 @@
 #include <corosync/corodefs.h>
 
 #include "service.h"
+#include "main.h"
 
 LOGSYS_DECLARE_SUBSYS ("CFG");
 
 enum cfg_message_req_types {
         MESSAGE_REQ_EXEC_CFG_RINGREENABLE = 0,
 	MESSAGE_REQ_EXEC_CFG_KILLNODE = 1,
-	MESSAGE_REQ_EXEC_CFG_SHUTDOWN = 2
+	MESSAGE_REQ_EXEC_CFG_SHUTDOWN = 2,
+	MESSAGE_REQ_EXEC_CFG_RELOAD_CONFIG = 3
 };
 
 #define DEFAULT_SHUTDOWN_TIMEOUT 5
@@ -122,6 +124,10 @@ static void message_handler_req_exec_cfg_shutdown (
         const void *message,
         unsigned int nodeid);
 
+static void message_handler_req_exec_cfg_reload_config (
+        const void *message,
+        unsigned int nodeid);
+
 static void exec_cfg_killnode_endian_convert (void *msg);
 
 static void message_handler_req_lib_cfg_ringstatusget (
@@ -152,6 +158,10 @@ static void message_handler_req_lib_cfg_local_get (
 	void *conn,
 	const void *msg);
 
+static void message_handler_req_lib_cfg_reload_config (
+	void *conn,
+	const void *msg);
+
 /*
  * Service Handler Definition
  */
@@ -184,6 +194,10 @@ static struct corosync_lib_handler cfg_lib_engine[] =
 	{ /* 6 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_local_get,
 		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 7 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_reload_config,
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
 	}
 };
 
@@ -198,6 +212,9 @@ static struct corosync_exec_handler cfg_exec_engine[] =
 	},
 	{ /* 2 */
 		.exec_handler_fn = message_handler_req_exec_cfg_shutdown,
+	},
+	{ /* 4 */
+		.exec_handler_fn = message_handler_req_exec_cfg_reload_config,
 	}
 };
 
@@ -231,6 +248,11 @@ struct req_exec_cfg_ringreenable {
         mar_message_source_t source __attribute__((aligned(8)));
 };
 
+struct req_exec_cfg_reload_config {
+	struct qb_ipc_request_header header __attribute__((aligned(8)));
+        mar_message_source_t source __attribute__((aligned(8)));
+};
+
 struct req_exec_cfg_killnode {
 	struct qb_ipc_request_header header __attribute__((aligned(8)));
         mar_uint32_t nodeid __attribute__((aligned(8)));
@@ -526,6 +548,145 @@ static void message_handler_req_exec_cfg_shutdown (
 	LEAVE();
 }
 
+/* strcmp replacement that can handle NULLs */
+static int nullcheck_strcmp(const char* left, const char *right)
+{
+	if (!left && right)
+		return -1;
+	if (left && ! right)
+		return 1;
+
+	if (!left && !right)
+		return 0;
+
+	return strcmp(left, right);
+}
+
+static void remove_deleted_entries(icmap_map_t temp_map, const char *prefix)
+{
+	icmap_iter_t old_iter;
+	icmap_iter_t new_iter;
+	const char *old_key, *new_key;
+	int ret;
+
+	old_iter = icmap_iter_init(prefix);
+	new_iter = icmap_iter_init_r(temp_map, prefix);
+
+	old_key = icmap_iter_next(old_iter, NULL, NULL);
+	new_key = icmap_iter_next(new_iter, NULL, NULL);
+
+	while (old_key || new_key) {
+		ret = nullcheck_strcmp(old_key, new_key);
+		if ((ret < 0 && old_key) || !new_key) {
+			/*
+			 * new_key is greater, a line (or more) has been deleted
+			 * Continue until old is >= new
+			 */
+			do {
+				/* Remove it from icmap & send notifications */
+				icmap_delete(old_key);
+
+				old_key = icmap_iter_next(old_iter, NULL, NULL);
+				ret = nullcheck_strcmp(old_key, new_key);
+			} while (ret < 0 && old_key);
+		}
+		else if ((ret > 0 && new_key) || !old_key) {
+			/*
+			 * old_key is greater, a line (or more) has been added
+			 * Continue until new is >= old
+			 *
+			 * we don't need to do anything special with this like tell
+			 * icmap. That will happen when we copy the values over
+			 */
+			do {
+				new_key = icmap_iter_next(new_iter, NULL, NULL);
+				ret = nullcheck_strcmp(old_key, new_key);
+			} while (ret > 0 && new_key);
+		}
+		if (ret == 0) {
+			new_key = icmap_iter_next(new_iter, NULL, NULL);
+			old_key = icmap_iter_next(old_iter, NULL, NULL);
+		}
+	}
+	icmap_iter_finalize(new_iter);
+	icmap_iter_finalize(old_iter);
+}
+
+/*
+ * Reload configuration file
+ */
+static void message_handler_req_exec_cfg_reload_config (
+        const void *message,
+        unsigned int nodeid)
+{
+	const struct req_exec_cfg_reload_config *req_exec_cfg_reload_config = message;
+	struct res_lib_cfg_reload_config res_lib_cfg_reload_config;
+	icmap_map_t temp_map;
+	const char *error_string;
+	int res = CS_OK;
+
+	ENTER();
+
+	log_printf(LOGSYS_LEVEL_NOTICE, "Config reload requested by node %d", nodeid);
+
+	/*
+	 * Set up a new hastable as a staging area.
+	 */
+	if ((res = icmap_init_r(&temp_map)) != CS_OK) {
+		log_printf(LOGSYS_LEVEL_ERROR, "Unable to create temporary icmap. config file reload cancelled\n");
+		goto reload_fini;
+	}
+
+	/*
+	 * Load new config into the temporary map
+	 */
+	res = coroparse_configparse(temp_map, &error_string);
+	if (res == -1) {
+		log_printf (LOGSYS_LEVEL_ERROR, "Unable to reload config file: %s", error_string);
+		res = CS_ERR_LIBRARY;
+		goto reload_return;
+	}
+
+	/* Tell interested listeners that we have started a reload */
+	icmap_set_uint8("config.reload_in_progress", 1);
+
+	/* Detect deleted entries and remove them from the main icmap hashtable */
+	remove_deleted_entries(temp_map, "logging.");
+	remove_deleted_entries(temp_map, "totem.");
+	remove_deleted_entries(temp_map, "nodelist.");
+	remove_deleted_entries(temp_map, "quorum.");
+
+	/*
+	 * Copy new keys into live config.
+	 * If this fails we will have a partially loaded config because some keys (above) might
+	 * have been reset to defaults - I'm not sure what to do here, we might have to quit.
+	 */
+	if ( (res = icmap_copy_map(icmap_get_global_map(), temp_map)) != CS_OK) {
+		log_printf (LOGSYS_LEVEL_ERROR, "Error making new config live. cmap database may be inconsistent\n");
+	}
+
+	/* All done - let clients know */
+	icmap_set_uint8("config.reload_in_progress", 0);
+
+reload_fini:
+	/* Finished with the temporary storage */
+	icmap_fini_r(temp_map);
+
+reload_return:
+	/* All done, return result to the caller if it was on this system */
+	if (nodeid == api->totem_nodeid_get()) {
+		res_lib_cfg_reload_config.header.size = sizeof(res_lib_cfg_reload_config);
+		res_lib_cfg_reload_config.header.id = MESSAGE_RES_CFG_RELOAD_CONFIG;
+		res_lib_cfg_reload_config.header.error = res;
+		api->ipc_response_send(req_exec_cfg_reload_config->source.conn,
+				       &res_lib_cfg_reload_config,
+				       sizeof(res_lib_cfg_reload_config));
+		api->ipc_refcnt_dec(req_exec_cfg_reload_config->source.conn);;
+	}
+
+	LEAVE();
+}
+
 /*
  * Library Interface Implementation
  */
@@ -847,3 +1008,25 @@ static void message_handler_req_lib_cfg_local_get (void *conn, const void *msg)
 	api->ipc_response_send(conn, &res_lib_cfg_local_get,
 		sizeof(res_lib_cfg_local_get));
 }
+
+static void message_handler_req_lib_cfg_reload_config (void *conn, const void *msg)
+{
+	struct req_exec_cfg_reload_config req_exec_cfg_reload_config;
+	struct iovec iovec;
+
+	ENTER();
+
+	req_exec_cfg_reload_config.header.size =
+		sizeof (struct req_exec_cfg_reload_config);
+	req_exec_cfg_reload_config.header.id = SERVICE_ID_MAKE (CFG_SERVICE,
+		MESSAGE_REQ_EXEC_CFG_RELOAD_CONFIG);
+	api->ipc_source_set (&req_exec_cfg_reload_config.source, conn);
+	api->ipc_refcnt_inc(conn);
+
+	iovec.iov_base = (char *)&req_exec_cfg_reload_config;
+	iovec.iov_len = sizeof (struct req_exec_cfg_reload_config);
+
+	assert (api->totem_mcast (&iovec, 1, TOTEM_SAFE) == 0);
+
+	LEAVE();
+}
diff --git a/exec/coroparse.c b/exec/coroparse.c
index af4072d..1ac0cdd 100644
--- a/exec/coroparse.c
+++ b/exec/coroparse.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2012 Red Hat, Inc.
+ * Copyright (c) 2006-2013 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -76,6 +76,7 @@ typedef int (*parser_cb_f)(const char *path,
 			char *value,
 			enum parser_cb_type type,
 			const char **error_string,
+			icmap_map_t config_map,
 			void *user_data);
 
 enum main_cp_cb_data_state {
@@ -120,7 +121,7 @@ struct main_cp_cb_data {
 };
 
 static int read_config_file_into_icmap(
-	const char **error_string);
+	const char **error_string, icmap_map_t config_map);
 static char error_string_response[512];
 
 static int uid_determine (const char *req_user)
@@ -243,9 +244,9 @@ static char *strchr_rs (const char *haystack, int byte)
 	return ((char *) end_address);
 }
 
-int coroparse_configparse (const char **error_string)
+int coroparse_configparse (icmap_map_t config_map, const char **error_string)
 {
-	if (read_config_file_into_icmap(error_string)) {
+	if (read_config_file_into_icmap(error_string, config_map)) {
 		return -1;
 	}
 
@@ -277,6 +278,7 @@ static int parse_section(FILE *fp,
 			 const char **error_string,
 			 int depth,
 			 parser_cb_f parser_cb,
+			 icmap_map_t config_map,
 			 void *user_data)
 {
 	char line[512];
@@ -286,7 +288,7 @@ static int parse_section(FILE *fp,
 	char new_keyname[ICMAP_KEYNAME_MAXLEN];
 
 	if (strcmp(path, "") == 0) {
-		parser_cb("", NULL, NULL, PARSER_CB_START, error_string, user_data);
+		parser_cb("", NULL, NULL, PARSER_CB_START, error_string, config_map, user_data);
 	}
 
 	while (fgets (line, sizeof (line), fp)) {
@@ -340,11 +342,11 @@ static int parse_section(FILE *fp,
 			}
 			strcat(new_keyname, section);
 
-			if (!parser_cb(new_keyname, NULL, NULL, PARSER_CB_SECTION_START, error_string, user_data)) {
+			if (!parser_cb(new_keyname, NULL, NULL, PARSER_CB_SECTION_START, error_string, config_map, user_data)) {
 				return -1;
 			}
 
-			if (parse_section(fp, new_keyname, error_string, depth + 1, parser_cb, user_data))
+			if (parse_section(fp, new_keyname, error_string, depth + 1, parser_cb, config_map, user_data))
 				return -1;
 
 			continue ;
@@ -369,7 +371,7 @@ static int parse_section(FILE *fp,
 			}
 			strcat(new_keyname, key);
 
-			if (!parser_cb(new_keyname, key, value, PARSER_CB_ITEM, error_string, user_data)) {
+			if (!parser_cb(new_keyname, key, value, PARSER_CB_ITEM, error_string, config_map, user_data)) {
 				return -1;
 			}
 
@@ -383,7 +385,7 @@ static int parse_section(FILE *fp,
 				return -1;
 			}
 
-			if (!parser_cb(path, NULL, NULL, PARSER_CB_SECTION_END, error_string, user_data)) {
+			if (!parser_cb(path, NULL, NULL, PARSER_CB_SECTION_END, error_string, config_map, user_data)) {
 				return -1;
 			}
 
@@ -397,7 +399,7 @@ static int parse_section(FILE *fp,
 	}
 
 	if (strcmp(path, "") == 0) {
-		parser_cb("", NULL, NULL, PARSER_CB_END, error_string, user_data);
+		parser_cb("", NULL, NULL, PARSER_CB_END, error_string, config_map, user_data);
 	}
 
 	return 0;
@@ -456,6 +458,7 @@ static int main_config_parser_cb(const char *path,
 			char *value,
 			enum parser_cb_type type,
 			const char **error_string,
+			icmap_map_t config_map,
 			void *user_data)
 {
 	int i;
@@ -487,7 +490,7 @@ static int main_config_parser_cb(const char *path,
 				if (safe_atoi(value, &i) != 0) {
 					goto atoi_error;
 				}
-				icmap_set_uint32(path, i);
+				icmap_set_uint32_r(config_map, path, i);
 				add_as_string = 0;
 			}
 			break;
@@ -499,7 +502,7 @@ static int main_config_parser_cb(const char *path,
 				if (safe_atoi(value, &i) != 0) {
 					goto atoi_error;
 				}
-				icmap_set_uint32(path, i);
+				icmap_set_uint32_r(config_map, path, i);
 				add_as_string = 0;
 			}
 
@@ -511,7 +514,7 @@ static int main_config_parser_cb(const char *path,
 				if (safe_atoi(value, &i) != 0) {
 					goto atoi_error;
 				}
-				icmap_set_uint8(path, i);
+				icmap_set_uint8_r(config_map, path, i);
 				add_as_string = 0;
 			}
 			break;
@@ -521,14 +524,14 @@ static int main_config_parser_cb(const char *path,
 				if (safe_atoi(value, &i) != 0) {
 					goto atoi_error;
 				}
-				icmap_set_uint32(path, i);
+				icmap_set_uint32_r(config_map, path, i);
 				add_as_string = 0;
 			}
 			if ((strcmp(path, "quorum.device.master_wins") == 0)) {
 				if (safe_atoi(value, &i) != 0) {
 					goto atoi_error;
 				}
-				icmap_set_uint8(path, i);
+				icmap_set_uint8_r(config_map, path, i);
 				add_as_string = 0;
 			}
 			break;
@@ -561,14 +564,14 @@ static int main_config_parser_cb(const char *path,
 				if (safe_atoi(value, &i) != 0) {
 					goto atoi_error;
 				}
-				icmap_set_uint32(path, i);
+				icmap_set_uint32_r(config_map,path, i);
 				add_as_string = 0;
 			}
 			if (strcmp(path, "totem.config_version") == 0) {
 				if (str_to_ull(value, &ull) != 0) {
 					goto atoi_error;
 				}
-				icmap_set_uint64(path, ull);
+				icmap_set_uint64_r(config_map, path, ull);
 				add_as_string = 0;
 			}
 			if (strcmp(path, "totem.ip_version") == 0) {
@@ -749,7 +752,7 @@ static int main_config_parser_cb(const char *path,
 				}
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
 						uid);
-				icmap_set_uint8(key_name, 1);
+				icmap_set_uint8_r(config_map, key_name, 1);
 				add_as_string = 0;
 			} else if (strcmp(key, "gid") == 0) {
 				gid = gid_determine(value);
@@ -759,7 +762,7 @@ static int main_config_parser_cb(const char *path,
 				}
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
 						gid);
-				icmap_set_uint8(key_name, 1);
+				icmap_set_uint8_r(config_map, key_name, 1);
 				add_as_string = 0;
 			} else {
 				*error_string = "uidgid: Only uid and gid are allowed items";
@@ -803,7 +806,7 @@ static int main_config_parser_cb(const char *path,
 					goto atoi_error;
 				}
 
-				icmap_set_uint32(key_name, i);
+				icmap_set_uint32_r(config_map, key_name, i);
 				add_as_string = 0;
 			}
 
@@ -812,14 +815,14 @@ static int main_config_parser_cb(const char *path,
 			}
 
 			if (add_as_string) {
-				icmap_set_string(key_name, value);
+				icmap_set_string_r(config_map, key_name, value);
 				add_as_string = 0;
 			}
 			break;
 		}
 
 		if (add_as_string) {
-			icmap_set_string(path, value);
+			icmap_set_string_r(config_map, path, value);
 		}
 		break;
 	case PARSER_CB_SECTION_START:
@@ -882,7 +885,7 @@ static int main_config_parser_cb(const char *path,
 			if (data->bindnetaddr != NULL) {
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
 						data->ringnumber);
-				icmap_set_string(key_name, data->bindnetaddr);
+				icmap_set_string_r(config_map, key_name, data->bindnetaddr);
 
 				free(data->bindnetaddr);
 				data->bindnetaddr = NULL;
@@ -891,7 +894,7 @@ static int main_config_parser_cb(const char *path,
 			if (data->mcastaddr != NULL) {
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
 						data->ringnumber);
-				icmap_set_string(key_name, data->mcastaddr);
+				icmap_set_string_r(config_map, key_name, data->mcastaddr);
 
 				free(data->mcastaddr);
 				data->mcastaddr = NULL;
@@ -900,7 +903,7 @@ static int main_config_parser_cb(const char *path,
 			if (data->broadcast != NULL) {
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
 						data->ringnumber);
-				icmap_set_string(key_name, data->broadcast);
+				icmap_set_string_r(config_map, key_name, data->broadcast);
 
 				free(data->broadcast);
 				data->broadcast = NULL;
@@ -909,13 +912,13 @@ static int main_config_parser_cb(const char *path,
 			if (data->mcastport > -1) {
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
 						data->ringnumber);
-				icmap_set_uint16(key_name, data->mcastport);
+				icmap_set_uint16_r(config_map, key_name, data->mcastport);
 			}
 
 			if (data->ttl > -1) {
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
 						data->ringnumber);
-				icmap_set_uint8(key_name, data->ttl);
+				icmap_set_uint8_r(config_map, key_name, data->ttl);
 			}
 
 			i = 0;
@@ -925,7 +928,7 @@ static int main_config_parser_cb(const char *path,
 
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
 						data->ringnumber, i);
-				icmap_set_string(key_name, kv_item->value);
+				icmap_set_string_r(config_map, key_name, kv_item->value);
 
 				iter_next = iter->next;
 
@@ -956,7 +959,7 @@ static int main_config_parser_cb(const char *path,
 
 				snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
 						data->subsys, kv_item->key);
-				icmap_set_string(key_name, kv_item->value);
+				icmap_set_string_r(config_map, key_name, kv_item->value);
 
 				iter_next = iter->next;
 
@@ -967,7 +970,7 @@ static int main_config_parser_cb(const char *path,
 
 			snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
 					data->subsys);
-			icmap_set_string(key_name, data->subsys);
+			icmap_set_string_r(config_map, key_name, data->subsys);
 
 			free(data->subsys);
 
@@ -1007,7 +1010,7 @@ static int main_config_parser_cb(const char *path,
 								kv_item->key);
 					}
 				}
-				icmap_set_string(key_name, kv_item->value);
+				icmap_set_string_r(config_map, key_name, kv_item->value);
 
 				iter_next = iter->next;
 
@@ -1020,21 +1023,21 @@ static int main_config_parser_cb(const char *path,
 				if (strcmp(data->logging_daemon_name, "corosync") != 0) {
 					snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
 							data->logging_daemon_name);
-					icmap_set_string(key_name, data->logging_daemon_name);
+					icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
 				}
 			} else {
 				if (strcmp(data->logging_daemon_name, "corosync") == 0) {
 					snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
 							data->subsys);
-					icmap_set_string(key_name, data->subsys);
+					icmap_set_string_r(config_map, key_name, data->subsys);
 
 				} else {
 					snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
 							data->logging_daemon_name, data->subsys);
-					icmap_set_string(key_name, data->subsys);
+					icmap_set_string_r(config_map, key_name, data->subsys);
 					snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
 							data->logging_daemon_name, data->subsys);
-					icmap_set_string(key_name, data->logging_daemon_name);
+					icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
 				}
 			}
 
@@ -1086,6 +1089,7 @@ static int uidgid_config_parser_cb(const char *path,
 			char *value,
 			enum parser_cb_type type,
 			const char **error_string,
+			icmap_map_t config_map,
 			void *user_data)
 {
 	char key_name[ICMAP_KEYNAME_MAXLEN];
@@ -1105,7 +1109,7 @@ static int uidgid_config_parser_cb(const char *path,
 			}
 			snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
 					uid);
-			icmap_set_uint8(key_name, 1);
+			icmap_set_uint8_r(config_map, key_name, 1);
 		} else if (strcmp(path, "uidgid.gid") == 0) {
 			gid = gid_determine(value);
 			if (gid == -1) {
@@ -1114,7 +1118,7 @@ static int uidgid_config_parser_cb(const char *path,
 			}
 			snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
 					gid);
-			icmap_set_uint8(key_name, 1);
+			icmap_set_uint8_r(config_map, key_name, 1);
 		} else {
 			*error_string = "uidgid: Only uid and gid are allowed items";
 			return (0);
@@ -1134,7 +1138,8 @@ static int uidgid_config_parser_cb(const char *path,
 }
 
 static int read_uidgid_files_into_icmap(
-	const char **error_string)
+	const char **error_string,
+	icmap_map_t config_map)
 {
 	FILE *fp;
 	const char *dirname;
@@ -1175,7 +1180,7 @@ static int read_uidgid_files_into_icmap(
 
 			key_name[0] = 0;
 
-			res = parse_section(fp, key_name, error_string, 0, uidgid_config_parser_cb, NULL);
+			res = parse_section(fp, key_name, error_string, 0, uidgid_config_parser_cb, config_map, NULL);
 
 			fclose (fp);
 
@@ -1194,7 +1199,8 @@ error_exit:
 
 /* Read config file and load into icmap */
 static int read_config_file_into_icmap(
-	const char **error_string)
+	const char **error_string,
+	icmap_map_t config_map)
 {
 	FILE *fp;
 	const char *filename;
@@ -1220,12 +1226,12 @@ static int read_config_file_into_icmap(
 
 	key_name[0] = 0;
 
-	res = parse_section(fp, key_name, error_string, 0, main_config_parser_cb, &data);
+	res = parse_section(fp, key_name, error_string, 0, main_config_parser_cb, config_map, &data);
 
 	fclose(fp);
 
 	if (res == 0) {
-	        res = read_uidgid_files_into_icmap(error_string);
+	        res = read_uidgid_files_into_icmap(error_string, config_map);
 	}
 
 	if (res == 0) {
diff --git a/exec/logconfig.c b/exec/logconfig.c
index 0c9eeb4..e6f984a 100644
--- a/exec/logconfig.c
+++ b/exec/logconfig.c
@@ -542,6 +542,22 @@ static void main_logging_notify(
 #endif
 {
 	const char *error_string;
+	static int reload_in_progress = 0;
+
+	/* If a full reload happens then suspend updates for individual keys until
+	 * it's all completed
+	 */
+	if (strcmp(key_name, "config.reload_in_progress") == 0) {
+		if (*(uint8_t *)new_val.data == 1) {
+			reload_in_progress = 1;
+		} else {
+			reload_in_progress = 0;
+		}
+	}
+	if (reload_in_progress) {
+		log_printf(LOGSYS_LEVEL_DEBUG, "Ignoring key change, reload in progress. %s\n", key_name);
+		return;
+	}
 
 	/*
 	 * Reload the logsys configuration
@@ -562,6 +578,12 @@ static void add_logsys_config_notification(void)
 			main_logging_notify,
 			NULL,
 			&icmap_track);
+
+	icmap_track_add("config.reload_in_progress",
+			ICMAP_TRACK_ADD | ICMAP_TRACK_MODIFY,
+			main_logging_notify,
+			NULL,
+			&icmap_track);
 }
 #else
 static void add_logsys_config_notification(void)
@@ -573,6 +595,12 @@ static void add_logsys_config_notification(void)
 			main_logging_notify,
 			NULL,
 			&cmap_track);
+
+	cmap_track_add(cmap_handle, "config.reload_in_progress",
+			CMAP_TRACK_ADD | CMAP_TRACK_MODIFY,
+			main_logging_notify,
+			NULL,
+			&cmap_track);
 }
 #endif
 
diff --git a/exec/main.c b/exec/main.c
index 6c69ee5..dadef97 100644
--- a/exec/main.c
+++ b/exec/main.c
@@ -1149,7 +1149,7 @@ int main (int argc, char **argv, char **envp)
 	 */
 	api = apidef_get ();
 
-	res = coroparse_configparse(&error_string);
+	res = coroparse_configparse(icmap_get_global_map(), &error_string);
 	if (res == -1) {
 		log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
 		corosync_exit_error (COROSYNC_DONE_MAINCONFIGREAD);
diff --git a/exec/main.h b/exec/main.h
index b65f0ae..12f7bb5 100644
--- a/exec/main.h
+++ b/exec/main.h
@@ -48,6 +48,7 @@
 #include <corosync/hdb.h>
 #include <qb/qbloop.h>
 #include <corosync/totem/totempg.h>
+#include <corosync/icmap.h>
 #include <corosync/coroapi.h>
 
 extern unsigned long long *(*main_clm_get_by_nodeid) (unsigned int node_id);
@@ -121,6 +122,6 @@ extern void cs_ipc_refcnt_dec(void *conn);
 
 extern void cs_ipc_allow_connections(int32_t allow);
 
-int coroparse_configparse (const char **error_string);
+int coroparse_configparse (icmap_map_t config_map, const char **error_string);
 
 #endif /* MAIN_H_DEFINED */
diff --git a/exec/totemconfig.c b/exec/totemconfig.c
index 62daeaf..8454c6e 100644
--- a/exec/totemconfig.c
+++ b/exec/totemconfig.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002-2005 MontaVista Software, Inc.
- * Copyright (c) 2006-2012 Red Hat, Inc.
+ * Copyright (c) 2006-2013 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -83,6 +83,57 @@ static char error_string_response[512];
 
 static void add_totem_config_notification(struct totem_config *totem_config);
 
+
+/* All the volatile parameters are uint32s, luckily */
+static uint32_t *totem_get_param_by_name(struct totem_config *totem_config, const char *param_name)
+{
+	if (strcmp(param_name, "totem.token") == 0)
+		return &totem_config->token_timeout;
+	if (strcmp(param_name, "totem.token_retransmit") == 0)
+		return &totem_config->token_retransmit_timeout;
+	if (strcmp(param_name, "totem.hold") == 0)
+		return &totem_config->token_hold_timeout;
+	if (strcmp(param_name, "totem.token_retransmits_before_loss_const") == 0)
+		return &totem_config->token_retransmits_before_loss_const;
+	if (strcmp(param_name, "totem.join") == 0)
+		return &totem_config->join_timeout;
+	if (strcmp(param_name, "totem.send_join") == 0)
+		return &totem_config->send_join_timeout;
+	if (strcmp(param_name, "totem.consensus") == 0)
+		return &totem_config->consensus_timeout;
+	if (strcmp(param_name, "totem.merge") == 0)
+		return &totem_config->merge_timeout;
+	if (strcmp(param_name, "totem.downcheck") == 0)
+		return &totem_config->downcheck_timeout;
+	if (strcmp(param_name, "totem.fail_recv_const") == 0)
+		return &totem_config->fail_to_recv_const;
+	if (strcmp(param_name, "totem.seqno_unchanged_const") == 0)
+		return &totem_config->seqno_unchanged_const;
+	if (strcmp(param_name, "totem.rrp_token_expired_timeout") == 0)
+		return &totem_config->rrp_token_expired_timeout;
+	if (strcmp(param_name, "totem.rrp_problem_count_timeout") == 0)
+		return &totem_config->rrp_problem_count_timeout;
+	if (strcmp(param_name, "totem.rrp_problem_count_threshold") == 0)
+		return &totem_config->rrp_problem_count_threshold;
+	if (strcmp(param_name, "totem.rrp_problem_count_mcast_threshold") == 0)
+		return &totem_config->rrp_problem_count_mcast_threshold;
+	if (strcmp(param_name, "totem.rrp_autorecovery_check_timeout") == 0)
+		return &totem_config->rrp_autorecovery_check_timeout;
+	if (strcmp(param_name, "totem.heartbeat_failures_allowed") == 0)
+		return &totem_config->heartbeat_failures_allowed;
+	if (strcmp(param_name, "totem.max_network_delay") == 0)
+		return &totem_config->max_network_delay;
+	if (strcmp(param_name, "totem.window_size") == 0)
+		return &totem_config->window_size;
+	if (strcmp(param_name, "totem.max_messages") == 0)
+		return &totem_config->max_messages;
+	if (strcmp(param_name, "totem.miss_count_const") == 0)
+		return &totem_config->miss_count_const;
+
+	return NULL;
+}
+
+
 static void totem_volatile_config_read (struct totem_config *totem_config)
 {
 	char *str;
@@ -703,80 +754,12 @@ extern int totem_config_read (
 	return 0;
 }
 
-int totem_config_validate (
+static int totem_set_volatile_defaults (
 	struct totem_config *totem_config,
 	const char **error_string)
 {
 	static char local_error_reason[512];
-	char parse_error[512];
 	const char *error_reason = local_error_reason;
-	int i;
-	unsigned int interface_max = INTERFACE_MAX;
-
-	if (totem_config->interface_count == 0) {
-		error_reason = "No interfaces defined";
-		goto parse_error;
-	}
-
-	for (i = 0; i < totem_config->interface_count; i++) {
-		/*
-		 * Some error checking of parsed data to make sure its valid
-		 */
-
-		struct totem_ip_address null_addr;
-		memset (&null_addr, 0, sizeof (struct totem_ip_address));
-
-		if ((totem_config->transport_number == 0) &&
-			memcmp (&totem_config->interfaces[i].mcast_addr, &null_addr,
-				sizeof (struct totem_ip_address)) == 0) {
-			error_reason = "No multicast address specified";
-			goto parse_error;
-		}
-
-		if (totem_config->interfaces[i].ip_port == 0) {
-			error_reason = "No multicast port specified";
-			goto parse_error;
-		}
-
-		if (totem_config->interfaces[i].ttl > 255) {
-			error_reason = "Invalid TTL (should be 0..255)";
-			goto parse_error;
-		}
-		if (totem_config->transport_number != TOTEM_TRANSPORT_UDP &&
-		    totem_config->interfaces[i].ttl != 1) {
-			error_reason = "Can only set ttl on multicast transport types";
-			goto parse_error;
-		}
-
-		if (totem_config->interfaces[i].mcast_addr.family == AF_INET6 &&
-			totem_config->node_id == 0) {
-
-			error_reason = "An IPV6 network requires that a node ID be specified.";
-			goto parse_error;
-		}
-
-		if (totem_config->broadcast_use == 0 && totem_config->transport_number == 0) {
-			if (totem_config->interfaces[i].mcast_addr.family != totem_config->interfaces[i].bindnet.family) {
-				error_reason = "Multicast address family does not match bind address family";
-				goto parse_error;
-			}
-
-			if (totem_config->interfaces[i].mcast_addr.family != totem_config->interfaces[i].bindnet.family) {
-				error_reason =  "Not all bind address belong to the same IP family";
-				goto parse_error;
-			}
-			if (totemip_is_mcast (&totem_config->interfaces[i].mcast_addr) != 0) {
-				error_reason = "mcastaddr is not a correct multicast address.";
-				goto parse_error;
-			}
-		}
-	}
-
-	if (totem_config->version != 2) {
-		error_reason = "This totem parser can only parse version 2 configurations.";
-		goto parse_error;
-	}
-
 
 	if (totem_config->token_retransmits_before_loss_const == 0) {
 		totem_config->token_retransmits_before_loss_const =
@@ -888,16 +871,15 @@ int totem_config_validate (
 		goto parse_error;
 	}
 
-	/*
-	 * RRP values validation
-	 */
-	if (strcmp (totem_config->rrp_mode, "none") &&
-		strcmp (totem_config->rrp_mode, "active") &&
-		strcmp (totem_config->rrp_mode, "passive")) {
-		snprintf (local_error_reason, sizeof(local_error_reason),
-			"The RRP mode \"%s\" specified is invalid.  It must be none, active, or passive.\n", totem_config->rrp_mode);
-		goto parse_error;
+	if (totem_config->fail_to_recv_const == 0) {
+		totem_config->fail_to_recv_const = FAIL_TO_RECV_CONST;
 	}
+	if (totem_config->seqno_unchanged_const == 0) {
+		totem_config->seqno_unchanged_const = SEQNO_UNCHANGED_CONST;
+	}
+
+/* RRP volatile values */
+
 	if (totem_config->rrp_problem_count_timeout == 0) {
 		totem_config->rrp_problem_count_timeout = RRP_PROBLEM_COUNT_TIMEOUT;
 	}
@@ -941,54 +923,127 @@ int totem_config_validate (
 		totem_config->rrp_autorecovery_check_timeout = RRP_AUTORECOVERY_CHECK_TIMEOUT;
 	}
 
-	if (strcmp (totem_config->rrp_mode, "none") == 0) {
-		interface_max = 1;
-	}
-	if (interface_max < totem_config->interface_count) {
-		snprintf (parse_error, sizeof(parse_error),
-			"%d is too many configured interfaces for the rrp_mode setting %s.",
-			totem_config->interface_count,
-			totem_config->rrp_mode);
-		error_reason = parse_error;
+	return 0;
+
+parse_error:
+	snprintf (error_string_response, sizeof(error_string_response),
+		 "parse error in config: %s\n", error_reason);
+	*error_string = error_string_response;
+	return (-1);
+
+}
+
+int totem_config_validate (
+	struct totem_config *totem_config,
+	const char **error_string)
+{
+	static char local_error_reason[512];
+	char parse_error[512];
+	const char *error_reason = local_error_reason;
+	int i;
+	unsigned int interface_max = INTERFACE_MAX;
+
+	if (totem_config->interface_count == 0) {
+		error_reason = "No interfaces defined";
 		goto parse_error;
 	}
 
+	for (i = 0; i < totem_config->interface_count; i++) {
+		/*
+		 * Some error checking of parsed data to make sure its valid
+		 */
 
-	if (totem_config->fail_to_recv_const == 0) {
-		totem_config->fail_to_recv_const = FAIL_TO_RECV_CONST;
-	}
-	if (totem_config->seqno_unchanged_const == 0) {
-		totem_config->seqno_unchanged_const = SEQNO_UNCHANGED_CONST;
+		struct totem_ip_address null_addr;
+		memset (&null_addr, 0, sizeof (struct totem_ip_address));
+
+		if ((totem_config->transport_number == 0) &&
+			memcmp (&totem_config->interfaces[i].mcast_addr, &null_addr,
+				sizeof (struct totem_ip_address)) == 0) {
+			error_reason = "No multicast address specified";
+			goto parse_error;
+		}
+
+		if (totem_config->interfaces[i].ip_port == 0) {
+			error_reason = "No multicast port specified";
+			goto parse_error;
+		}
+
+		if (totem_config->interfaces[i].ttl > 255) {
+			error_reason = "Invalid TTL (should be 0..255)";
+			goto parse_error;
+		}
+		if (totem_config->transport_number != TOTEM_TRANSPORT_UDP &&
+		    totem_config->interfaces[i].ttl != 1) {
+			error_reason = "Can only set ttl on multicast transport types";
+			goto parse_error;
+		}
+
+		if (totem_config->interfaces[i].mcast_addr.family == AF_INET6 &&
+			totem_config->node_id == 0) {
+
+			error_reason = "An IPV6 network requires that a node ID be specified.";
+			goto parse_error;
+		}
+
+		if (totem_config->broadcast_use == 0 && totem_config->transport_number == 0) {
+			if (totem_config->interfaces[i].mcast_addr.family != totem_config->interfaces[i].bindnet.family) {
+				error_reason = "Multicast address family does not match bind address family";
+				goto parse_error;
+			}
+
+			if (totem_config->interfaces[i].mcast_addr.family != totem_config->interfaces[i].bindnet.family) {
+				error_reason =  "Not all bind address belong to the same IP family";
+				goto parse_error;
+			}
+			if (totemip_is_mcast (&totem_config->interfaces[i].mcast_addr) != 0) {
+				error_reason = "mcastaddr is not a correct multicast address.";
+				goto parse_error;
+			}
+		}
 	}
-	if (totem_config->net_mtu == 0) {
-		totem_config->net_mtu = 1500;
+
+	if (totem_config->version != 2) {
+		error_reason = "This totem parser can only parse version 2 configurations.";
+		goto parse_error;
 	}
 
-	if ((MESSAGE_QUEUE_MAX) < totem_config->max_messages) {
+	totem_set_volatile_defaults(totem_config, error_string);
+
+	/*
+	 * RRP values validation
+	 */
+	if (strcmp (totem_config->rrp_mode, "none") &&
+		strcmp (totem_config->rrp_mode, "active") &&
+		strcmp (totem_config->rrp_mode, "passive")) {
 		snprintf (local_error_reason, sizeof(local_error_reason),
-			"The max_messages parameter (%d messages) may not be greater then (%d messages).",
-			totem_config->max_messages, MESSAGE_QUEUE_MAX);
+			"The RRP mode \"%s\" specified is invalid.  It must be none, active, or passive.\n", totem_config->rrp_mode);
 		goto parse_error;
 	}
 
-	if (totem_config->threads > SEND_THREADS_MAX) {
-		totem_config->threads = SEND_THREADS_MAX;
+	if (strcmp (totem_config->rrp_mode, "none") == 0) {
+		interface_max = 1;
 	}
-	if (totem_config->net_mtu > FRAME_SIZE_MAX) {
-		error_reason = "This net_mtu parameter is greater then the maximum frame size";
+	if (interface_max < totem_config->interface_count) {
+		snprintf (parse_error, sizeof(parse_error),
+			"%d is too many configured interfaces for the rrp_mode setting %s.",
+			totem_config->interface_count,
+			totem_config->rrp_mode);
+		error_reason = parse_error;
 		goto parse_error;
 	}
-	if (totem_config->vsf_type == NULL) {
-		totem_config->vsf_type = "none";
+
+	if (totem_config->net_mtu == 0) {
+		totem_config->net_mtu = 1500;
 	}
 
-	return (0);
+	return 0;
 
 parse_error:
 	snprintf (error_string_response, sizeof(error_string_response),
 		 "parse error in config: %s\n", error_reason);
 	*error_string = error_string_response;
 	return (-1);
+
 }
 
 static int read_keyfile (
@@ -1107,7 +1162,69 @@ static void totem_change_notify(
 	struct icmap_notify_value old_val,
 	void *user_data)
 {
-	totem_volatile_config_read((struct totem_config *)user_data);
+	uint32_t *param;
+	const char *error_string;
+	uint8_t reloading;
+
+	/*
+	 * If a full reload is in progress then don't do anything until it's done and
+	 * can reconfigure it all atomically
+	 */
+	if (icmap_get_uint8("config.reload_in_progress", &reloading) == CS_OK && reloading)
+		return;
+
+	param = totem_get_param_by_name((struct totem_config *)user_data, key_name);
+	if (!param)
+		return;
+
+	switch (event)
+	{
+	case QB_MAP_NOTIFY_DELETED:
+		if (new_val.type == ICMAP_VALUETYPE_UINT32)
+			*param = 0;
+		totem_set_volatile_defaults((struct totem_config *)user_data, &error_string);
+		break;
+	case QB_MAP_NOTIFY_REPLACED:
+	case QB_MAP_NOTIFY_INSERTED:
+		if (new_val.type == ICMAP_VALUETYPE_UINT32)
+			memcpy(param, new_val.data, new_val.len);
+		/* Other value types not supported, or needed (yet) */
+		break;
+	default:
+		break;
+	}
+}
+
+static void totem_reload_notify(
+	int32_t event,
+	const char *key_name,
+	struct icmap_notify_value new_val,
+	struct icmap_notify_value old_val,
+	void *user_data)
+{
+	struct totem_config *totem_config = (struct totem_config *)user_data;
+	uint32_t local_node_pos;
+
+	/* Reload has completed */
+	if (*(uint8_t *)new_val.data == 0) {
+		int i, j;
+
+		/* Clear out udpu nodelist so we can put the new one in if neede */
+		for (i=0; i<totem_config->interface_count; i++) {
+			for (j=0; j<PROCESSOR_COUNT_MAX; j++) {
+				memset(&totem_config->interfaces[i].member_list[j], 0, sizeof(struct totem_ip_address));
+			}
+		}
+
+		put_nodelist_members_to_config (totem_config);
+		totem_volatile_config_read (totem_config);
+
+		/* Reinstate the local_node_pos */
+		local_node_pos = find_local_node_in_nodelist(totem_config);
+		if (local_node_pos != -1) {
+			icmap_set_uint32("nodelist.local_node_pos", local_node_pos);
+		}
+	}
 }
 
 static void add_totem_config_notification(struct totem_config *totem_config)
@@ -1119,4 +1236,10 @@ static void add_totem_config_notification(struct totem_config *totem_config)
 		totem_change_notify,
 		totem_config,
 		&icmap_track);
+
+	icmap_track_add("config.reload_in_progress",
+		ICMAP_TRACK_ADD | ICMAP_TRACK_MODIFY,
+		totem_reload_notify,
+		totem_config,
+		&icmap_track);
 }
diff --git a/include/corosync/cfg.h b/include/corosync/cfg.h
index d26d5d1..cacbd6a 100644
--- a/include/corosync/cfg.h
+++ b/include/corosync/cfg.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005 MontaVista Software, Inc.
- * Copyright (c) 2006-2012 Red Hat, Inc.
+ * Copyright (c) 2006-2013 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -157,6 +157,9 @@ corosync_cfg_local_get (
 	corosync_cfg_handle_t handle,
 	unsigned int *local_nodeid);
 
+cs_error_t corosync_cfg_reload_config (
+	corosync_cfg_handle_t handle);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/corosync/ipc_cfg.h b/include/corosync/ipc_cfg.h
index f5f6748..a12a847 100644
--- a/include/corosync/ipc_cfg.h
+++ b/include/corosync/ipc_cfg.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005 MontaVista Software, Inc.
- * Copyright (c) 2009-2012 Red Hat, Inc.
+ * Copyright (c) 2009-2013 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -55,7 +55,8 @@ enum req_lib_cfg_types {
 	MESSAGE_REQ_CFG_REPLYTOSHUTDOWN = 4,
 	MESSAGE_REQ_CFG_GET_NODE_ADDRS = 5,
 	MESSAGE_REQ_CFG_LOCAL_GET = 6,
-	MESSAGE_REQ_CFG_CRYPTO_SET = 7
+	MESSAGE_REQ_CFG_RELOAD_CONFIG = 7,
+	MESSAGE_REQ_CFG_CRYPTO_SET = 8
 };
 
 enum res_lib_cfg_types {
@@ -74,6 +75,7 @@ enum res_lib_cfg_types {
 	MESSAGE_RES_CFG_LOCAL_GET = 12,
 	MESSAGE_RES_CFG_REPLYTOSHUTDOWN = 13,
 	MESSAGE_RES_CFG_CRYPTO_SET = 14,
+	MESSAGE_RES_CFG_RELOAD_CONFIG = 15
 };
 
 struct req_lib_cfg_ringstatusget {
@@ -150,6 +152,14 @@ struct res_lib_cfg_local_get {
 	mar_uint32_t local_nodeid __attribute__((aligned(8)));
 };
 
+struct req_lib_cfg_reload_config {
+	struct qb_ipc_request_header header __attribute__((aligned(8)));
+};
+
+struct res_lib_cfg_reload_config {
+	struct qb_ipc_response_header header __attribute__((aligned(8)));
+};
+
 typedef enum {
 	AIS_AMF_ADMINISTRATIVETARGET_SERVICEUNIT = 0,
 	AIS_AMF_ADMINISTRATIVETARGET_SERVICEGROUP = 1,
diff --git a/lib/cfg.c b/lib/cfg.c
index d594324..7bb56de 100644
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002-2005 MontaVista Software, Inc.
- * Copyright (c) 2006-2011 Red Hat, Inc.
+ * Copyright (c) 2006-2013 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -620,3 +620,42 @@ error_exit:
 
 	return (error);
 }
+
+cs_error_t corosync_cfg_reload_config (
+	corosync_cfg_handle_t handle)
+{
+	cs_error_t error;
+	struct cfg_inst *cfg_inst;
+	struct iovec iov;
+	struct req_lib_cfg_reload_config req_lib_cfg_reload_config;
+	struct res_lib_cfg_reload_config res_lib_cfg_reload_config;
+
+	error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, handle, (void *)&cfg_inst));
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_reload_config.header.size = sizeof (struct qb_ipc_request_header);
+	req_lib_cfg_reload_config.header.id = MESSAGE_REQ_CFG_RELOAD_CONFIG;
+
+	iov.iov_base = (void *)&req_lib_cfg_reload_config;
+	iov.iov_len = sizeof (struct req_lib_cfg_reload_config);
+
+	error = qb_to_cs_error (qb_ipcc_sendv_recv (
+		cfg_inst->c,
+		&iov,
+		1,
+		&res_lib_cfg_reload_config,
+		sizeof (struct res_lib_cfg_reload_config), CS_IPC_TIMEOUT_MS));
+
+	if (error != CS_OK) {
+		goto error_exit;
+	}
+
+	error = res_lib_cfg_reload_config.header.error;
+
+error_exit:
+	(void)hdb_handle_put (&cfg_hdb, handle);
+
+	return (error);
+}
diff --git a/tools/corosync-cfgtool.c b/tools/corosync-cfgtool.c
index 12a66a7..07d318a 100644
--- a/tools/corosync-cfgtool.c
+++ b/tools/corosync-cfgtool.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2012 Red Hat, Inc.
+ * Copyright (c) 2006-2013 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -137,6 +137,29 @@ static void ringreenable_do (void)
 	(void)corosync_cfg_finalize (handle);
 }
 
+static void reload_config_do (void)
+{
+	cs_error_t result;
+	corosync_cfg_handle_t handle;
+
+	printf ("Reloading corosync.conf...\n");
+	result = corosync_cfg_initialize (&handle, NULL);
+	if (result != CS_OK) {
+		printf ("Could not initialize corosync configuration API error %d\n", result);
+		exit (1);
+	}
+
+	result = corosync_cfg_reload_config (handle);
+	if (result != CS_OK) {
+		printf ("Could not reload configuration %d\n", result);
+	}
+	else {
+		printf ("Done\n");
+	}
+
+	(void)corosync_cfg_finalize (handle);
+}
+
 static void shutdown_do(void)
 {
 	cs_error_t result;
@@ -232,11 +255,12 @@ static void usage_do (void)
 	printf ("\t\tre-enable redundant ring operation.\n");
 	printf ("\t-a\tDisplay the IP address(es) of a node\n");
 	printf ("\t-k\tKill a node identified by node id.\n");
+	printf ("\t-R\tReload corosync.conf on all nodes.\n");
 	printf ("\t-H\tShutdown corosync cleanly on this node.\n");
 }
 
 int main (int argc, char *argv[]) {
-	const char *options = "i:srk:a:hH";
+	const char *options = "i:srRk:a:hH";
 	int opt;
 	unsigned int nodeid;
 	char interface_name[128] = "";
@@ -253,6 +277,9 @@ int main (int argc, char *argv[]) {
 		case 's':
 			rc = ringstatusget_do (interface_name);
 			break;
+		case 'R':
+			reload_config_do ();
+			break;
 		case 'r':
 			ringreenable_do ();
 			break;
_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss

[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux