Re: [PATCH 3/3] votequorum: rearrange code

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

 



ACK

Reviewed-By: Christine Caulfield <ccaulfie@xxxxxxxxxx>

Chrissie

On 16/01/12 13:27, Fabio M. Di Nitto wrote:
From: "Fabio M. Di Nitto"<fdinitto@xxxxxxxxxx>

this commit has no functional changes or bugfixes.

Simply reorganize the code in more logical way and change function
names to be more consistent.

Signed-off-by: Fabio M. Di Nitto<fdinitto@xxxxxxxxxx>
---
:100644 100644 96ca5b4... 2e7b8f1... M	services/votequorum.c
  services/votequorum.c | 1426 +++++++++++++++++++++++++------------------------
  1 files changed, 736 insertions(+), 690 deletions(-)

diff --git a/services/votequorum.c b/services/votequorum.c
index 96ca5b4..2e7b8f1 100644
--- a/services/votequorum.c
+++ b/services/votequorum.c
@@ -50,9 +50,17 @@
  #include<corosync/icmap.h>
  #include<corosync/ipc_votequorum.h>

-#define VOTEQUORUM_MAJOR_VERSION 7
-#define VOTEQUORUM_MINOR_VERSION 0
-#define VOTEQUORUM_PATCH_VERSION 0
+LOGSYS_DECLARE_SUBSYS ("VOTEQ");
+
+/*
+ * interface with corosync
+ */
+
+static struct corosync_api_v1 *corosync_api;
+
+/*
+ * votequorum global config vars
+ */

  /*
   * Silly default to prevent accidents!
@@ -60,14 +68,73 @@
  #define DEFAULT_EXPECTED   1024
  #define DEFAULT_QDEV_POLL 10000
  #define DEFAULT_LEAVE_TMO 10000
+
+static unsigned int quorumdev_poll = DEFAULT_QDEV_POLL;
+static char quorum_device_name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
+
+static uint8_t two_node = 0;
+
+static uint8_t wait_for_all = 0;
+static uint8_t wait_for_all_status = 0;
+
+static uint8_t auto_tie_breaker = 0;
+static int lowest_node_id = -1;
+
  #define DEFAULT_LMS_WIN   10000
+static uint8_t last_man_standing = 0;
+static uint32_t last_man_standing_window = DEFAULT_LMS_WIN;

-LOGSYS_DECLARE_SUBSYS ("VOTEQ");
+/*
+ * votequorum_exec defines/structs/forward definitions
+ */

-enum quorum_message_req_types {
-	MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO  = 0,
-	MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE = 1,
-};
+struct req_exec_quorum_nodeinfo {
+	struct qb_ipc_request_header header __attribute__((aligned(8)));
+	unsigned int first_trans;
+	unsigned int votes;
+	unsigned int expected_votes;
+	unsigned int major_version;	/* Not backwards compatible */
+	unsigned int minor_version;	/* Backwards compatible */
+	unsigned int patch_version;	/* Backwards/forwards compatible */
+	unsigned int config_version;
+	unsigned int flags;
+	unsigned int wait_for_all_status;
+	unsigned int quorate;
+} __attribute__((packed));
+
+struct req_exec_quorum_reconfigure {
+	struct qb_ipc_request_header header __attribute__((aligned(8)));
+	unsigned int param;
+	unsigned int nodeid;
+	unsigned int value;
+} __attribute__((packed));
+
+/*
+ * votequorum_exec onwire version (via totem)
+ */
+
+#define VOTEQUORUM_MAJOR_VERSION 7
+#define VOTEQUORUM_MINOR_VERSION 0
+#define VOTEQUORUM_PATCH_VERSION 0
+
+/*
+ * votequorum_exec onwire messages (via totem)
+ */
+
+#define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO    0
+#define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE 1
+
+static void votequorum_exec_send_expectedvotes_notification(void);
+static int votequorum_exec_send_quorum_notification(void *conn, uint64_t context);
+
+#define VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES 1
+#define VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES     2
+
+static int votequorum_exec_send_reconfigure(int param, int nodeid, int value);
+
+/*
+ * votequorum internal node status/view
+ */

  #define NODE_FLAGS_BEENDOWN         1
  #define NODE_FLAGS_QDISK            8
@@ -95,39 +162,28 @@ struct cluster_node {
  	struct list_head list;
  };

+/*
+ * votequorum internal quorum status
+ */
+
  static int quorum;
  static int cluster_is_quorate;
  static int first_trans = 1;
-static unsigned int quorumdev_poll = DEFAULT_QDEV_POLL;

-static uint8_t two_node = 0;
-static uint8_t wait_for_all = 0;
-static uint8_t wait_for_all_status = 0;
-static uint8_t auto_tie_breaker = 0;
-static int lowest_node_id = -1;
-static uint8_t last_man_standing = 0;
-static uint32_t last_man_standing_window = DEFAULT_LMS_WIN;
-static int last_man_standing_timer_set = 0;
-static corosync_timer_handle_t last_man_standing_timer;
+/*
+ * votequorum membership data
+ */

  static struct cluster_node *us;
  static struct cluster_node *quorum_device = NULL;
-static char quorum_device_name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
-static corosync_timer_handle_t quorum_device_timer;
  static struct list_head cluster_members_list;
-static struct corosync_api_v1 *corosync_api;
-static struct list_head trackers_list;
  static unsigned int quorum_members[PROCESSOR_COUNT_MAX+1];
  static int quorum_members_entries = 0;
  static struct memb_ring_id quorum_ringid;

-#define max(a,b) (((a)>  (b)) ? (a) : (b))
-static struct cluster_node *find_node_by_nodeid(int nodeid);
-static struct cluster_node *allocate_node(int nodeid);
-
-#define list_iterate(v, head) \
-	for (v = (head)->next; v != head; v = v->next)
-
+/*
+ * votequorum tracking
+ */
  struct quorum_pd {
  	unsigned char track_flags;
  	int tracking_enabled;
@@ -136,33 +192,67 @@ struct quorum_pd {
  	void *conn;
  };

+static struct list_head trackers_list;
+
+/*
+ * votequorum timers
+ */
+
+static corosync_timer_handle_t quorum_device_timer;
+static corosync_timer_handle_t last_man_standing_timer;
+static int last_man_standing_timer_set = 0;
+
  /*
   * Service Interfaces required by service_message_handler struct
   */

  static void votequorum_init(struct corosync_api_v1 *api,
-			    quorum_set_quorate_fn_t report);
+			    quorum_set_quorate_fn_t q_set_quorate_fn);

