[PATCH 3/4] Reload: Add atomic reload to totemconfig

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

 



When a reload is in progress, wait until the whole thing has
finished before setting parameters

Signed-off-by: Christine Caulfield <ccaulfie@xxxxxxxxxx>
---
 exec/totemconfig.c | 335 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 229 insertions(+), 106 deletions(-)

diff --git a/exec/totemconfig.c b/exec/totemconfig.c
index 62daeaf..de63043 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 ICMAP_TRACK_DELETE:
+		if (new_val.type == ICMAP_VALUETYPE_UINT32)
+			*param = 0;
+		totem_set_volatile_defaults((struct totem_config *)user_data, &error_string);
+		break;
+	case ICMAP_TRACK_ADD:
+	case ICMAP_TRACK_MODIFY:
+		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);
 }
-- 
1.8.1.4

_______________________________________________
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