From: "Fabio M. Di Nitto" <fdinitto@xxxxxxxxxx> this change should address the last issues, reduce again size of the onwire and make registration atomic and safe. Similar approach is used for unregister. qdevice name update/reconfigure is only partially implemented, but some bits are stubs. Signed-off-by: Fabio M. Di Nitto <fdinitto@xxxxxxxxxx> --- exec/votequorum.c | 290 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 250 insertions(+), 40 deletions(-) diff --git a/exec/votequorum.c b/exec/votequorum.c index 3765a69..a5c9883 100644 --- a/exec/votequorum.c +++ b/exec/votequorum.c @@ -64,10 +64,12 @@ static struct corosync_api_v1 *corosync_api; #define DEFAULT_QDEVICE_TIMEOUT 10000 +static char qdevice_name[VOTEQUORUM_MAX_QDEVICE_NAME_LEN]; static struct cluster_node *qdevice = NULL; static unsigned int qdevice_timeout = DEFAULT_QDEVICE_TIMEOUT; static uint8_t qdevice_can_operate = 1; static uint8_t qdevice_is_registered = 0; +static void *qdevice_reg_conn = NULL; static uint8_t two_node = 0; @@ -94,7 +96,6 @@ struct req_exec_quorum_nodeinfo { uint32_t votes; uint32_t expected_votes; uint32_t flags; - char qdevice_name[VOTEQUORUM_MAX_QDEVICE_NAME_LEN]; } __attribute__((packed)); struct req_exec_quorum_reconfigure { @@ -107,6 +108,18 @@ struct req_exec_quorum_reconfigure { uint8_t _pad2; } __attribute__((packed)); +struct req_exec_quorum_qdevice_reg { + struct qb_ipc_request_header header __attribute__((aligned(8))); + uint32_t operation; + char qdevice_name[VOTEQUORUM_MAX_QDEVICE_NAME_LEN]; +} __attribute__((packed)); + +struct req_exec_quorum_qdevice_reconfigure { + struct qb_ipc_request_header header __attribute__((aligned(8))); + char oldname[VOTEQUORUM_MAX_QDEVICE_NAME_LEN]; + char newname[VOTEQUORUM_MAX_QDEVICE_NAME_LEN]; +} __attribute__((packed)); + /* * votequorum_exec onwire version (via totem) */ @@ -117,8 +130,10 @@ struct req_exec_quorum_reconfigure { * votequorum_exec onwire messages (via totem) */ -#define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO 0 -#define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE 1 +#define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO 0 +#define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE 1 +#define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_REG 2 +#define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_RECONFIGURE 3 static void votequorum_exec_send_expectedvotes_notification(void); static int votequorum_exec_send_quorum_notification(void *conn, uint64_t context); @@ -129,6 +144,12 @@ static int votequorum_exec_send_quorum_notification(void *conn, uint64_t context static int votequorum_exec_send_reconfigure(uint8_t param, unsigned int nodeid, uint32_t value); /* + * used by req_exec_quorum_qdevice_reg + */ +#define VOTEQUORUM_QDEVICE_OPERATION_UNREGISTER 0 +#define VOTEQUORUM_QDEVICE_OPERATION_REGISTER 1 + +/* * votequorum internal node status/view */ @@ -153,7 +174,6 @@ struct cluster_node { uint32_t votes; uint32_t expected_votes; uint32_t flags; - char qdevice_name[VOTEQUORUM_MAX_QDEVICE_NAME_LEN]; struct list_head list; }; @@ -227,6 +247,16 @@ static void message_handler_req_exec_votequorum_reconfigure ( unsigned int nodeid); static void exec_votequorum_reconfigure_endian_convert (void *message); +static void message_handler_req_exec_votequorum_qdevice_reg ( + const void *message, + unsigned int nodeid); +static void exec_votequorum_qdevice_reg_endian_convert (void *message); + +static void message_handler_req_exec_votequorum_qdevice_reconfigure ( + const void *message, + unsigned int nodeid); +static void exec_votequorum_qdevice_reconfigure_endian_convert (void *message); + static struct corosync_exec_handler votequorum_exec_engine[] = { { /* 0 */ @@ -237,6 +267,14 @@ static struct corosync_exec_handler votequorum_exec_engine[] = .exec_handler_fn = message_handler_req_exec_votequorum_reconfigure, .exec_endian_convert_fn = exec_votequorum_reconfigure_endian_convert }, + { /* 2 */ + .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reg, + .exec_endian_convert_fn = exec_votequorum_qdevice_reg_endian_convert + }, + { /* 3 */ + .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reconfigure, + .exec_endian_convert_fn = exec_votequorum_qdevice_reconfigure_endian_convert + }, }; /* @@ -1144,11 +1182,6 @@ static int votequorum_exec_send_nodeinfo(uint32_t nodeid) req_exec_quorum_nodeinfo.votes = node->votes; req_exec_quorum_nodeinfo.expected_votes = node->expected_votes; req_exec_quorum_nodeinfo.flags = node->flags; - if ((nodeid != NODEID_QDEVICE) && (qdevice_is_registered)) { - strcpy(req_exec_quorum_nodeinfo.qdevice_name, qdevice->qdevice_name); - } else { - memset(req_exec_quorum_nodeinfo.qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); - } req_exec_quorum_nodeinfo.header.id = SERVICE_ID_MAKE(VOTEQUORUM_SERVICE, MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO); req_exec_quorum_nodeinfo.header.size = sizeof(req_exec_quorum_nodeinfo); @@ -1162,6 +1195,50 @@ static int votequorum_exec_send_nodeinfo(uint32_t nodeid) return ret; } +static int votequorum_exec_send_qdevice_reconfigure(const char *oldname, const char *newname) +{ + struct req_exec_quorum_qdevice_reconfigure req_exec_quorum_qdevice_reconfigure; + struct iovec iov[1]; + int ret; + + ENTER(); + + req_exec_quorum_qdevice_reconfigure.header.id = SERVICE_ID_MAKE(VOTEQUORUM_SERVICE, MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_RECONFIGURE); + req_exec_quorum_qdevice_reconfigure.header.size = sizeof(req_exec_quorum_qdevice_reconfigure); + strcpy(req_exec_quorum_qdevice_reconfigure.oldname, oldname); + strcpy(req_exec_quorum_qdevice_reconfigure.newname, newname); + + iov[0].iov_base = (void *)&req_exec_quorum_qdevice_reconfigure; + iov[0].iov_len = sizeof(req_exec_quorum_qdevice_reconfigure); + + ret = corosync_api->totem_mcast (iov, 1, TOTEM_AGREED); + + LEAVE(); + return ret; +} + +static int votequorum_exec_send_qdevice_reg(uint32_t operation, const char *qdevice_name_req) +{ + struct req_exec_quorum_qdevice_reg req_exec_quorum_qdevice_reg; + struct iovec iov[1]; + int ret; + + ENTER(); + + req_exec_quorum_qdevice_reg.header.id = SERVICE_ID_MAKE(VOTEQUORUM_SERVICE, MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_REG); + req_exec_quorum_qdevice_reg.header.size = sizeof(req_exec_quorum_qdevice_reg); + req_exec_quorum_qdevice_reg.operation = operation; + strcpy(req_exec_quorum_qdevice_reg.qdevice_name, qdevice_name_req); + + iov[0].iov_base = (void *)&req_exec_quorum_qdevice_reg; + iov[0].iov_len = sizeof(req_exec_quorum_qdevice_reg); + + ret = corosync_api->totem_mcast (iov, 1, TOTEM_AGREED); + + LEAVE(); + return ret; +} + static int votequorum_exec_send_quorum_notification(void *conn, uint64_t context) { struct res_lib_votequorum_notification *res_lib_votequorum_notification; @@ -1251,6 +1328,136 @@ static void votequorum_exec_send_expectedvotes_notification(void) LEAVE(); } +static void exec_votequorum_qdevice_reconfigure_endian_convert (void *message) +{ + ENTER(); + + LEAVE(); +} + +static void message_handler_req_exec_votequorum_qdevice_reconfigure ( + const void *message, + unsigned int nodeid) +{ + const struct req_exec_quorum_qdevice_reconfigure *req_exec_quorum_qdevice_reconfigure = message; + + ENTER(); + + log_printf(LOGSYS_LEVEL_DEBUG, "Received qdevice name change req from node %u [from: %s to: %s]", + nodeid, + req_exec_quorum_qdevice_reconfigure->oldname, + req_exec_quorum_qdevice_reconfigure->newname); + + if (!strcmp(req_exec_quorum_qdevice_reconfigure->oldname, qdevice_name)) { + log_printf(LOGSYS_LEVEL_DEBUG, "Allowing qdevice rename"); + memset(qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); + strcpy(qdevice_name, req_exec_quorum_qdevice_reconfigure->newname); + /* + * TODO: notify qdevices about name change? + * this is not relevant for now and can wait later on since + * qdevices are local only and libvotequorum is not final + */ + } + + LEAVE(); +} + +static void exec_votequorum_qdevice_reg_endian_convert (void *message) +{ + struct req_exec_quorum_qdevice_reg *req_exec_quorum_qdevice_reg = message; + + ENTER(); + + req_exec_quorum_qdevice_reg->operation = swab32(req_exec_quorum_qdevice_reg->operation); + + LEAVE(); +} + +static void message_handler_req_exec_votequorum_qdevice_reg ( + const void *message, + unsigned int nodeid) +{ + const struct req_exec_quorum_qdevice_reg *req_exec_quorum_qdevice_reg = message; + struct res_lib_votequorum_status res_lib_votequorum_status; + int wipe_qdevice_name = 1; + struct cluster_node *node = NULL; + struct list_head *tmp; + cs_error_t error = CS_OK; + + ENTER(); + + log_printf(LOGSYS_LEVEL_DEBUG, "Received qdevice op %u req from node %u [%s]", + req_exec_quorum_qdevice_reg->operation, + nodeid, req_exec_quorum_qdevice_reg->qdevice_name); + + switch(req_exec_quorum_qdevice_reg->operation) + { + case VOTEQUORUM_QDEVICE_OPERATION_REGISTER: + if (nodeid != us->node_id) { + if (!strlen(qdevice_name)) { + log_printf(LOGSYS_LEVEL_DEBUG, "Remote qdevice name recorded"); + strcpy(qdevice_name, req_exec_quorum_qdevice_reg->qdevice_name); + } + LEAVE(); + return; + } + + /* + * this should NEVER happen + */ + if (!qdevice_reg_conn) { + log_printf(LOGSYS_LEVEL_WARNING, "Unable to determine origin of the qdevice register call!"); + LEAVE(); + return; + } + + /* + * registering our own device in this case + */ + if (!strlen(qdevice_name)) { + strcpy(qdevice_name, req_exec_quorum_qdevice_reg->qdevice_name); + } + + /* + * check if it is our device or something else + */ + if ((!strncmp(req_exec_quorum_qdevice_reg->qdevice_name, + qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN))) { + qdevice_is_registered = 1; + us->flags |= NODE_FLAGS_QDEVICE; + votequorum_exec_send_nodeinfo(NODEID_QDEVICE); + votequorum_exec_send_nodeinfo(us->node_id); + } else { + log_printf(LOGSYS_LEVEL_WARNING, + "A new qdevice with different name (new: %s old: %s) is trying to register!", + req_exec_quorum_qdevice_reg->qdevice_name, qdevice_name); + error = CS_ERR_EXIST; + } + + 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; + corosync_api->ipc_response_send(qdevice_reg_conn, &res_lib_votequorum_status, sizeof(res_lib_votequorum_status)); + qdevice_reg_conn = NULL; + break; + case VOTEQUORUM_QDEVICE_OPERATION_UNREGISTER: + list_iterate(tmp, &cluster_members_list) { + node = list_entry(tmp, struct cluster_node, list); + if ((node->state == NODESTATE_MEMBER) && + (node->flags & NODE_FLAGS_QDEVICE)) { + wipe_qdevice_name = 0; + } + } + + if (wipe_qdevice_name) { + memset(qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); + } + + break; + } + LEAVE(); +} + static void exec_votequorum_nodeinfo_endian_convert (void *message) { struct req_exec_quorum_nodeinfo *nodeinfo = message; @@ -1317,19 +1524,6 @@ static void message_handler_req_exec_votequorum_nodeinfo ( if (nodeid != NODEID_QDEVICE) { node->votes = req_exec_quorum_nodeinfo->votes; - - memset(node->qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); - if (node->flags & NODE_FLAGS_QDEVICE) { - int state = 0; - - if (node->flags & NODE_FLAGS_QDEVICE_STATE) { - state = 1; - } - - strcpy(node->qdevice_name, req_exec_quorum_nodeinfo->qdevice_name); - log_printf(LOGSYS_LEVEL_DEBUG, "Got qdevice data from node[%u]: state %u name %s", - node->node_id, state, node->qdevice_name); - } } else { if ((!cluster_is_quorate) && (req_exec_quorum_nodeinfo->flags & NODE_FLAGS_QUORATE)) { @@ -1500,7 +1694,7 @@ static char *votequorum_exec_init_fn (struct corosync_api_v1 *api) } qdevice->state = NODESTATE_DEAD; qdevice->votes = 0; - memset(qdevice->qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); + memset(qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); votequorum_readconfig_dynamic(); recalculate_quorum(0, 0); @@ -1580,6 +1774,10 @@ static void votequorum_confchg_fn ( quorum_members_entries = member_list_entries; votequorum_exec_send_nodeinfo(us->node_id); votequorum_exec_send_nodeinfo(NODEID_QDEVICE); + if (strlen(qdevice_name)) { + votequorum_exec_send_qdevice_reg(VOTEQUORUM_QDEVICE_OPERATION_REGISTER, + qdevice_name); + } } memcpy(&quorum_ringid, ring_id, sizeof(*ring_id)); @@ -1677,7 +1875,7 @@ static void qdevice_timer_fn(void *arg) qdevice->state = NODESTATE_DEAD; us->flags &= ~NODE_FLAGS_QDEVICE_STATE; - log_printf(LOGSYS_LEVEL_INFO, "lost contact with quorum device %s", qdevice->qdevice_name); + log_printf(LOGSYS_LEVEL_INFO, "lost contact with quorum device %s", qdevice_name); votequorum_exec_send_nodeinfo(us->node_id); qdevice_timer_set = 0; @@ -1932,21 +2130,33 @@ static void message_handler_req_lib_votequorum_qdevice_register (void *conn, if (qdevice_is_registered) { if ((!strncmp(req_lib_votequorum_qdevice_register->name, - qdevice->qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN))) { + qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN))) { goto out; } else { log_printf(LOGSYS_LEVEL_WARNING, "A new qdevice with different name (new: %s old: %s) is trying to re-register!", - req_lib_votequorum_qdevice_register->name, qdevice->qdevice_name); + req_lib_votequorum_qdevice_register->name, qdevice_name); error = CS_ERR_EXIST; goto out; } } else { - qdevice_is_registered = 1; - strcpy(qdevice->qdevice_name, req_lib_votequorum_qdevice_register->name); - us->flags |= NODE_FLAGS_QDEVICE; - votequorum_exec_send_nodeinfo(NODEID_QDEVICE); - votequorum_exec_send_nodeinfo(us->node_id); + if (qdevice_reg_conn != NULL) { + log_printf(LOGSYS_LEVEL_WARNING, + "Registration request already in progress"); + error = CS_ERR_TRY_AGAIN; + goto out; + } + qdevice_reg_conn = conn; + if (votequorum_exec_send_qdevice_reg(VOTEQUORUM_QDEVICE_OPERATION_REGISTER, + req_lib_votequorum_qdevice_register->name) != 0) { + log_printf(LOGSYS_LEVEL_WARNING, + "Unable to send qdevice registration request to cluster"); + error = CS_ERR_TRY_AGAIN; + qdevice_reg_conn = NULL; + } else { + LEAVE(); + return; + } } out: @@ -1969,7 +2179,7 @@ static void message_handler_req_lib_votequorum_qdevice_unregister (void *conn, ENTER(); if (qdevice_is_registered) { - if (strncmp(req_lib_votequorum_qdevice_unregister->name, qdevice->qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN)) { + if (strncmp(req_lib_votequorum_qdevice_unregister->name, qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN)) { error = CS_ERR_INVALID_PARAM; goto out; } @@ -1981,8 +2191,9 @@ static void message_handler_req_lib_votequorum_qdevice_unregister (void *conn, us->flags &= ~NODE_FLAGS_QDEVICE; us->flags &= ~NODE_FLAGS_QDEVICE_STATE; qdevice->state = NODESTATE_DEAD; - memset(qdevice->qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); votequorum_exec_send_nodeinfo(us->node_id); + votequorum_exec_send_qdevice_reg(VOTEQUORUM_QDEVICE_OPERATION_UNREGISTER, + req_lib_votequorum_qdevice_unregister->name); } else { error = CS_ERR_NOT_EXIST; } @@ -2006,13 +2217,12 @@ static void message_handler_req_lib_votequorum_qdevice_update (void *conn, ENTER(); if (qdevice_is_registered) { - if (strncmp(req_lib_votequorum_qdevice_update->oldname, qdevice->qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN)) { + if (strncmp(req_lib_votequorum_qdevice_update->oldname, qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN)) { error = CS_ERR_INVALID_PARAM; goto out; } - memset(qdevice->qdevice_name, 0, VOTEQUORUM_MAX_QDEVICE_NAME_LEN); - strcpy(qdevice->qdevice_name, req_lib_votequorum_qdevice_update->newname); - votequorum_exec_send_nodeinfo(us->node_id); + votequorum_exec_send_qdevice_reconfigure(req_lib_votequorum_qdevice_update->oldname, + req_lib_votequorum_qdevice_update->newname); } else { error = CS_ERR_NOT_EXIST; } @@ -2041,7 +2251,7 @@ static void message_handler_req_lib_votequorum_qdevice_poll (void *conn, } if (qdevice_is_registered) { - if (strncmp(req_lib_votequorum_qdevice_poll->name, qdevice->qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN)) { + if (strncmp(req_lib_votequorum_qdevice_poll->name, qdevice_name, VOTEQUORUM_MAX_QDEVICE_NAME_LEN)) { error = CS_ERR_INVALID_PARAM; goto out; } @@ -2108,7 +2318,7 @@ static void message_handler_req_lib_votequorum_qdevice_getinfo (void *conn, } else { res_lib_votequorum_qdevice_getinfo.state = 0; } - strcpy(res_lib_votequorum_qdevice_getinfo.name, node->qdevice_name); + strcpy(res_lib_votequorum_qdevice_getinfo.name, qdevice_name); } else { error = CS_ERR_NOT_EXIST; } @@ -2121,7 +2331,7 @@ static void message_handler_req_lib_votequorum_qdevice_getinfo (void *conn, } else { res_lib_votequorum_qdevice_getinfo.state = 0; } - strcpy(res_lib_votequorum_qdevice_getinfo.name, qdevice->qdevice_name); + strcpy(res_lib_votequorum_qdevice_getinfo.name, qdevice_name); } else { error = CS_ERR_NOT_EXIST; } -- 1.7.7.6 _______________________________________________ discuss mailing list discuss@xxxxxxxxxxxx http://lists.corosync.org/mailman/listinfo/discuss