-static void quorum_confchg_fn (
+static void votequorum_confchg_fn (
  	enum totem_configuration_type configuration_type,
  	const unsigned int *member_list, size_t member_list_entries,
  	const unsigned int *left_list, size_t left_list_entries,
  	const unsigned int *joined_list, size_t joined_list_entries,
  	const struct memb_ring_id *ring_id);

-static int votequorum_exec_init_fn (struct corosync_api_v1 *api);
+static quorum_set_quorate_fn_t quorum_callback;

-static int quorum_lib_init_fn (void *conn);
+/*
+ * votequorum_exec handler and definitions
+ */

-static int quorum_lib_exit_fn (void *conn);
+static int votequorum_exec_init_fn (struct corosync_api_v1 *api);

  static void message_handler_req_exec_votequorum_nodeinfo (
  	const void *message,
  	unsigned int nodeid);
+static void exec_votequorum_nodeinfo_endian_convert (void *message);

  static void message_handler_req_exec_votequorum_reconfigure (
  	const void *message,
  	unsigned int nodeid);
+static void exec_votequorum_reconfigure_endian_convert (void *message);
+
+static struct corosync_exec_handler votequorum_exec_engine[] =
+{
+	{ /* 0 */
+		.exec_handler_fn	= message_handler_req_exec_votequorum_nodeinfo,
+		.exec_endian_convert_fn	= exec_votequorum_nodeinfo_endian_convert
+	},
+	{ /* 1 */
+		.exec_handler_fn	= message_handler_req_exec_votequorum_reconfigure,
+		.exec_endian_convert_fn	= exec_votequorum_reconfigure_endian_convert
+	},
+};
+
+/*
+ * Library Handler and Functions Definitions
+ */
+
+static int quorum_lib_init_fn (void *conn);
+
+static int quorum_lib_exit_fn (void *conn);

  static void message_handler_req_lib_votequorum_getinfo (void *conn,
  							const void *message);
@@ -190,19 +280,6 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn,
  static void message_handler_req_lib_votequorum_trackstop (void *conn,
  							  const void *message);

-static int quorum_exec_send_nodeinfo(void);
-static int quorum_exec_send_reconfigure(int param, int nodeid, int value);
-
-static void exec_votequorum_nodeinfo_endian_convert (void *message);
-static void exec_votequorum_reconfigure_endian_convert (void *message);
-
-static void add_votequorum_config_notification(void);
-
-static void recalculate_quorum(int allow_decrease, int by_current_nodes);
-
-/*
- * Library Handler Definition
- */
  static struct corosync_lib_handler quorum_lib_service[] =
  {
  	{ /* 0 */
@@ -243,48 +320,35 @@ static struct corosync_lib_handler quorum_lib_service[] =
  	}
  };

-static struct corosync_exec_handler votequorum_exec_engine[] =
-{
-	{ /* 0 */
-		.exec_handler_fn	= message_handler_req_exec_votequorum_nodeinfo,
-		.exec_endian_convert_fn	= exec_votequorum_nodeinfo_endian_convert
-	},
-	{ /* 1 */
-		.exec_handler_fn	= message_handler_req_exec_votequorum_reconfigure,
-		.exec_endian_convert_fn	= exec_votequorum_reconfigure_endian_convert
-	},
-};
-
-static quorum_set_quorate_fn_t set_quorum;
-
  /*
- * lcrso object definition
+ * Dynamic loader/lcrso object definition
   */
+
  static struct quorum_services_api_ver1 votequorum_iface_ver0 = {
  	.init				= votequorum_init
  };

  static struct corosync_service_engine quorum_service_handler = {
-	.name					= "corosync votes quorum service v0.91",
-	.id					= VOTEQUORUM_SERVICE,
-	.private_data_size			= sizeof (struct quorum_pd),
-	.allow_inquorate			= CS_LIB_ALLOW_INQUORATE,
-	.flow_control				= COROSYNC_LIB_FLOW_CONTROL_REQUIRED,
-	.lib_init_fn				= quorum_lib_init_fn,
-	.lib_exit_fn				= quorum_lib_exit_fn,
-	.lib_engine				= quorum_lib_service,
-	.lib_engine_count			= sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler),
-	.exec_init_fn				= votequorum_exec_init_fn,
-	.exec_engine				= votequorum_exec_engine,
-	.exec_engine_count			= sizeof (votequorum_exec_engine) / sizeof (struct corosync_exec_handler),
-	.confchg_fn				= quorum_confchg_fn,
-	.sync_mode				= CS_SYNC_V1
+	.name				= "corosync votes quorum service v0.91",
+	.id				= VOTEQUORUM_SERVICE,
+	.private_data_size		= sizeof (struct quorum_pd),
+	.allow_inquorate		= CS_LIB_ALLOW_INQUORATE,
+	.flow_control			= COROSYNC_LIB_FLOW_CONTROL_REQUIRED,
+	.lib_init_fn			= quorum_lib_init_fn,
+	.lib_exit_fn			= quorum_lib_exit_fn,
+	.lib_engine			= quorum_lib_service,
+	.lib_engine_count		= sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler),
+	.exec_init_fn			= votequorum_exec_init_fn,
+	.exec_engine			= votequorum_exec_engine,
+	.exec_engine_count		= sizeof (votequorum_exec_engine) / sizeof (struct corosync_exec_handler),
+	.confchg_fn			= votequorum_confchg_fn,
+	.sync_mode			= CS_SYNC_V1
  };

-/*
- * Dynamic loader definition
- */
-static struct corosync_service_engine *quorum_get_service_handler_ver0 (void);
+static struct corosync_service_engine *quorum_get_service_handler_ver0 (void)
+{
+	return (&quorum_service_handler);
+}

  static struct corosync_service_engine_iface_ver0 quorum_service_handler_iface = {
  	.corosync_get_service_engine_ver0 = quorum_get_service_handler_ver0
@@ -320,12 +384,6 @@ static struct lcr_comp quorum_comp_ver0 = {
  	.ifaces				= corosync_quorum_ver0
  };

-
-static struct corosync_service_engine *quorum_get_service_handler_ver0 (void)
-{
-	return (&quorum_service_handler);
-}
-
  #ifdef COROSYNC_SOLARIS
  void corosync_lcr_component_register (void);
  void corosync_lcr_component_register (void) {
@@ -337,252 +395,89 @@ __attribute__ ((constructor)) static void corosync_lcr_component_register (void)
  	lcr_component_register (&quorum_comp_ver0);
  }

-static void votequorum_init(struct corosync_api_v1 *api,
-			    quorum_set_quorate_fn_t report)
-{
-	ENTER();
+/*
+ * common/utility macros/functions
+ */

-	set_quorum = report;
+#define max(a,b) (((a)>  (b)) ? (a) : (b))

-	icmap_get_uint8("quorum.wait_for_all",&wait_for_all);
-	icmap_get_uint8("quorum.auto_tie_breaker",&auto_tie_breaker);
-	icmap_get_uint8("quorum.last_man_standing",&last_man_standing);
-	icmap_get_uint32("quorum.last_man_standing_window",&last_man_standing_window);
+#define list_iterate(v, head) \
+	for (v = (head)->next; v != head; v = v->next)

-	/*
-	 * TODO: we need to know the lowest node-id in the cluster
-	 * current lack of node list with node-id's requires us to see all nodes
-	 * to determine which is the lowest.
-	 */
-	if (auto_tie_breaker) {
-		wait_for_all = 1;
-	}
+static void node_add_ordered(struct cluster_node *newnode)
+{
+	struct cluster_node *node = NULL;
+	struct list_head *tmp;
+	struct list_head *newlist =&newnode->list;

-	if (wait_for_all) {
-		wait_for_all_status = 1;
+	ENTER();
+
+	list_iterate(tmp,&cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		if (newnode->node_id<  node->node_id) {
+			break;
+		}
  	}

-	/* Load the library-servicing part of this module */
-	api->service_link_and_init(api, "corosync_votequorum_iface", 0);
+	if (!node) {
+		list_add(&newnode->list,&cluster_members_list);
+	} else {
+		newlist->prev = tmp->prev;
+		newlist->next = tmp;
+		tmp->prev->next = newlist;
+		tmp->prev = newlist;
+	}

  	LEAVE();
  }

-struct req_exec_quorum_nodeinfo {
-	struct qb_ipc_request_header header __attribute__((aligned(8)));
-	unsigned int first_trans;
-	unsigned int votes;
-	unsigned int expected_votes;
-	unsigned int major_version;	/* Not backwards compatible */
-	unsigned int minor_version;	/* Backwards compatible */
-	unsigned int patch_version;	/* Backwards/forwards compatible */
-	unsigned int config_version;
-	unsigned int flags;
-	unsigned int wait_for_all_status;
-	unsigned int quorate;
-} __attribute__((packed));
+static struct cluster_node *allocate_node(int nodeid)
+{
+	struct cluster_node *cl;

-/*
- * Parameters for RECONFIG command
- */
-#define RECONFIG_PARAM_EXPECTED_VOTES 1
-#define RECONFIG_PARAM_NODE_VOTES     2
+	ENTER();

-struct req_exec_quorum_reconfigure {
-	struct qb_ipc_request_header header __attribute__((aligned(8)));
-	unsigned int param;
-	unsigned int nodeid;
-	unsigned int value;
-} __attribute__((packed));
+	cl = malloc(sizeof(struct cluster_node));
+	if (cl) {
+		memset(cl, 0, sizeof(struct cluster_node));
+		cl->node_id = nodeid;
+		if (nodeid) {
+			node_add_ordered(cl);
+		}
+	}

-static void read_quorum_config(void)
+	LEAVE();
+
+	return cl;
+}
+
+static struct cluster_node *find_node_by_nodeid(int nodeid)
  {
-	int cluster_members = 0;
+	struct cluster_node *node;
  	struct list_head *tmp;

  	ENTER();

-	log_printf(LOGSYS_LEVEL_DEBUG, "Reading configuration\n");
-
-	if (icmap_get_uint32("quorum.expected_votes",&us->expected_votes) != CS_OK) {
-		us->expected_votes = DEFAULT_EXPECTED;
+	if (nodeid == NODEID_US) {
+		LEAVE();
+		return us;
  	}

-	if (icmap_get_uint32("quorum.votes",&us->votes) != CS_OK) {
-		us->votes = 1;
-	}
-
-	if (icmap_get_uint32("quorum.quorumdev_poll",&quorumdev_poll) != CS_OK) {
-		quorumdev_poll = DEFAULT_QDEV_POLL;
-	}
-
-	icmap_get_uint8("quorum.two_node",&two_node);
-
-	/*
-	 * two_node mode is invalid if there are more than 2 nodes in the cluster!
-	 */
-	list_iterate(tmp,&cluster_members_list) {
-		cluster_members++;
-        }
-
-	if (two_node&&  cluster_members>  2) {
-		log_printf(LOGSYS_LEVEL_WARNING, "quorum.two_node was set but there are more than 2 nodes in the cluster. It will be ignored.\n");
-		two_node = 0;
-	}
-
-	LEAVE();
-}
-
-static int votequorum_exec_init_fn (struct corosync_api_v1 *api)
-{
-#ifdef COROSYNC_SOLARIS
-	logsys_subsys_init();
-#endif
-
-	ENTER();
-
-	corosync_api = api;
-
-	list_init(&cluster_members_list);
-	list_init(&trackers_list);
-
-	/*
-	 * Allocate a cluster_node for us
-	 */
-	us = allocate_node(corosync_api->totem_nodeid_get());
-	if (!us) {
-		LEAVE();
-		return (1);
-	}
-
-	us->flags |= NODE_FLAGS_US;
-	us->state = NODESTATE_MEMBER;
-	us->expected_votes = DEFAULT_EXPECTED;
-	us->votes = 1;
-	time(&us->join_time);
-
-	read_quorum_config();
-	recalculate_quorum(0, 0);
-
-	/*
-	 * Listen for changes
-	 */
-	add_votequorum_config_notification();
-
-	/*
-	 * Start us off with one node
-	 */
-	quorum_exec_send_nodeinfo();
-
-	LEAVE();
-
-	return (0);
-}
-
-static int quorum_lib_exit_fn (void *conn)
-{
-	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
-
-	ENTER();
-
-	if (quorum_pd->tracking_enabled) {
-		list_del (&quorum_pd->list);
-		list_init (&quorum_pd->list);
-	}
-
-	LEAVE();
-
-	return (0);
-}
-
-
-static int send_quorum_notification(void *conn, uint64_t context)
-{
-	struct res_lib_votequorum_notification *res_lib_votequorum_notification;
-	struct list_head *tmp;
-	struct cluster_node *node;
-	int cluster_members = 0;
-	int i = 0;
-	int size;
-	char *buf;
-
-	ENTER();
-
-	list_iterate(tmp,&cluster_members_list) {
-		node = list_entry(tmp, struct cluster_node, list);
-		cluster_members++;
-        }
-	if (quorum_device) {
-		cluster_members++;
-	}
-
-	size = sizeof(struct res_lib_votequorum_notification) + sizeof(struct votequorum_node) * cluster_members;
-	buf = alloca(size);
-	if (!buf) {
+	if (nodeid == NODEID_QDEVICE) {
  		LEAVE();
-		return -1;
+		return quorum_device;
  	}

-	res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)buf;
-	res_lib_votequorum_notification->quorate = cluster_is_quorate;
-	res_lib_votequorum_notification->node_list_entries = cluster_members;
-	res_lib_votequorum_notification->context = context;
  	list_iterate(tmp,&cluster_members_list) {
  		node = list_entry(tmp, struct cluster_node, list);
-		res_lib_votequorum_notification->node_list[i].nodeid = node->node_id;
-		res_lib_votequorum_notification->node_list[i++].state = node->state;
-        }
-	if (quorum_device) {
-		res_lib_votequorum_notification->node_list[i].nodeid = 0;
-		res_lib_votequorum_notification->node_list[i++].state = quorum_device->state | 0x80;
-	}
-	res_lib_votequorum_notification->header.id = MESSAGE_RES_VOTEQUORUM_NOTIFICATION;
-	res_lib_votequorum_notification->header.size = size;
-	res_lib_votequorum_notification->header.error = CS_OK;
-
-	/* Send it to all interested parties */
-	if (conn) {
-		int ret = corosync_api->ipc_dispatch_send(conn, buf, size);
-		LEAVE();
-		return ret;
-	} else {
-		struct quorum_pd *qpd;
-
-		list_iterate(tmp,&trackers_list) {
-			qpd = list_entry(tmp, struct quorum_pd, list);
-			res_lib_votequorum_notification->context = qpd->tracking_context;
-			corosync_api->ipc_dispatch_send(qpd->conn, buf, size);
+		if (node->node_id == nodeid) {
+			LEAVE();
+			return node;
  		}
  	}

  	LEAVE();
-
-	return 0;
-}
-
-static void send_expectedvotes_notification(void)
-{
-	struct res_lib_votequorum_expectedvotes_notification res_lib_votequorum_expectedvotes_notification;
-	struct quorum_pd *qpd;
-	struct list_head *tmp;
-
-	ENTER();
-
-	log_printf(LOGSYS_LEVEL_DEBUG, "Sending expected votes callback\n");
-
-	res_lib_votequorum_expectedvotes_notification.header.id = MESSAGE_RES_VOTEQUORUM_EXPECTEDVOTES_NOTIFICATION;
-	res_lib_votequorum_expectedvotes_notification.header.size = sizeof(res_lib_votequorum_expectedvotes_notification);
-	res_lib_votequorum_expectedvotes_notification.header.error = CS_OK;
-	res_lib_votequorum_expectedvotes_notification.expected_votes = us->expected_votes;
-
-	list_iterate(tmp,&trackers_list) {
-		qpd = list_entry(tmp, struct quorum_pd, list);
-		res_lib_votequorum_expectedvotes_notification.context = qpd->tracking_context;
-		corosync_api->ipc_dispatch_send(qpd->conn,&res_lib_votequorum_expectedvotes_notification,
-						sizeof(struct res_lib_votequorum_expectedvotes_notification));
-	}
-
-	LEAVE();
+	return NULL;
  }

  static void get_lowest_node_id(void)
@@ -626,68 +521,9 @@ static int check_low_node_id_partition(void)
  	return found;
  }

-static void set_quorate(int total_votes)
-{
-	int quorate;
-	int quorum_change = 0;
-
-	ENTER();
-
-	/*
-	 * wait for all nodes to show up before granting quorum
-	 */
-
-	if ((wait_for_all)&&  (wait_for_all_status)) {
-		if (total_votes != us->expected_votes) {
-			log_printf(LOGSYS_LEVEL_NOTICE,
-				   "Waiting for all cluster members. "
-				   "Current votes: %d expected_votes: %d\n",
-				   total_votes, us->expected_votes);
-			cluster_is_quorate = 0;
-			return;
-		}
-		wait_for_all_status = 0;
-		get_lowest_node_id();
-	}
-
-	if (quorum>  total_votes) {
-		quorate = 0;
-	} else {
-		quorate = 1;
-	}
-
-	if ((auto_tie_breaker)&&
-	    (total_votes == (us->expected_votes / 2))&&
-	    (check_low_node_id_partition() == 1)) {
-		quorate = 1;
-	}
-
-	if (cluster_is_quorate&&  !quorate) {
-		quorum_change = 1;
-		log_printf(LOGSYS_LEVEL_DEBUG, "quorum lost, blocking activity\n");
-	}
-	if (!cluster_is_quorate&&  quorate) {
-		quorum_change = 1;
-		log_printf(LOGSYS_LEVEL_DEBUG, "quorum regained, resuming activity\n");
-	}
-
-	cluster_is_quorate = quorate;
-
-	if (wait_for_all) {
-		if (quorate) {
-			wait_for_all_status = 0;
-		} else {
-			wait_for_all_status = 1;
-		}
-	}
-
-	if (quorum_change) {
-		set_quorum(quorum_members, quorum_members_entries,
-			   cluster_is_quorate,&quorum_ringid);
-	}
-
-	LEAVE();
-}
+/*
+ * quorum calculation core bits
+ */

  static int calculate_quorum(int allow_decrease, int max_expected, unsigned int *ret_total_votes)
  {
@@ -760,121 +596,259 @@ static int calculate_quorum(int allow_decrease, int max_expected, unsigned int *
  	return newquorum;
  }

-/* Recalculate cluster quorum, set quorate and notify changes */
-static void recalculate_quorum(int allow_decrease, int by_current_nodes)
+static void are_we_quorate(int total_votes)
  {
-	unsigned int total_votes = 0;
-	int cluster_members = 0;
-	struct list_head *nodelist;
-	struct cluster_node *node;
+	int quorate;
+	int quorum_change = 0;

  	ENTER();

-	list_iterate(nodelist,&cluster_members_list) {
-		node = list_entry(nodelist, struct cluster_node, list);
-		if (node->state == NODESTATE_MEMBER) {
-			if (by_current_nodes) {
-				cluster_members++;
-			}
-			total_votes += node->votes;
-		}
-	}
-
  	/*
-	 * Keep expected_votes at the highest number of votes in the cluster
+	 * wait for all nodes to show up before granting quorum
  	 */
-	log_printf(LOGSYS_LEVEL_DEBUG, "total_votes=%d, expected_votes=%d\n", total_votes, us->expected_votes);
-	if (total_votes>  us->expected_votes) {
-		us->expected_votes = total_votes;
-		send_expectedvotes_notification();
-	}
-
-	quorum = calculate_quorum(allow_decrease, cluster_members,&total_votes);
-	set_quorate(total_votes);
-
-	send_quorum_notification(NULL, 0L);

-	LEAVE();
-}
+	if ((wait_for_all)&&  (wait_for_all_status)) {
+		if (total_votes != us->expected_votes) {
+			log_printf(LOGSYS_LEVEL_NOTICE,
+				   "Waiting for all cluster members. "
+				   "Current votes: %d expected_votes: %d\n",
+				   total_votes, us->expected_votes);
+			cluster_is_quorate = 0;
+			return;
+		}
+		wait_for_all_status = 0;
+		get_lowest_node_id();
+	}

-static void node_add_ordered(struct cluster_node *newnode)
-{
-	struct cluster_node *node = NULL;
-	struct list_head *tmp;
-	struct list_head *newlist =&newnode->list;
+	if (quorum>  total_votes) {
+		quorate = 0;
+	} else {
+		quorate = 1;
+	}

-	ENTER();
+	if ((auto_tie_breaker)&&
+	    (total_votes == (us->expected_votes / 2))&&
+	    (check_low_node_id_partition() == 1)) {
+		quorate = 1;
+	}

-	list_iterate(tmp,&cluster_members_list) {
-		node = list_entry(tmp, struct cluster_node, list);
-		if (newnode->node_id<  node->node_id) {
-			break;
+	if (cluster_is_quorate&&  !quorate) {
+		quorum_change = 1;
+		log_printf(LOGSYS_LEVEL_DEBUG, "quorum lost, blocking activity\n");
+	}
+	if (!cluster_is_quorate&&  quorate) {
+		quorum_change = 1;
+		log_printf(LOGSYS_LEVEL_DEBUG, "quorum regained, resuming activity\n");
+	}
+
+	cluster_is_quorate = quorate;
+
+	if (wait_for_all) {
+		if (quorate) {
+			wait_for_all_status = 0;
+		} else {
+			wait_for_all_status = 1;
  		}
  	}

-	if (!node) {
-		list_add(&newnode->list,&cluster_members_list);
-	} else {
-		newlist->prev = tmp->prev;
-		newlist->next = tmp;
-		tmp->prev->next = newlist;
-		tmp->prev = newlist;
+	if (quorum_change) {
+		quorum_callback(quorum_members, quorum_members_entries,
+				cluster_is_quorate,&quorum_ringid);
  	}

  	LEAVE();
  }

-static struct cluster_node *allocate_node(int nodeid)
+/* Recalculate cluster quorum, set quorate and notify changes */
+static void recalculate_quorum(int allow_decrease, int by_current_nodes)
  {
-	struct cluster_node *cl;
+	unsigned int total_votes = 0;
+	int cluster_members = 0;
+	struct list_head *nodelist;
+	struct cluster_node *node;

  	ENTER();

-	cl = malloc(sizeof(struct cluster_node));
-	if (cl) {
-		memset(cl, 0, sizeof(struct cluster_node));
-		cl->node_id = nodeid;
-		if (nodeid) {
-			node_add_ordered(cl);
+	list_iterate(nodelist,&cluster_members_list) {
+		node = list_entry(nodelist, struct cluster_node, list);
+		if (node->state == NODESTATE_MEMBER) {
+			if (by_current_nodes) {
+				cluster_members++;
+			}
+			total_votes += node->votes;
  		}
  	}

+	/*
+	 * Keep expected_votes at the highest number of votes in the cluster
+	 */
+	log_printf(LOGSYS_LEVEL_DEBUG, "total_votes=%d, expected_votes=%d\n", total_votes, us->expected_votes);
+	if (total_votes>  us->expected_votes) {
+		us->expected_votes = total_votes;
+		votequorum_exec_send_expectedvotes_notification();
+	}
+
+	quorum = calculate_quorum(allow_decrease, cluster_members,&total_votes);
+	are_we_quorate(total_votes);
+
+	votequorum_exec_send_quorum_notification(NULL, 0L);
+
  	LEAVE();
+}

-	return cl;
+/*
+ * configuration bits and pieces
+ */
+
+/*
+ * votequorum_readconfig_static is executed before
+ * votequorum_readconfig_dynamic
+ */
+
+static void votequorum_readconfig_static(void)
+{
+	icmap_get_uint8("quorum.wait_for_all",&wait_for_all);
+	icmap_get_uint8("quorum.auto_tie_breaker",&auto_tie_breaker);
+	icmap_get_uint8("quorum.last_man_standing",&last_man_standing);
+	icmap_get_uint32("quorum.last_man_standing_window",&last_man_standing_window);
+
+	/*
+	 * TODO: we need to know the lowest node-id in the cluster
+	 * current lack of node list with node-id's requires us to see all nodes
+	 * to determine which is the lowest.
+	 */
+	if (auto_tie_breaker) {
+		wait_for_all = 1;
+	}
+
+	if (wait_for_all) {
+		wait_for_all_status = 1;
+	}
  }

-static struct cluster_node *find_node_by_nodeid(int nodeid)
+static void votequorum_readconfig_dynamic(void)
  {
-	struct cluster_node *node;
+	int cluster_members = 0;
  	struct list_head *tmp;

  	ENTER();

-	if (nodeid == NODEID_US) {
-		LEAVE();
-		return us;
+	log_printf(LOGSYS_LEVEL_DEBUG, "Reading configuration\n");
+
+	/*
+	 * TODO: add votequorum_parse_nodelist();
+	 */
+
+	if (icmap_get_uint32("quorum.expected_votes",&us->expected_votes) != CS_OK) {
+		us->expected_votes = DEFAULT_EXPECTED;
  	}

-	if (nodeid == NODEID_QDEVICE) {
-		LEAVE();
-		return quorum_device;
+	if (icmap_get_uint32("quorum.votes",&us->votes) != CS_OK) {
+		us->votes = 1;
  	}

+	if (icmap_get_uint32("quorum.quorumdev_poll",&quorumdev_poll) != CS_OK) {
+		quorumdev_poll = DEFAULT_QDEV_POLL;
+	}
+
+	icmap_get_uint8("quorum.two_node",&two_node);
+
+	/*
+	 * two_node mode is invalid if there are more than 2 nodes in the cluster!
+	 */
  	list_iterate(tmp,&cluster_members_list) {
-		node = list_entry(tmp, struct cluster_node, list);
-		if (node->node_id == nodeid) {
-			LEAVE();
-			return node;
-		}
+		cluster_members++;
+        }
+
+	if (two_node&&  cluster_members>  2) {
+		log_printf(LOGSYS_LEVEL_WARNING, "quorum.two_node was set but there are more than 2 nodes in the cluster. It will be ignored.\n");
+		two_node = 0;
  	}

  	LEAVE();
-	return NULL;
  }

+static void votequorum_refresh_config(
+	int32_t event,
+	const char *key_name,
+	struct icmap_notify_value new_val,
+	struct icmap_notify_value old_val,
+	void *user_data)
+{
+	unsigned int old_votes;
+	unsigned int old_expected;
+
+	ENTER();
+
+	old_votes = us->votes;
+	old_expected = us->expected_votes;
+
+	/*
+	 * Reload the configuration
+	 */
+	votequorum_readconfig_dynamic();

-static int quorum_exec_send_nodeinfo()
+	/*
+	 * Check for fundamental changes that we need to propogate
+	 */
+	if (old_votes != us->votes) {
+		votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES, us->node_id, us->votes);
+	}
+	if (old_expected != us->expected_votes) {
+		votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, us->expected_votes);
+	}
+
+	LEAVE();
+}
+
+static void votequorum_exec_add_config_notification(void)
+{
+	icmap_track_t icmap_track;
+
+	ENTER();
+
+	/*
+	 * TODO: add track for nodeslist
+	 */
+
+	icmap_track_add("quorum.",
+		ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX,
+		votequorum_refresh_config,
+		NULL,
+		&icmap_track);
+
+	LEAVE();
+}
+
+/*
+ * votequorum_exec core
+ */
+
+static int votequorum_exec_send_reconfigure(int param, int nodeid, int value)
+{
+	struct req_exec_quorum_reconfigure req_exec_quorum_reconfigure;
+	struct iovec iov[1];
+	int ret;
+
+	ENTER();
+
+	req_exec_quorum_reconfigure.param = param;
+	req_exec_quorum_reconfigure.nodeid = nodeid;
+	req_exec_quorum_reconfigure.value = value;
+
+	req_exec_quorum_reconfigure.header.id = SERVICE_ID_MAKE(VOTEQUORUM_SERVICE, MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE);
+	req_exec_quorum_reconfigure.header.size = sizeof(req_exec_quorum_reconfigure);
+
+	iov[0].iov_base = (void *)&req_exec_quorum_reconfigure;
+	iov[0].iov_len = sizeof(req_exec_quorum_reconfigure);
+
+	ret = corosync_api->totem_mcast (iov, 1, TOTEM_AGREED);
+
+	LEAVE();
+	return ret;
+}
+
+static int votequorum_exec_send_nodeinfo(void)
  {
  	struct req_exec_quorum_nodeinfo req_exec_quorum_nodeinfo;
  	struct iovec iov[1];
@@ -904,32 +878,293 @@ static int quorum_exec_send_nodeinfo()
  	return ret;
  }

+static int votequorum_exec_send_quorum_notification(void *conn, uint64_t context)
+{
+	struct res_lib_votequorum_notification *res_lib_votequorum_notification;
+	struct list_head *tmp;
+	struct cluster_node *node;
+	int cluster_members = 0;
+	int i = 0;
+	int size;
+	char *buf;
+
+	ENTER();
+
+	list_iterate(tmp,&cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		cluster_members++;
+        }
+	if (quorum_device) {
+		cluster_members++;
+	}
+
+	size = sizeof(struct res_lib_votequorum_notification) + sizeof(struct votequorum_node) * cluster_members;
+	buf = alloca(size);
+	if (!buf) {
+		LEAVE();
+		return -1;
+	}
+
+	res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)buf;
+	res_lib_votequorum_notification->quorate = cluster_is_quorate;
+	res_lib_votequorum_notification->node_list_entries = cluster_members;
+	res_lib_votequorum_notification->context = context;
+	list_iterate(tmp,&cluster_members_list) {
+		node = list_entry(tmp, struct cluster_node, list);
+		res_lib_votequorum_notification->node_list[i].nodeid = node->node_id;
+		res_lib_votequorum_notification->node_list[i++].state = node->state;
+        }
+	if (quorum_device) {
+		res_lib_votequorum_notification->node_list[i].nodeid = 0;
+		res_lib_votequorum_notification->node_list[i++].state = quorum_device->state | 0x80;
+	}
+	res_lib_votequorum_notification->header.id = MESSAGE_RES_VOTEQUORUM_NOTIFICATION;
+	res_lib_votequorum_notification->header.size = size;
+	res_lib_votequorum_notification->header.error = CS_OK;
+
+	/* Send it to all interested parties */
+	if (conn) {
+		int ret = corosync_api->ipc_dispatch_send(conn, buf, size);
+		LEAVE();
+		return ret;
+	} else {
+		struct quorum_pd *qpd;
+
+		list_iterate(tmp,&trackers_list) {
+			qpd = list_entry(tmp, struct quorum_pd, list);
+			res_lib_votequorum_notification->context = qpd->tracking_context;
+			corosync_api->ipc_dispatch_send(qpd->conn, buf, size);
+		}
+	}
+
+	LEAVE();
+
+	return 0;
+}
+
+static void votequorum_exec_send_expectedvotes_notification(void)
+{
+	struct res_lib_votequorum_expectedvotes_notification res_lib_votequorum_expectedvotes_notification;
+	struct quorum_pd *qpd;
+	struct list_head *tmp;
+
+	ENTER();
+
+	log_printf(LOGSYS_LEVEL_DEBUG, "Sending expected votes callback\n");
+
+	res_lib_votequorum_expectedvotes_notification.header.id = MESSAGE_RES_VOTEQUORUM_EXPECTEDVOTES_NOTIFICATION;
+	res_lib_votequorum_expectedvotes_notification.header.size = sizeof(res_lib_votequorum_expectedvotes_notification);
+	res_lib_votequorum_expectedvotes_notification.header.error = CS_OK;
+	res_lib_votequorum_expectedvotes_notification.expected_votes = us->expected_votes;
+
+	list_iterate(tmp,&trackers_list) {
+		qpd = list_entry(tmp, struct quorum_pd, list);
+		res_lib_votequorum_expectedvotes_notification.context = qpd->tracking_context;
+		corosync_api->ipc_dispatch_send(qpd->conn,&res_lib_votequorum_expectedvotes_notification,
+						sizeof(struct res_lib_votequorum_expectedvotes_notification));
+	}
+
+	LEAVE();
+}
+
+static void exec_votequorum_nodeinfo_endian_convert (void *message)
+{
+	struct req_exec_quorum_nodeinfo *nodeinfo = message;
+
+	ENTER();
+
+	nodeinfo->votes = swab32(nodeinfo->votes);
+	nodeinfo->expected_votes = swab32(nodeinfo->expected_votes);
+	nodeinfo->major_version = swab32(nodeinfo->major_version);
+	nodeinfo->minor_version = swab32(nodeinfo->minor_version);
+	nodeinfo->patch_version = swab32(nodeinfo->patch_version);
+	nodeinfo->config_version = swab32(nodeinfo->config_version);
+	nodeinfo->flags = swab32(nodeinfo->flags);
+	nodeinfo->wait_for_all_status = swab32(nodeinfo->wait_for_all_status);
+	nodeinfo->quorate = swab32(nodeinfo->quorate);

-static int quorum_exec_send_reconfigure(int param, int nodeid, int value)
+	LEAVE();
+}
+
+static void message_handler_req_exec_votequorum_nodeinfo (
+	const void *message,
+	unsigned int nodeid)
  {
-	struct req_exec_quorum_reconfigure req_exec_quorum_reconfigure;
-	struct iovec iov[1];
-	int ret;
+	const struct req_exec_quorum_nodeinfo *req_exec_quorum_nodeinfo = message;
+	struct cluster_node *node;
+	int old_votes;
+	int old_expected;
+	nodestate_t old_state;
+	int new_node = 0;

  	ENTER();

-	req_exec_quorum_reconfigure.param = param;
-	req_exec_quorum_reconfigure.nodeid = nodeid;
-	req_exec_quorum_reconfigure.value = value;
+	log_printf(LOGSYS_LEVEL_DEBUG, "got nodeinfo message from cluster node %d\n", nodeid);

-	req_exec_quorum_reconfigure.header.id = SERVICE_ID_MAKE(VOTEQUORUM_SERVICE, MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE);
-	req_exec_quorum_reconfigure.header.size = sizeof(req_exec_quorum_reconfigure);
+	node = find_node_by_nodeid(nodeid);
+	if (!node) {
+		node = allocate_node(nodeid);
+		new_node = 1;
+	}
+	if (!node) {
+		corosync_api->error_memory_failure();
+		LEAVE();
+		return;
+	}

-	iov[0].iov_base = (void *)&req_exec_quorum_reconfigure;
-	iov[0].iov_len = sizeof(req_exec_quorum_reconfigure);
+	old_votes = node->votes;
+	old_expected = node->expected_votes;
+	old_state = node->state;

-	ret = corosync_api->totem_mcast (iov, 1, TOTEM_AGREED);
+	/* Update node state */
+	node->votes = req_exec_quorum_nodeinfo->votes;
+	node->expected_votes = req_exec_quorum_nodeinfo->expected_votes;
+	node->state = NODESTATE_MEMBER;
+
+	log_printf(LOGSYS_LEVEL_DEBUG, "nodeinfo message: votes: %d, expected: %d wfa: %d quorate: %d\n",
+					req_exec_quorum_nodeinfo->votes,
+					req_exec_quorum_nodeinfo->expected_votes,
+					req_exec_quorum_nodeinfo->wait_for_all_status,
+					req_exec_quorum_nodeinfo->quorate);
+
+	if ((last_man_standing)&&  (req_exec_quorum_nodeinfo->votes>  1)) {
+		log_printf(LOGSYS_LEVEL_WARNING, "Last Man Standing feature is supported only when all"
+						 "cluster nodes votes are set to 1. Disabling LMS.");
+		last_man_standing = 0;
+		if (last_man_standing_timer_set) {
+			corosync_api->timer_delete(last_man_standing_timer);
+			last_man_standing_timer_set = 0;
+		}
+	}
+
+	node->flags&= ~NODE_FLAGS_BEENDOWN;
+
+	if (new_node ||
+	    req_exec_quorum_nodeinfo->first_trans ||
+	    old_votes != node->votes ||
+	    old_expected != node->expected_votes ||
+	    old_state != node->state) {
+		recalculate_quorum(0, 0);
+	}
+
+	if (!nodeid) {
+		free(node);
+	}
+
+	if ((wait_for_all)&&
+	    (!req_exec_quorum_nodeinfo->wait_for_all_status)&&
+	    (req_exec_quorum_nodeinfo->quorate)) {
+		wait_for_all_status = 0;
+	}
+
+	LEAVE();
+}
+
+static void exec_votequorum_reconfigure_endian_convert (void *message)
+{
+	struct req_exec_quorum_reconfigure *reconfigure = message;
+
+	ENTER();
+
+	reconfigure->nodeid = swab32(reconfigure->nodeid);
+	reconfigure->value = swab32(reconfigure->value);
+
+	LEAVE();
+}
+
+static void message_handler_req_exec_votequorum_reconfigure (
+	const void *message,
+	unsigned int nodeid)
+{
+	const struct req_exec_quorum_reconfigure *req_exec_quorum_reconfigure = message;
+	struct cluster_node *node;
+	struct list_head *nodelist;
+
+	ENTER();
+
+	log_printf(LOGSYS_LEVEL_DEBUG, "got reconfigure message from cluster node %d\n", nodeid);
+
+	node = find_node_by_nodeid(req_exec_quorum_reconfigure->nodeid);
+	if (!node) {
+		LEAVE();
+		return;
+	}
+
+	switch(req_exec_quorum_reconfigure->param)
+	{
+	case VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES:
+		list_iterate(nodelist,&cluster_members_list) {
+			node = list_entry(nodelist, struct cluster_node, list);
+			if (node->state == NODESTATE_MEMBER&&
+			    node->expected_votes>  req_exec_quorum_reconfigure->value) {
+				node->expected_votes = req_exec_quorum_reconfigure->value;
+			}
+		}
+		votequorum_exec_send_expectedvotes_notification();
+		recalculate_quorum(1, 0);  /* Allow decrease */
+		break;
+
+	case VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES:
+		node->votes = req_exec_quorum_reconfigure->value;
+		recalculate_quorum(1, 0);  /* Allow decrease */
+		break;
+
+	}
+
+	LEAVE();
+}
+
+static int votequorum_exec_init_fn (struct corosync_api_v1 *api)
+{
+#ifdef COROSYNC_SOLARIS
+	logsys_subsys_init();
+#endif
+
+	ENTER();
+
+	corosync_api = api;
+
+	list_init(&cluster_members_list);
+	list_init(&trackers_list);
+
+	/*
+	 * Allocate a cluster_node for us
+	 */
+	us = allocate_node(corosync_api->totem_nodeid_get());
+	if (!us) {
+		LEAVE();
+		return (1);
+	}
+
+	us->flags |= NODE_FLAGS_US;
+	us->state = NODESTATE_MEMBER;
+	us->expected_votes = DEFAULT_EXPECTED;
+	us->votes = 1;
+	time(&us->join_time);
+
+	votequorum_readconfig_dynamic();
+	recalculate_quorum(0, 0);
+
+	/*
+	 * Listen for changes
+	 */
+	votequorum_exec_add_config_notification();
+
+	/*
+	 * Start us off with one node
+	 */
+	votequorum_exec_send_nodeinfo();

  	LEAVE();
-	return ret;
+
+	return (0);
  }

-static void lms_timer_fn(void *arg)
+/*
+ * votequorum service core
+ */
+
+static void votequorum_last_man_standing_timer_fn(void *arg)
  {
  	ENTER();

@@ -941,7 +1176,7 @@ static void lms_timer_fn(void *arg)
  	LEAVE();
  }

-static void quorum_confchg_fn (
+static void votequorum_confchg_fn (
  	enum totem_configuration_type configuration_type,
  	const unsigned int *member_list, size_t member_list_entries,
  	const unsigned int *left_list, size_t left_list_entries,
@@ -978,7 +1213,9 @@ static void quorum_confchg_fn (
  				corosync_api->timer_delete(last_man_standing_timer);
  				last_man_standing_timer_set = 0;
  			}
-			corosync_api->timer_add_duration((unsigned long long)last_man_standing_window*1000000, NULL, lms_timer_fn,&last_man_standing_timer);
+			corosync_api->timer_add_duration((unsigned long long)last_man_standing_window*1000000,
+							 NULL, votequorum_last_man_standing_timer_fn,
+							&last_man_standing_timer);
  			last_man_standing_timer_set = 1;
  		}
  	}
@@ -989,7 +1226,7 @@ static void quorum_confchg_fn (
  		if (quorum_device) {
  			quorum_members[quorum_members_entries++] = 0;
  		}
-		quorum_exec_send_nodeinfo();
+		votequorum_exec_send_nodeinfo();
  	}

  	if (left_list_entries) {
@@ -999,176 +1236,91 @@ static void quorum_confchg_fn (
  	memcpy(&quorum_ringid, ring_id, sizeof(*ring_id));

  	if (configuration_type == TOTEM_CONFIGURATION_REGULAR) {
-		set_quorum(quorum_members, quorum_members_entries,
-			   cluster_is_quorate,&quorum_ringid);
+		quorum_callback(quorum_members, quorum_members_entries,
+				cluster_is_quorate,&quorum_ringid);
  	}

  	LEAVE();
  }

-static void exec_votequorum_nodeinfo_endian_convert (void *message)
+static void votequorum_init(struct corosync_api_v1 *api,
+			    quorum_set_quorate_fn_t q_set_quorate_fn)
  {
-	struct req_exec_quorum_nodeinfo *nodeinfo = message;
-
  	ENTER();

-	nodeinfo->votes = swab32(nodeinfo->votes);
-	nodeinfo->expected_votes = swab32(nodeinfo->expected_votes);
-	nodeinfo->major_version = swab32(nodeinfo->major_version);
-	nodeinfo->minor_version = swab32(nodeinfo->minor_version);
-	nodeinfo->patch_version = swab32(nodeinfo->patch_version);
-	nodeinfo->config_version = swab32(nodeinfo->config_version);
-	nodeinfo->flags = swab32(nodeinfo->flags);
-	nodeinfo->wait_for_all_status = swab32(nodeinfo->wait_for_all_status);
-	nodeinfo->quorate = swab32(nodeinfo->quorate);
+	quorum_callback = q_set_quorate_fn;
+
+	votequorum_readconfig_static();
+
+	/* Load the library-servicing part of this module */
+	api->service_link_and_init(api, "corosync_votequorum_iface", 0);

  	LEAVE();
  }

-static void exec_votequorum_reconfigure_endian_convert (void *message)
+/*
+ * Library Handler init/fini
+ */
+
+static int quorum_lib_init_fn (void *conn)
  {
-	struct req_exec_quorum_reconfigure *reconfigure = message;
+	struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);

  	ENTER();

-	reconfigure->nodeid = swab32(reconfigure->nodeid);
-	reconfigure->value = swab32(reconfigure->value);
+	list_init (&pd->list);
+	pd->conn = conn;

  	LEAVE();
+	return (0);
  }

-static void message_handler_req_exec_votequorum_nodeinfo (
-	const void *message,
-	unsigned int nodeid)
+static int quorum_lib_exit_fn (void *conn)
  {
-	const struct req_exec_quorum_nodeinfo *req_exec_quorum_nodeinfo = message;
-	struct cluster_node *node;
-	int old_votes;
-	int old_expected;
-	nodestate_t old_state;
-	int new_node = 0;
+	struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);

  	ENTER();

-	log_printf(LOGSYS_LEVEL_DEBUG, "got nodeinfo message from cluster node %d\n", nodeid);
-
-	node = find_node_by_nodeid(nodeid);
-	if (!node) {
-		node = allocate_node(nodeid);
-		new_node = 1;
-	}
-	if (!node) {
-		corosync_api->error_memory_failure();
-		LEAVE();
-		return;
-	}
-
-	old_votes = node->votes;
-	old_expected = node->expected_votes;
-	old_state = node->state;
-
-	/* Update node state */
-	node->votes = req_exec_quorum_nodeinfo->votes;
-	node->expected_votes = req_exec_quorum_nodeinfo->expected_votes;
-	node->state = NODESTATE_MEMBER;
-
-	log_printf(LOGSYS_LEVEL_DEBUG, "nodeinfo message: votes: %d, expected: %d wfa: %d quorate: %d\n",
-					req_exec_quorum_nodeinfo->votes,
-					req_exec_quorum_nodeinfo->expected_votes,
-					req_exec_quorum_nodeinfo->wait_for_all_status,
-					req_exec_quorum_nodeinfo->quorate);
-
-	if ((last_man_standing)&&  (req_exec_quorum_nodeinfo->votes>  1)) {
-		log_printf(LOGSYS_LEVEL_WARNING, "Last Man Standing feature is supported only when all"
-						 "cluster nodes votes are set to 1. Disabling LMS.");
-		last_man_standing = 0;
-		if (last_man_standing_timer_set) {
-			corosync_api->timer_delete(last_man_standing_timer);
-			last_man_standing_timer_set = 0;
-		}
-	}
-
-	node->flags&= ~NODE_FLAGS_BEENDOWN;
-
-	if (new_node ||
-	    req_exec_quorum_nodeinfo->first_trans ||
-	    old_votes != node->votes ||
-	    old_expected != node->expected_votes ||
-	    old_state != node->state) {
-		recalculate_quorum(0, 0);
-	}
-
-	if (!nodeid) {
-		free(node);
-	}
-
-	if ((wait_for_all)&&
-	    (!req_exec_quorum_nodeinfo->wait_for_all_status)&&
-	    (req_exec_quorum_nodeinfo->quorate)) {
-		wait_for_all_status = 0;
+	if (quorum_pd->tracking_enabled) {
+		list_del (&quorum_pd->list);
+		list_init (&quorum_pd->list);
  	}

  	LEAVE();
+
+	return (0);
  }

-static void message_handler_req_exec_votequorum_reconfigure (
-	const void *message,
-	unsigned int nodeid)
-{
-	const struct req_exec_quorum_reconfigure *req_exec_quorum_reconfigure = message;
-	struct cluster_node *node;
-	struct list_head *nodelist;
+/*
+ * library internal functions
+ */

+static void quorum_device_timer_fn(void *arg)
+{
  	ENTER();

-	log_printf(LOGSYS_LEVEL_DEBUG, "got reconfigure message from cluster node %d\n", nodeid);
-
-	node = find_node_by_nodeid(req_exec_quorum_reconfigure->nodeid);
-	if (!node) {
+	if (!quorum_device || quorum_device->state == NODESTATE_DEAD) {
  		LEAVE();
  		return;
  	}

-	switch(req_exec_quorum_reconfigure->param)
-	{
-	case RECONFIG_PARAM_EXPECTED_VOTES:
-		list_iterate(nodelist,&cluster_members_list) {
-			node = list_entry(nodelist, struct cluster_node, list);
-			if (node->state == NODESTATE_MEMBER&&
-			    node->expected_votes>  req_exec_quorum_reconfigure->value) {
-				node->expected_votes = req_exec_quorum_reconfigure->value;
-			}
-		}
-		send_expectedvotes_notification();
-		recalculate_quorum(1, 0);  /* Allow decrease */
-		break;
-
-	case RECONFIG_PARAM_NODE_VOTES:
-		node->votes = req_exec_quorum_reconfigure->value;
-		recalculate_quorum(1, 0);  /* Allow decrease */
-		break;
-
+	if ((quorum_device->last_hello / QB_TIME_NS_IN_SEC) + quorumdev_poll/1000<
+	    (qb_util_nano_current_get () / QB_TIME_NS_IN_SEC)) {
+		quorum_device->state = NODESTATE_DEAD;
+		log_printf(LOGSYS_LEVEL_INFO, "lost contact with quorum device\n");
+		recalculate_quorum(0, 0);
+	} else {
+		corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device,
+						 quorum_device_timer_fn,&quorum_device_timer);
  	}

  	LEAVE();
  }

-static int quorum_lib_init_fn (void *conn)
-{
-	struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn);
-
-	ENTER();
-
-	list_init (&pd->list);
-	pd->conn = conn;
-
-	LEAVE();
-	return (0);
-}
-
  /*
- * Message from the library
+ * Library Handler Functions
   */
+
  static void message_handler_req_lib_votequorum_getinfo (void *conn, const void *message)
  {
  	const struct req_lib_votequorum_getinfo *req_lib_votequorum_getinfo = message;
@@ -1238,9 +1390,6 @@ static void message_handler_req_lib_votequorum_getinfo (void *conn, const void *
  	LEAVE();
  }

-/*
- * Message from the library
- */
  static void message_handler_req_lib_votequorum_setexpected (void *conn, const void *message)
  {
  	const struct req_lib_votequorum_setexpected *req_lib_votequorum_setexpected = message;
@@ -1261,12 +1410,9 @@ static void message_handler_req_lib_votequorum_setexpected (void *conn, const vo
  		goto error_exit;
  	}

-	quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id,
-				     req_lib_votequorum_setexpected->expected_votes);
+	votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES, us->node_id,
+					 req_lib_votequorum_setexpected->expected_votes);

-	/*
-	 * send status
-	 */
  error_exit:
  	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
  	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
@@ -1276,9 +1422,6 @@ error_exit:
  	LEAVE();
  }

-/*
- * Message from the library
- */
  static void message_handler_req_lib_votequorum_setvotes (void *conn, const void *message)
  {
  	const struct req_lib_votequorum_setvotes *req_lib_votequorum_setvotes = message;
@@ -1318,12 +1461,9 @@ static void message_handler_req_lib_votequorum_setvotes (void *conn, const void
  		nodeid = corosync_api->totem_nodeid_get();
  	}

-	quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, nodeid,
-				     req_lib_votequorum_setvotes->votes);
+	votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES, nodeid,
+					 req_lib_votequorum_setvotes->votes);

-	/*
-	 * send status
-	 */
  error_exit:
  	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
  	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
@@ -1333,28 +1473,6 @@ error_exit:
  	LEAVE();
  }

-static void quorum_device_timer_fn(void *arg)
-{
-	ENTER();
-
-	if (!quorum_device || quorum_device->state == NODESTATE_DEAD) {
-		LEAVE();
-		return;
-	}
-
-	if ((quorum_device->last_hello / QB_TIME_NS_IN_SEC) + quorumdev_poll/1000<
-	    (qb_util_nano_current_get () / QB_TIME_NS_IN_SEC)) {
-		quorum_device->state = NODESTATE_DEAD;
-		log_printf(LOGSYS_LEVEL_INFO, "lost contact with quorum device\n");
-		recalculate_quorum(0, 0);
-	} else {
-		corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device,
-						 quorum_device_timer_fn,&quorum_device_timer);
-	}
-
-	LEAVE();
-}
-
  static void message_handler_req_lib_votequorum_qdisk_register (void *conn,
  							       const void *message)
  {
@@ -1374,9 +1492,6 @@ static void message_handler_req_lib_votequorum_qdisk_register (void *conn,
  		list_add(&quorum_device->list,&cluster_members_list);
  	}

-	/*
-	 * send status
-	 */
  	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
  	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
  	res_lib_votequorum_status.header.error = error;
@@ -1404,9 +1519,6 @@ static void message_handler_req_lib_votequorum_qdisk_unregister (void *conn,
  		error = CS_ERR_NOT_EXIST;
  	}

-	/*
-	 * send status
-	 */
  	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
  	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
  	res_lib_votequorum_status.header.error = error;
@@ -1477,9 +1589,6 @@ static void message_handler_req_lib_votequorum_qdisk_getinfo (void *conn,
  		error = CS_ERR_NOT_EXIST;
  	}

-	/*
-	 * send status
-	 */
  	res_lib_votequorum_qdisk_getinfo.header.size = sizeof(res_lib_votequorum_qdisk_getinfo);
  	res_lib_votequorum_qdisk_getinfo.header.id = MESSAGE_RES_VOTEQUORUM_GETINFO;
  	res_lib_votequorum_qdisk_getinfo.header.error = error;
@@ -1503,7 +1612,7 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn,
  	if (req_lib_votequorum_trackstart->track_flags&  CS_TRACK_CURRENT ||
  	    req_lib_votequorum_trackstart->track_flags&  CS_TRACK_CHANGES) {
  		log_printf(LOGSYS_LEVEL_DEBUG, "sending initial status to %p\n", conn);
-		send_quorum_notification(conn, req_lib_votequorum_trackstart->context);
+		votequorum_exec_send_quorum_notification(conn, req_lib_votequorum_trackstart->context);
  	}

  	/*
@@ -1519,9 +1628,6 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn,
  		list_add (&quorum_pd->list,&trackers_list);
  	}

-	/*
-	 * Send status
-	 */
  	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
  	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
  	res_lib_votequorum_status.header.error = CS_OK;
@@ -1548,9 +1654,6 @@ static void message_handler_req_lib_votequorum_trackstop (void *conn,
  		error = CS_ERR_NOT_EXIST;
  	}

-	/*
-	 * send status
-	 */
  	res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status);
  	res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS;
  	res_lib_votequorum_status.header.error = error;
@@ -1558,60 +1661,3 @@ static void message_handler_req_lib_votequorum_trackstop (void *conn,

  	LEAVE();
  }
-
-static void reread_config(void)
-{
-	unsigned int old_votes;
-	unsigned int old_expected;
-
-	ENTER();
-
-	old_votes = us->votes;
-	old_expected = us->expected_votes;
-
-	/*
-	 * Reload the configuration
-	 */
-	read_quorum_config();
-
-	/*
-	 * Check for fundamental changes that we need to propogate
-	 */
-	if (old_votes != us->votes) {
-		quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, us->node_id, us->votes);
-	}
-	if (old_expected != us->expected_votes) {
-		quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, us->expected_votes);
-	}
-
-	LEAVE();
-}
-
-static void key_change_quorum(
-	int32_t event,
-	const char *key_name,
-	struct icmap_notify_value new_val,
-	struct icmap_notify_value old_val,
-	void *user_data)
-{
-	ENTER();
-
-	reread_config();
-
-	LEAVE();
-}
-
-static void add_votequorum_config_notification(void)
-{
-	icmap_track_t icmap_track;
-
-	ENTER();
-
-	icmap_track_add("quorum.",
-		ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX,
-		key_change_quorum,
-		NULL,
-		&icmap_track);
-
-	LEAVE();
-}

_______________________________________________
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