diff options
20 files changed, 1462 insertions, 722 deletions
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index ee7d3b2c841..b7c6691abd5 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -215,6 +215,31 @@ out: } int +gf_cli_output_peer_hostnames (dict_t *dict, int count, char *prefix) +{ + int ret = -1; + char key[256] = {0,}; + int i = 0; + char *hostname = NULL; + + cli_out ("Other names:"); + /* Starting from friend.hostname1, as friend.hostname0 will be the same + * as friend.hostname + */ + for (i = 1; i < count; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname%d", prefix, i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + break; + cli_out ("%s", hostname); + hostname = NULL; + } + + return ret; +} + +int gf_cli_output_peer_status (dict_t *dict, int count) { int ret = -1; @@ -225,6 +250,7 @@ gf_cli_output_peer_status (dict_t *dict, int count) char *state = NULL; int32_t connected = 0; char *connected_str = NULL; + int hostname_count = 0; cli_out ("Number of Peers: %d", count); i = 1; @@ -256,6 +282,19 @@ gf_cli_output_peer_status (dict_t *dict, int count) cli_out ("\nHostname: %s\nUuid: %s\nState: %s (%s)", hostname_buf, uuid_buf, state, connected_str); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.hostname_count", i); + ret = dict_get_int32 (dict, key, &hostname_count); + /* Print other addresses only if there are more than 1. + */ + if ((ret == 0) && (hostname_count > 1)) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d", i); + ret = gf_cli_output_peer_hostnames (dict, + hostname_count, + key); + } i++; } diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c index dd38a51c6c0..78d131583e9 100644 --- a/cli/src/cli-xml-output.c +++ b/cli/src/cli-xml-output.c @@ -3018,6 +3018,41 @@ out: #endif } +#if (HAVE_LIB_XML) +static int +cli_xml_output_peer_hostnames (xmlTextWriterPtr writer, dict_t *dict, + const char *prefix, int count) +{ + int ret = -1; + int i = 0; + char *hostname = NULL; + char key[1024] = {0,}; + + /* <hostnames> */ + ret = xmlTextWriterStartElement (writer, (xmlChar *)"hostnames"); + XML_RET_CHECK_AND_GOTO (ret, out); + + for (i = 0; i < count; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname%d", prefix, i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement + (writer, (xmlChar *)"hostname", "%s", hostname); + XML_RET_CHECK_AND_GOTO (ret, out); + hostname = NULL; + } + + /* </hostnames> */ + ret = xmlTextWriterEndElement (writer); + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} +#endif + int cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno, char *op_errstr) @@ -3032,6 +3067,7 @@ cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno, int connected = 0; int state_id = 0; char *state_str = NULL; + int hostname_count = 0; int i = 1; char key[1024] = {0,}; @@ -3082,6 +3118,17 @@ cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno, XML_RET_CHECK_AND_GOTO (ret, out); memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.hostname_count", i); + ret = dict_get_int32 (dict, key, &hostname_count); + if ((ret == 0) && (hostname_count > 0)) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d", i); + ret = cli_xml_output_peer_hostnames (writer, dict, key, + hostname_count); + XML_RET_CHECK_AND_GOTO (ret, out); + } + + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.connected", i); ret = dict_get_int32 (dict, key, &connected); if (ret) diff --git a/doc/gluster.8 b/doc/gluster.8 index de3eee1b0e2..87b83956ce6 100644 --- a/doc/gluster.8 +++ b/doc/gluster.8 @@ -95,7 +95,7 @@ Rotate the log file for corresponding volume/brick. .SS "Peer Commands" .TP \fB\ peer probe <HOSTNAME> \fR -Probe the specified peer. +Probe the specified peer. In case the <HOSTNAME> given belongs to an already probed peer, the peer probe command will add the hostname to the peer if required. .TP \fB\ peer detach <HOSTNAME> \fR Detach the specified peer. diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 124b312f4a1..54ee3e53818 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -3199,3 +3199,36 @@ gf_check_logger (const char *value) return logger; } + +/* gf_compare_sockaddr compares the given addresses @addr1 and @addr2 for + * equality, ie. if they both refer to the same address. + * + * This was inspired by sock_addr_cmp_addr() from + * https://www.opensource.apple.com/source/postfix/postfix-197/postfix/src/util/sock_addr.c + */ +gf_boolean_t +gf_compare_sockaddr (const struct sockaddr *addr1, + const struct sockaddr *addr2) +{ + GF_ASSERT (addr1 != NULL); + GF_ASSERT (addr2 != NULL); + + /* Obviously, the addresses don't match if their families are different + */ + if (addr1->sa_family != addr2->sa_family) + return _gf_false; + + + if (AF_INET == addr1->sa_family) { + if (((struct sockaddr_in *)addr1)->sin_addr.s_addr == + ((struct sockaddr_in *)addr2)->sin_addr.s_addr) + return _gf_true; + + } else if (AF_INET6 == addr1->sa_family) { + if (memcmp ((char *)&((struct sockaddr_in6 *)addr1)->sin6_addr, + (char *)&((struct sockaddr_in6 *)addr2)->sin6_addr, + sizeof (struct in6_addr)) == 0) + return _gf_true; + } + return _gf_false; +} diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index b4372f10bbc..1ddb46c6758 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -639,4 +639,7 @@ gf_check_log_format (const char *value); int gf_check_logger (const char *value); +gf_boolean_t +gf_compare_sockaddr (const struct sockaddr *addr1, + const struct sockaddr *addr2); #endif /* _COMMON_UTILS_H */ diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index e4636089ee7..7f3e8ddd88f 100644 --- a/xlators/mgmt/glusterd/src/Makefile.am +++ b/xlators/mgmt/glusterd/src/Makefile.am @@ -12,8 +12,8 @@ glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \ glusterd-geo-rep.c glusterd-replace-brick.c glusterd-log-ops.c \ glusterd-volume-ops.c glusterd-brick-ops.c glusterd-mountbroker.c \ glusterd-syncop.c glusterd-hooks.c glusterd-volume-set.c \ - glusterd-locks.c glusterd-snapshot.c glusterd-mgmt-handler.c \ - glusterd-mgmt.c + glusterd-locks.c glusterd-snapshot.c glusterd-mgmt-handler.c \ + glusterd-mgmt.c glusterd-peer-utils.c glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ $(top_builddir)/rpc/xdr/src/libgfxdr.la \ @@ -24,7 +24,7 @@ noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h \ glusterd-sm.h glusterd-store.h glusterd-mem-types.h \ glusterd-pmap.h glusterd-volgen.h glusterd-mountbroker.h \ glusterd-syncop.h glusterd-hooks.h glusterd-locks.h \ - glusterd-mgmt.h glusterd-messages.h + glusterd-mgmt.h glusterd-messages.h glusterd-peer-utils.h AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ -I$(rpclibdir) -I$(CONTRIBDIR)/rbtree \ diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index e10dc22b56b..8e4071221de 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -101,9 +101,9 @@ glusterd_handle_friend_req (rpcsvc_request_t *req, uuid_t uuid, port = GF_DEFAULT_BASE_PORT; ret = glusterd_remote_hostname_get (req, rhost, sizeof (rhost)); - ret = glusterd_friend_find (uuid, rhost, &peerinfo); + peerinfo = glusterd_peerinfo_find (uuid, rhost); - if (ret) { + if (peerinfo == NULL) { ret = glusterd_xfer_friend_add_resp (req, hostname, rhost, port, -1, GF_PROBE_UNKNOWN_PEER); if (friend_req->vols.vols_val) { @@ -196,9 +196,9 @@ glusterd_handle_unfriend_req (rpcsvc_request_t *req, uuid_t uuid, if (!port) port = GF_DEFAULT_BASE_PORT; - ret = glusterd_friend_find (uuid, hostname, &peerinfo); + peerinfo = glusterd_peerinfo_find (uuid, hostname); - if (ret) { + if (peerinfo == NULL) { gf_log ("glusterd", GF_LOG_CRITICAL, "Received remove-friend from unknown peer %s", hostname); @@ -252,54 +252,6 @@ out: return ret; } -static int -glusterd_add_peer_detail_to_dict (glusterd_peerinfo_t *peerinfo, - dict_t *friends, int count) -{ - - int ret = -1; - char key[256] = {0, }; - char *peer_uuid_str = NULL; - - GF_ASSERT (peerinfo); - GF_ASSERT (friends); - - snprintf (key, 256, "friend%d.uuid", count); - peer_uuid_str = gd_peer_uuid_str (peerinfo); - ret = dict_set_str (friends, key, peer_uuid_str); - if (ret) - goto out; - - snprintf (key, 256, "friend%d.hostname", count); - ret = dict_set_str (friends, key, peerinfo->hostname); - if (ret) - goto out; - - snprintf (key, 256, "friend%d.port", count); - ret = dict_set_int32 (friends, key, peerinfo->port); - if (ret) - goto out; - - snprintf (key, 256, "friend%d.stateId", count); - ret = dict_set_int32 (friends, key, peerinfo->state.state); - if (ret) - goto out; - - snprintf (key, 256, "friend%d.state", count); - ret = dict_set_str (friends, key, - glusterd_friend_sm_state_name_get(peerinfo->state.state)); - if (ret) - goto out; - - snprintf (key, 256, "friend%d.connected", count); - ret = dict_set_int32 (friends, key, (int32_t)peerinfo->connected); - if (ret) - goto out; - -out: - return ret; -} - struct args_pack { dict_t *dict; int vol_count; @@ -561,44 +513,6 @@ out: return ret; } -int -glusterd_friend_find (uuid_t uuid, char *hostname, - glusterd_peerinfo_t **peerinfo) -{ - int ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - - if (uuid) { - ret = glusterd_friend_find_by_uuid (uuid, peerinfo); - - if (ret) { - gf_log (this->name, GF_LOG_DEBUG, - "Unable to find peer by uuid: %s", - uuid_utoa (uuid)); - } else { - goto out; - } - - } - - if (hostname) { - ret = glusterd_friend_find_by_hostname (hostname, peerinfo); - - if (ret) { - gf_log (this->name, GF_LOG_DEBUG, - "Unable to find hostname: %s", hostname); - } else { - goto out; - } - } - -out: - return ret; -} - int32_t glusterd_op_txn_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx, char *err_str, size_t err_len) @@ -752,7 +666,6 @@ __glusterd_handle_cluster_lock (rpcsvc_request_t *req) gd1_mgmt_cluster_lock_req lock_req = {{0},}; glusterd_op_lock_ctx_t *ctx = NULL; glusterd_op_t op = GD_OP_EVENT_LOCK; - glusterd_peerinfo_t *peerinfo = NULL; glusterd_op_info_t txn_op_info = {{0},}; glusterd_conf_t *priv = NULL; uuid_t *txn_id = NULL; @@ -778,7 +691,7 @@ __glusterd_handle_cluster_lock (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_DEBUG, "Received LOCK from uuid: %s", uuid_utoa (lock_req.uuid)); - if (glusterd_friend_find_by_uuid (lock_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (lock_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (lock_req.uuid)); @@ -891,7 +804,6 @@ __glusterd_handle_stage_op (rpcsvc_request_t *req) int32_t ret = -1; glusterd_req_ctx_t *req_ctx = NULL; gd1_mgmt_stage_op_req op_req = {{0},}; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; uuid_t *txn_id = NULL; glusterd_op_info_t txn_op_info = {{0},}; @@ -927,7 +839,7 @@ __glusterd_handle_stage_op (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_DEBUG, "transaction ID = %s", uuid_utoa (*txn_id)); - if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -982,7 +894,6 @@ __glusterd_handle_commit_op (rpcsvc_request_t *req) int32_t ret = -1; glusterd_req_ctx_t *req_ctx = NULL; gd1_mgmt_commit_op_req op_req = {{0},}; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; uuid_t *txn_id = NULL; glusterd_conf_t *priv = NULL; @@ -1004,7 +915,7 @@ __glusterd_handle_commit_op (rpcsvc_request_t *req) goto out; } - if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -1119,16 +1030,13 @@ __glusterd_handle_cli_probe (rpcsvc_request_t *req) goto out; } - if (!(ret = glusterd_friend_find_by_hostname (hostname, &peerinfo))) { - if (strcmp (peerinfo->hostname, hostname) == 0) { - - gf_log ("glusterd", GF_LOG_DEBUG, "Probe host %s port " - "%d already a peer", hostname, port); - glusterd_xfer_cli_probe_resp (req, 0, GF_PROBE_FRIEND, - NULL, hostname, port, - dict); - goto out; - } + peerinfo = glusterd_peerinfo_find_by_hostname (hostname); + if (peerinfo && gd_peer_has_address (peerinfo, hostname)) { + gf_log ("glusterd", GF_LOG_DEBUG, "Probe host %s port %d " + "already a peer", hostname, port); + glusterd_xfer_cli_probe_resp (req, 0, GF_PROBE_FRIEND, NULL, + hostname, port, dict); + goto out; } ret = glusterd_probe_begin (req, hostname, port, dict, &op_errno); @@ -2021,9 +1929,8 @@ __glusterd_handle_fsm_log (rpcsvc_request_t *req) conf = this->private; log = &conf->op_sm_log; } else { - ret = glusterd_friend_find_by_hostname (cli_req.name, - &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find_by_hostname (cli_req.name); + if (!peerinfo) { snprintf (msg, sizeof (msg), "%s is not a peer", cli_req.name); goto out; @@ -2150,7 +2057,6 @@ __glusterd_handle_cluster_unlock (rpcsvc_request_t *req) gd1_mgmt_cluster_unlock_req unlock_req = {{0}, }; int32_t ret = -1; glusterd_op_lock_ctx_t *ctx = NULL; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; uuid_t *txn_id = NULL; glusterd_conf_t *priv = NULL; @@ -2176,7 +2082,7 @@ __glusterd_handle_cluster_unlock (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_DEBUG, "Received UNLOCK from uuid: %s", uuid_utoa (unlock_req.uuid)); - if (glusterd_friend_find_by_uuid (unlock_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (unlock_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (unlock_req.uuid)); @@ -2402,24 +2308,21 @@ out: } int -glusterd_friend_hostname_update (glusterd_peerinfo_t *peerinfo, - char *hostname, - gf_boolean_t store_update) +glusterd_peer_hostname_update (glusterd_peerinfo_t *peerinfo, + const char *hostname, gf_boolean_t store_update) { - char *new_hostname = NULL; int ret = 0; GF_ASSERT (peerinfo); GF_ASSERT (hostname); - new_hostname = gf_strdup (hostname); - if (!new_hostname) { - ret = -1; + ret = gd_add_address_to_peer (peerinfo, hostname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Couldn't add address to the peer info"); goto out; } - GF_FREE (peerinfo->hostname); - peerinfo->hostname = new_hostname; if (store_update) ret = glusterd_store_peerinfo (peerinfo); out: @@ -2435,12 +2338,10 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req) glusterd_peerinfo_t *peerinfo = NULL; glusterd_conf_t *priv = NULL; xlator_t *this = NULL; - glusterd_peerinfo_t *tmp = NULL; gd1_mgmt_friend_update_rsp rsp = {{0},}; dict_t *dict = NULL; char key[100] = {0,}; char *uuid_buf = NULL; - char *hostname = NULL; int i = 1; int count = 0; uuid_t uuid = {0,}; @@ -2462,8 +2363,8 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req) goto out; } - ret = glusterd_friend_find (friend_req.uuid, NULL, &tmp); - if (ret) { + if (glusterd_peerinfo_find (friend_req.uuid, NULL) == NULL) { + ret = -1; gf_log ("", GF_LOG_CRITICAL, "Received friend update request " "from unknown peer %s", uuid_utoa (friend_req.uuid)); goto out; @@ -2503,46 +2404,59 @@ __glusterd_handle_friend_update (rpcsvc_request_t *req) args.mode = GD_MODE_ON; while ( i <= count) { + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "friend%d.uuid", i); ret = dict_get_str (dict, key, &uuid_buf); if (ret) goto out; uuid_parse (uuid_buf, uuid); - snprintf (key, sizeof (key), "friend%d.hostname", i); - ret = dict_get_str (dict, key, &hostname); - if (ret) - goto out; - - gf_log ("", GF_LOG_INFO, "Received uuid: %s, hostname:%s", - uuid_buf, hostname); - - if (uuid_is_null (uuid)) { - gf_log (this->name, GF_LOG_WARNING, "Updates mustn't " - "contain peer with 'null' uuid"); - continue; - } if (!uuid_compare (uuid, MY_UUID)) { - gf_log ("", GF_LOG_INFO, "Received my uuid as Friend"); + gf_log (this->name, GF_LOG_INFO, + "Received my uuid as Friend"); i++; continue; } - ret = glusterd_friend_find (uuid, hostname, &tmp); + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d", i); + + peerinfo = glusterd_peerinfo_find (uuid, NULL); + if (peerinfo == NULL) { + /* Create a new peer and add it to the list as there is + * no existing peer with the uuid + */ + peerinfo = gd_peerinfo_from_dict (dict, key); + if (peerinfo == NULL) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "Could not create peerinfo from dict " + "for prefix %s", key); + goto out; + } + + /* As this is a new peer, it should be added as a + * friend. The friend state machine will take care of + * correcting the state as required + */ + peerinfo->state.state = GD_FRIEND_STATE_BEFRIENDED; - if (!ret) { - if (strcmp (hostname, tmp->hostname) != 0) { - glusterd_friend_hostname_update (tmp, hostname, - _gf_true); + ret = glusterd_friend_add_from_peerinfo (peerinfo, 0, + &args); + } else { + /* As an existing peer was found, update it with the new + * information + */ + ret = gd_update_peerinfo_from_dict (peerinfo, dict, + key); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + "update peer %s", peerinfo->hostname); + goto out; } - i++; - continue; } - ret = glusterd_friend_add (hostname, friend_req.port, - GD_FRIEND_STATE_BEFRIENDED, - &uuid, &peerinfo, 0, &args); - + peerinfo = NULL; i++; } @@ -2558,6 +2472,9 @@ out: free (friend_req.friends.friends_val);//malloced by xdr } + if (peerinfo) + glusterd_peerinfo_cleanup (peerinfo); + glusterd_friend_sm (); glusterd_op_sm (); @@ -2625,11 +2542,11 @@ __glusterd_handle_probe_query (rpcsvc_request_t *req) gf_log ("", GF_LOG_ERROR, "Unable to get the remote hostname"); goto out; } - ret = glusterd_friend_find (probe_req.uuid, remote_hostname, &peerinfo); - if ((ret != 0 ) && (!list_empty (&conf->peers))) { + peerinfo = glusterd_peerinfo_find (probe_req.uuid, remote_hostname); + if ((peerinfo == NULL) && (!list_empty (&conf->peers))) { rsp.op_ret = -1; rsp.op_errno = GF_PROBE_ANOTHER_CLUSTER; - } else if (ret) { + } else if (peerinfo == NULL) { gf_log ("glusterd", GF_LOG_INFO, "Unable to find peerinfo" " for host: %s (%d)", remote_hostname, port); args.mode = GD_MODE_ON; @@ -2951,17 +2868,17 @@ glusterd_handle_umount (rpcsvc_request_t *req) int glusterd_friend_remove (uuid_t uuid, char *hostname) { - int ret = 0; + int ret = -1; glusterd_peerinfo_t *peerinfo = NULL; - ret = glusterd_friend_find (uuid, hostname, &peerinfo); - if (ret) + peerinfo = glusterd_peerinfo_find (uuid, hostname); + if (peerinfo == NULL) goto out; ret = glusterd_friend_remove_cleanup_vols (peerinfo->uuid); if (ret) gf_log (THIS->name, GF_LOG_WARNING, "Volumes cleanup failed"); - ret = glusterd_friend_cleanup (peerinfo); + ret = glusterd_peerinfo_cleanup (peerinfo); out: gf_log ("", GF_LOG_DEBUG, "returning %d", ret); return ret; @@ -3068,10 +2985,10 @@ int glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo, glusterd_peerctx_args_t *args) { - dict_t *options = NULL; - int ret = -1; - glusterd_peerctx_t *peerctx = NULL; - data_t *data = NULL; + dict_t *options = NULL; + int ret = -1; + glusterd_peerctx_t *peerctx = NULL; + data_t *data = NULL; peerctx = GF_CALLOC (1, sizeof (*peerctx), gf_gld_mt_peerctx_t); if (!peerctx) @@ -3136,9 +3053,11 @@ glusterd_friend_add (const char *hoststr, int port, conf = this->private; GF_ASSERT (conf); GF_ASSERT (hoststr); + GF_ASSERT (friend); - ret = glusterd_peerinfo_new (friend, state, uuid, hoststr, port); - if (ret) { + *friend = glusterd_peerinfo_new (state, uuid, hoststr, port); + if (*friend == NULL) { + ret = -1; goto out; } @@ -3167,7 +3086,7 @@ glusterd_friend_add (const char *hoststr, int port, } if (ret) { - (void) glusterd_friend_cleanup (*friend); + (void) glusterd_peerinfo_cleanup (*friend); *friend = NULL; } @@ -3176,6 +3095,54 @@ out: return ret; } +/* glusterd_friend_add_from_peerinfo() adds a new peer into the local friends + * list from a pre created @peerinfo object. It otherwise works similarly to + * glusterd_friend_add() + */ +int +glusterd_friend_add_from_peerinfo (glusterd_peerinfo_t *friend, + gf_boolean_t restore, + glusterd_peerctx_args_t *args) +{ + int ret = 0; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + + this = THIS; + conf = this->private; + GF_ASSERT (conf); + + GF_VALIDATE_OR_GOTO (this->name, (friend != NULL), out); + + /* + * We can't add to the list after calling glusterd_friend_rpc_create, + * even if it succeeds, because by then the callback to take it back + * off and free might have happened already (notably in the case of an + * invalid peer name). That would mean we're adding something that had + * just been free, and we're likely to crash later. + */ + list_add_tail (&friend->uuid_list, &conf->peers); + + //restore needs to first create the list of peers, then create rpcs + //to keep track of quorum in race-free manner. In restore for each peer + //rpc-create calls rpc_notify when the friend-list is partially + //constructed, leading to wrong quorum calculations. + if (!restore) { + ret = glusterd_store_peerinfo (friend); + if (ret == 0) { + ret = glusterd_friend_rpc_create (this, friend, args); + } + else { + gf_log (this->name, GF_LOG_ERROR, + "Failed to store peerinfo"); + } + } + +out: + gf_log (this->name, GF_LOG_INFO, "connect returned %d", ret); + return ret; +} + int glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port, dict_t *dict, int *op_errno) @@ -3187,15 +3154,15 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port, GF_ASSERT (hoststr); - ret = glusterd_friend_find (NULL, (char *)hoststr, &peerinfo); + peerinfo = glusterd_peerinfo_find (NULL, hoststr); - if (ret) { + if (peerinfo == NULL) { gf_log ("glusterd", GF_LOG_INFO, "Unable to find peerinfo" " for host: %s (%d)", hoststr, port); args.mode = GD_MODE_ON; args.req = req; args.dict = dict; - ret = glusterd_friend_add ((char *)hoststr, port, + ret = glusterd_friend_add (hoststr, port, GD_FRIEND_STATE_DEFAULT, NULL, &peerinfo, 0, &args); if ((!ret) && (!peerinfo->connected)) { @@ -3210,8 +3177,8 @@ glusterd_probe_begin (rpcsvc_request_t *req, const char *hoststr, int port, *op_errno = GF_PROBE_FRIEND_DETACHING; goto out; } - ret = glusterd_friend_hostname_update (peerinfo, (char*)hoststr, - _gf_false); + ret = glusterd_peer_hostname_update (peerinfo, hoststr, + _gf_false); if (ret) goto out; //this is just to rename so inject local acc for cluster update @@ -3246,9 +3213,10 @@ glusterd_deprobe_begin (rpcsvc_request_t *req, const char *hoststr, int port, GF_ASSERT (hoststr); GF_ASSERT (req); - ret = glusterd_friend_find (uuid, (char *)hoststr, &peerinfo); + peerinfo = glusterd_peerinfo_find (uuid, hoststr); - if (ret) { + if (peerinfo == NULL) { + ret = -1; gf_log ("glusterd", GF_LOG_INFO, "Unable to find peerinfo" " for host: %s %d", hoststr, port); goto out; @@ -3614,7 +3582,7 @@ glusterd_list_friends (rpcsvc_request_t *req, dict_t *dict, int32_t flags) if (!list_empty (&priv->peers)) { list_for_each_entry (entry, &priv->peers, uuid_list) { count++; - ret = glusterd_add_peer_detail_to_dict (entry, + ret = gd_add_peer_detail_to_dict (entry, friends, count); if (ret) goto out; diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c b/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c index 48e390f5692..c0c1cfcba18 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c @@ -122,7 +122,6 @@ glusterd_handle_mgmt_v3_lock_fn (rpcsvc_request_t *req) { gd1_mgmt_v3_lock_req lock_req = {{0},}; int32_t ret = -1; - glusterd_peerinfo_t *peerinfo = NULL; glusterd_op_lock_ctx_t *ctx = NULL; xlator_t *this = NULL; gf_boolean_t is_synctasked = _gf_false; @@ -144,7 +143,7 @@ glusterd_handle_mgmt_v3_lock_fn (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_DEBUG, "Received mgmt_v3 lock req " "from uuid: %s", uuid_utoa (lock_req.uuid)); - if (glusterd_friend_find_by_uuid (lock_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (lock_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (lock_req.uuid)); @@ -247,7 +246,6 @@ glusterd_handle_pre_validate_fn (rpcsvc_request_t *req) { int32_t ret = -1; gd1_mgmt_v3_pre_val_req op_req = {{0},}; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; char *op_errstr = NULL; dict_t *dict = NULL; @@ -267,7 +265,7 @@ glusterd_handle_pre_validate_fn (rpcsvc_request_t *req) goto out; } - if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -374,7 +372,6 @@ glusterd_handle_brick_op_fn (rpcsvc_request_t *req) { int32_t ret = -1; gd1_mgmt_v3_brick_op_req op_req = {{0},}; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; char *op_errstr = NULL; dict_t *dict = NULL; @@ -393,7 +390,7 @@ glusterd_handle_brick_op_fn (rpcsvc_request_t *req) goto out; } - if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -499,7 +496,6 @@ glusterd_handle_commit_fn (rpcsvc_request_t *req) { int32_t ret = -1; gd1_mgmt_v3_commit_req op_req = {{0},}; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; char *op_errstr = NULL; dict_t *dict = NULL; @@ -518,7 +514,7 @@ glusterd_handle_commit_fn (rpcsvc_request_t *req) goto out; } - if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -625,7 +621,6 @@ glusterd_handle_post_validate_fn (rpcsvc_request_t *req) { int32_t ret = -1; gd1_mgmt_v3_post_val_req op_req = {{0},}; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; char *op_errstr = NULL; dict_t *dict = NULL; @@ -645,7 +640,7 @@ glusterd_handle_post_validate_fn (rpcsvc_request_t *req) goto out; } - if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (op_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); @@ -794,7 +789,6 @@ glusterd_handle_mgmt_v3_unlock_fn (rpcsvc_request_t *req) gd1_mgmt_v3_unlock_req lock_req = {{0},}; int32_t ret = -1; glusterd_op_lock_ctx_t *ctx = NULL; - glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; gf_boolean_t is_synctasked = _gf_false; gf_boolean_t free_ctx = _gf_false; @@ -815,7 +809,7 @@ glusterd_handle_mgmt_v3_unlock_fn (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_DEBUG, "Received volume unlock req " "from uuid: %s", uuid_utoa (lock_req.uuid)); - if (glusterd_friend_find_by_uuid (lock_req.uuid, &peerinfo)) { + if (glusterd_peerinfo_find_by_uuid (lock_req.uuid) == NULL) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (lock_req.uuid)); diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 66276bd466d..52ab039b9ec 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1200,8 +1200,9 @@ glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) ret = 0; } } else { - ret = glusterd_friend_find (NULL, hostname, &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find (NULL, hostname); + if (peerinfo == NULL) { + ret = -1; snprintf (msg, sizeof (msg), "%s, is not a friend", hostname); *op_errstr = gf_strdup (msg); diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c new file mode 100644 index 00000000000..be8ae76c77a --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c @@ -0,0 +1,902 @@ +/* + Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "glusterd-peer-utils.h" +#include "glusterd-store.h" +#include "common-utils.h" + +int32_t +glusterd_peerinfo_cleanup (glusterd_peerinfo_t *peerinfo) +{ + GF_ASSERT (peerinfo); + glusterd_peerctx_t *peerctx = NULL; + gf_boolean_t quorum_action = _gf_false; + glusterd_conf_t *priv = THIS->private; + + if (peerinfo->quorum_contrib != QUORUM_NONE) + quorum_action = _gf_true; + if (peerinfo->rpc) { + peerctx = peerinfo->rpc->mydata; + peerinfo->rpc->mydata = NULL; + peerinfo->rpc = glusterd_rpc_clnt_unref (priv, peerinfo->rpc); + peerinfo->rpc = NULL; + if (peerctx) { + GF_FREE (peerctx->errstr); + GF_FREE (peerctx); + } + } + glusterd_peerinfo_destroy (peerinfo); + + if (quorum_action) + glusterd_do_quorum_action (); + return 0; +} + +int32_t +glusterd_peerinfo_destroy (glusterd_peerinfo_t *peerinfo) +{ + int32_t ret = -1; + glusterd_peer_hostname_t *hostname = NULL; + glusterd_peer_hostname_t *tmp = NULL; + + if (!peerinfo) + goto out; + + list_del_init (&peerinfo->uuid_list); + + ret = glusterd_store_delete_peerinfo (peerinfo); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "Deleting peer info failed"); + } + + GF_FREE (peerinfo->hostname); + peerinfo->hostname = NULL; + + list_for_each_entry_safe (hostname, tmp, &peerinfo->hostnames, + hostname_list) { + glusterd_peer_hostname_free (hostname); + } + + glusterd_sm_tr_log_delete (&peerinfo->sm_log); + GF_FREE (peerinfo); + peerinfo = NULL; + + ret = 0; + +out: + return ret; +} + +/* glusterd_peerinfo_find_by_hostname searches for a peer which matches the + * hostname @hoststr and if found returns the pointer to peerinfo object. + * Returns NULL otherwise. + * + * It first attempts a quick search by string matching @hoststr. If that fails, + * it'll attempt a more thorough match by resolving the addresses and matching + * the resolved addrinfos. + */ +glusterd_peerinfo_t * +glusterd_peerinfo_find_by_hostname (const char *hoststr) +{ + int ret = -1; + struct addrinfo *addr = NULL; + struct addrinfo *p = NULL; + xlator_t *this = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + + + this = THIS; + GF_ASSERT (hoststr); + + peerinfo = NULL; + + peerinfo = gd_peerinfo_find_from_hostname (hoststr); + if (peerinfo) + return peerinfo; + + ret = getaddrinfo (hoststr, NULL, NULL, &addr); + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, + "error in getaddrinfo: %s\n", + gai_strerror(ret)); + goto out; + } + + for (p = addr; p != NULL; p = p->ai_next) { + peerinfo = gd_peerinfo_find_from_addrinfo (p); + if (peerinfo) { + freeaddrinfo (addr); + return peerinfo; + } + } + +out: + gf_log (this->name, GF_LOG_DEBUG, "Unable to find friend: %s", hoststr); + if (addr) + freeaddrinfo (addr); + return NULL; +} + +int +glusterd_hostname_to_uuid (char *hostname, uuid_t uuid) +{ + GF_ASSERT (hostname); + GF_ASSERT (uuid); + + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_conf_t *priv = NULL; + int ret = -1; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + peerinfo = glusterd_peerinfo_find_by_hostname (hostname); + if (peerinfo) { + ret = 0; + uuid_copy (uuid, peerinfo->uuid); + } else { + if (gf_is_local_addr (hostname)) { + uuid_copy (uuid, MY_UUID); + ret = 0; + } else { + ret = -1; + } + } + + gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret); + return ret; +} + +/* glusterd_peerinfo_find_by_uuid searches for a peer which matches the + * uuid @uuid and if found returns the pointer to peerinfo object. + * Returns NULL otherwise. + */ +glusterd_peerinfo_t * +glusterd_peerinfo_find_by_uuid (uuid_t uuid) +{ + glusterd_conf_t *priv = NULL; + glusterd_peerinfo_t *entry = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + priv = this->private; + + GF_ASSERT (priv); + + if (uuid_is_null (uuid)) + return NULL; + + list_for_each_entry (entry, &priv->peers, uuid_list) { + if (!uuid_compare (entry->uuid, uuid)) { + + gf_log (this->name, GF_LOG_DEBUG, + "Friend found... state: %s", + glusterd_friend_sm_state_name_get (entry->state.state)); + return entry; + } + } + + gf_log (this->name, GF_LOG_DEBUG, "Friend with uuid: %s, not found", + uuid_utoa (uuid)); + return NULL; +} + +/* glusterd_peerinfo_find will search for a peer matching either @uuid or + * @hostname and return a pointer to the peerinfo object + * Returns NULL otherwise. + */ +glusterd_peerinfo_t * +glusterd_peerinfo_find (uuid_t uuid, const char *hostname) +{ + glusterd_peerinfo_t *peerinfo = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + + if (uuid) { + peerinfo = glusterd_peerinfo_find_by_uuid (uuid); + + if (peerinfo) { + return peerinfo; + } else { + gf_log (this->name, GF_LOG_DEBUG, + "Unable to find peer by uuid: %s", + uuid_utoa (uuid)); + } + + } + + if (hostname) { + peerinfo = glusterd_peerinfo_find_by_hostname (hostname); + + if (peerinfo) { + return peerinfo; + } else { + gf_log (this->name, GF_LOG_DEBUG, + "Unable to find hostname: %s", hostname); + } + } + return NULL; +} + +/* glusterd_peerinfo_new will create a new peerinfo object and set it's members + * values using the passed parameters. + * @hostname is added as the first entry in peerinfo->hostnames list and also + * set to peerinfo->hostname. + * It returns a pointer to peerinfo object if successfull and returns NULL + * otherwise. The caller should take care of freeing the created peerinfo + * object. + */ +glusterd_peerinfo_t * +glusterd_peerinfo_new (glusterd_friend_sm_state_t state, uuid_t *uuid, + const char *hostname, int port) +{ + glusterd_peerinfo_t *new_peer = NULL; + int ret = -1; + + new_peer = GF_CALLOC (1, sizeof (*new_peer), gf_gld_mt_peerinfo_t); + if (!new_peer) + goto out; + + INIT_LIST_HEAD (&new_peer->uuid_list); + + new_peer->state.state = state; + + INIT_LIST_HEAD (&new_peer->hostnames); + if (hostname) { + ret = gd_add_address_to_peer (new_peer, hostname); + if (ret) + goto out; + /* Also set it to peerinfo->hostname. Doing this as we use + * peerinfo->hostname in a lot of places and is really hard to + * get everything right + */ + new_peer->hostname = gf_strdup (hostname); + } + + if (uuid) { + uuid_copy (new_peer->uuid, *uuid); + } + + ret = glusterd_sm_tr_log_init (&new_peer->sm_log, + glusterd_friend_sm_state_name_get, + glusterd_friend_sm_event_name_get, + GLUSTERD_TR_LOG_SIZE); + if (ret) + goto out; + + if (new_peer->state.state == GD_FRIEND_STATE_BEFRIENDED) + new_peer->quorum_contrib = QUORUM_WAITING; + new_peer->port = port; +out: + if (ret && new_peer) { + glusterd_peerinfo_cleanup (new_peer); + new_peer = NULL; + } + return new_peer; +} + +/* Check if the all peers are connected and befriended, except the peer + * specified (the peer being detached) + */ +gf_boolean_t +glusterd_chk_peers_connected_befriended (uuid_t skip_uuid) +{ + gf_boolean_t ret = _gf_true; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_conf_t *priv = NULL; + + priv= THIS->private; + GF_ASSERT (priv); + + list_for_each_entry (peerinfo, &priv->peers, uuid_list) { + + if (!uuid_is_null (skip_uuid) && !uuid_compare (skip_uuid, + peerinfo->uuid)) + continue; + + if ((GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state) + || !(peerinfo->connected)) { + ret = _gf_false; + break; + } + } + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %s", + (ret?"TRUE":"FALSE")); + return ret; +} + +/* Return hostname for given uuid if it exists + * else return NULL + */ +char * +glusterd_uuid_to_hostname (uuid_t uuid) +{ + char *hostname = NULL; + glusterd_conf_t *priv = NULL; + glusterd_peerinfo_t *entry = NULL; + + priv = THIS->private; + GF_ASSERT (priv); + + if (!uuid_compare (MY_UUID, uuid)) { + hostname = gf_strdup ("localhost"); + } + if (!list_empty (&priv->peers)) { + list_for_each_entry (entry, &priv->peers, uuid_list) { + if (!uuid_compare (entry->uuid, uuid)) { + hostname = gf_strdup (entry->hostname); + break; + } + } + } + + return hostname; +} + +char* +gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo) +{ + if ((peerinfo == NULL) || uuid_is_null (peerinfo->uuid)) + return NULL; + + if (peerinfo->uuid_str[0] == '\0') + uuid_utoa_r (peerinfo->uuid, peerinfo->uuid_str); + + return peerinfo->uuid_str; +} + +gf_boolean_t +glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, + struct list_head *peers, + char **down_peerstr) +{ + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + gf_boolean_t ret = _gf_false; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (!uuid_compare (brickinfo->uuid, MY_UUID)) + continue; + + list_for_each_entry (peerinfo, peers, uuid_list) { + if (uuid_compare (peerinfo->uuid, brickinfo->uuid)) + continue; + + /*Found peer who owns the brick, return false + * if peer is not connected or not friend */ + if (!(peerinfo->connected) || + (peerinfo->state.state != + GD_FRIEND_STATE_BEFRIENDED)) { + *down_peerstr = gf_strdup (peerinfo->hostname); + gf_log ("", GF_LOG_DEBUG, "Peer %s is down. ", + peerinfo->hostname); + goto out; + } + } + } + + ret = _gf_true; +out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +glusterd_peer_hostname_new (const char *hostname, + glusterd_peer_hostname_t **name) +{ + glusterd_peer_hostname_t *peer_hostname = NULL; + int32_t ret = -1; + + GF_ASSERT (hostname); + GF_ASSERT (name); + + peer_hostname = GF_CALLOC (1, sizeof (*peer_hostname), + gf_gld_mt_peer_hostname_t); + + if (!peer_hostname) + goto out; + + peer_hostname->hostname = gf_strdup (hostname); + INIT_LIST_HEAD (&peer_hostname->hostname_list); + + *name = peer_hostname; + ret = 0; + +out: + gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +void +glusterd_peer_hostname_free (glusterd_peer_hostname_t *name) +{ + if (!name) + return; + + list_del_init (&name->hostname_list); + + GF_FREE (name->hostname); + name->hostname = NULL; + + GF_FREE (name); + + return; +} + +gf_boolean_t +gd_peer_has_address (glusterd_peerinfo_t *peerinfo, const char *address) +{ + gf_boolean_t ret = _gf_false; + glusterd_peer_hostname_t *hostname = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", (peerinfo != NULL), out); + GF_VALIDATE_OR_GOTO ("glusterd", (address != NULL), out); + + list_for_each_entry (hostname, &peerinfo->hostnames, hostname_list) { + if (strcmp (hostname->hostname, address) == 0) { + ret = _gf_true; + break; + } + } + +out: + return ret; +} + +int +gd_add_address_to_peer (glusterd_peerinfo_t *peerinfo, const char *address) +{ + + int ret = -1; + glusterd_peer_hostname_t *hostname = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", (peerinfo != NULL), out); + GF_VALIDATE_OR_GOTO ("glusterd", (address != NULL), out); + + if (gd_peer_has_address (peerinfo, address)) { + ret = 0; + goto out; + } + + ret = glusterd_peer_hostname_new (address, &hostname); + if (ret) + goto out; + + list_add_tail (&hostname->hostname_list, &peerinfo->hostnames); + + ret = 0; +out: + return ret; +} + +/* gd_add_friend_to_dict() adds details of @friend into @dict with the given + * @prefix. All the parameters are compulsary. + * + * The complete address list is added to the dict only if the cluster op-version + * is >= GD_OP_VERSION_3_6_0 + */ +int +gd_add_friend_to_dict (glusterd_peerinfo_t *friend, dict_t *dict, + const char *prefix) +{ + int ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + char key[100] = {0,}; + glusterd_peer_hostname_t *address = NULL; + int count = 0; + + this = THIS; + GF_VALIDATE_OR_GOTO ("glusterd", (this != NULL), out); + + conf = this->private; + GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); + + GF_VALIDATE_OR_GOTO (this->name, (friend != NULL), out); + GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); + GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); + + snprintf (key, sizeof (key), "%s.uuid", prefix); + ret = dict_set_dynstr_with_alloc (dict, key, uuid_utoa (friend->uuid)); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set key %s in dict", key); + goto out; + } + + /* Setting the first hostname from the list with this key for backward + * compatability + */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname", prefix); + address = list_entry (&friend->hostnames, glusterd_peer_hostname_t, + hostname_list); + if (!address) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "Could not retrieve first " + "address for peer"); + goto out; + } + ret = dict_set_dynstr_with_alloc (dict, key, address->hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set key %s in dict", key); + goto out; + } + + if (conf->op_version < GD_OP_VERSION_3_6_0) { + ret = 0; + goto out; + } + + address = NULL; + count = 0; + list_for_each_entry (address, &friend->hostnames, hostname_list) { + GF_VALIDATE_OR_GOTO (this->name, (address != NULL), out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname%d", prefix, count); + ret = dict_set_dynstr_with_alloc (dict, key, address->hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set key %s in dict", key); + goto out; + } + count++; + } + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.address-count", prefix); + ret = dict_set_int32 (dict, key, count); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Failed to set key %s in dict", key); + +out: + gf_log (this ? this->name : "glusterd", GF_LOG_DEBUG, "Returning %d", + ret); + return ret; +} + +/* gd_peerinfo_find_from_hostname iterates over all the addresses saved for each + * peer and matches it to @hoststr. + * Returns the matched peer if found else returns NULL + */ +glusterd_peerinfo_t * +gd_peerinfo_find_from_hostname (const char *hoststr) +{ + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + glusterd_peerinfo_t *peer = NULL; + glusterd_peer_hostname_t *tmphost = NULL; + + this = THIS; + GF_ASSERT (this != NULL); + priv = this->private; + GF_VALIDATE_OR_GOTO (this->name, (priv != NULL), out); + + GF_VALIDATE_OR_GOTO (this->name, (hoststr != NULL), out); + + list_for_each_entry (peer, &priv->peers, uuid_list) { + list_for_each_entry (tmphost, &peer->hostnames,hostname_list) { + if (!strncasecmp (tmphost->hostname, hoststr, 1024)) { + gf_log (this->name, GF_LOG_DEBUG, + "Friend %s found.. state: %d", + tmphost->hostname, peer->state.state); + return peer; + } + } + } +out: + return NULL; +} + +/* gd_peerinfo_find_from_addrinfo iterates over all the addresses saved for each + * peer, resolves them and compares them to @addr. + * + * + * NOTE: As getaddrinfo is a blocking call and is being performed multiple times + * in this function, it could lead to the calling thread to be blocked for + * significant amounts of time. + * + * Returns the matched peer if found else returns NULL + */ +glusterd_peerinfo_t * +gd_peerinfo_find_from_addrinfo (const struct addrinfo *addr) +{ + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + glusterd_peerinfo_t *peer = NULL; + glusterd_peer_hostname_t *address = NULL; + int ret = 0; + struct addrinfo *paddr = NULL; + struct addrinfo *tmp = NULL; + + this = THIS; + GF_ASSERT (this != NULL); + conf = this->private; + GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); + + GF_VALIDATE_OR_GOTO (this->name, (addr != NULL), out); + + list_for_each_entry (peer, &conf->peers, uuid_list) { + list_for_each_entry (address, &peer->hostnames, hostname_list) { + /* TODO: Cache the resolved addrinfos to improve + * performance + */ + ret = getaddrinfo (address->hostname, NULL, NULL, + &paddr); + if (ret) { + /* Don't fail if getaddrinfo fails, continue + * onto the next address + */ + gf_log (this->name, GF_LOG_TRACE, + "getaddrinfo for %s failed (%s)", + address->hostname, gai_strerror (ret)); + ret = 0; + continue; + } + + for (tmp = paddr; tmp != NULL; tmp = tmp->ai_next) { + if (gf_compare_sockaddr (addr->ai_addr, + tmp->ai_addr)) { + freeaddrinfo (paddr); + return peer; + } + } + } + } +out: + return NULL; +} + +/* gd_update_peerinfo_from_dict will update the hostnames for @peerinfo from + * peer details with @prefix in @dict. + * Returns 0 on sucess and -1 on failure. + */ +int +gd_update_peerinfo_from_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict, + const char *prefix) +{ + int ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + char key[100] = {0,}; + char *hostname = NULL; + int count = 0; + int i = 0; + + this = THIS; + GF_ASSERT (this != NULL); + + conf = this->private; + GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); + + GF_VALIDATE_OR_GOTO (this->name, (peerinfo != NULL), out); + GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); + GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname", prefix); + ret = dict_get_str (dict, key, &hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Key %s not present in " + "dictionary", key); + goto out; + } + ret = gd_add_address_to_peer (peerinfo, hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Could not add address to peer"); + goto out; + } + /* Also set peerinfo->hostname to the first address */ + if (peerinfo->hostname != NULL) + GF_FREE (peerinfo->hostname); + peerinfo->hostname = gf_strdup (hostname); + + if (conf->op_version < GD_OP_VERSION_3_6_0) { + ret = 0; + goto out; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.address-count", prefix); + ret = dict_get_int32 (dict, key, &count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Key %s not present in " + "dictionary", key); + goto out; + } + hostname = NULL; + for (i = 0; i < count; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname%d",prefix, i); + ret = dict_get_str (dict, key, &hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Key %s not present " + "in dictionary", key); + goto out; + } + ret = gd_add_address_to_peer (peerinfo, hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Could not add address to peer"); + goto out; + } + + hostname = NULL; + } + +out: + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +/* gd_peerinfo_from_dict creates a peerinfo object from details of peer with + * @prefix in @dict. + * Returns a pointer to the created peerinfo object on success, and NULL on + * failure. + */ +glusterd_peerinfo_t * +gd_peerinfo_from_dict (dict_t *dict, const char *prefix) +{ + int ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + glusterd_peerinfo_t *new_peer = NULL; + char key[100] = {0,}; + char *uuid_str = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO ("glusterd", (this != NULL), out); + + conf = this->private; + GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); + + GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); + GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); + + new_peer = glusterd_peerinfo_new (GD_FRIEND_STATE_DEFAULT, NULL, NULL, + 0); + if (new_peer == NULL) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "Could not create peerinfo " + "object"); + goto out; + } + + snprintf (key, sizeof (key), "%s.uuid", prefix); + ret = dict_get_str (dict, key, &uuid_str); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Key %s not present in " + "dictionary", key); + goto out; + } + uuid_parse (uuid_str, new_peer->uuid); + + ret = gd_update_peerinfo_from_dict (new_peer, dict, prefix); + +out: + if ((ret != 0) && (new_peer != NULL)) { + glusterd_peerinfo_cleanup (new_peer); + new_peer = NULL; + } + + return new_peer; +} + +int +gd_add_peer_hostnames_to_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict, + const char *prefix) +{ + int ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + char key[256] = {0,}; + glusterd_peer_hostname_t *addr = NULL; + int count = 0; + + this = THIS; + GF_ASSERT (this != NULL); + + conf = this->private; + GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); + + if (conf->op_version < GD_OP_VERSION_3_6_0) { + ret = 0; + goto out; + } + + GF_VALIDATE_OR_GOTO (this->name, (peerinfo != NULL), out); + GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); + GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); + + list_for_each_entry (addr, &peerinfo->hostnames, hostname_list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname%d", prefix, count); + ret = dict_set_dynstr_with_alloc (dict, key, addr->hostname); + if (ret) + goto out; + count++; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.hostname_count", prefix); + ret = dict_set_int32 (dict, key, count); + +out: + return ret; +} + +int +gd_add_peer_detail_to_dict (glusterd_peerinfo_t *peerinfo, dict_t *friends, + int count) +{ + + int ret = -1; + char key[256] = {0, }; + char *peer_uuid_str = NULL; + + GF_ASSERT (peerinfo); + GF_ASSERT (friends); + + snprintf (key, sizeof (key), "friend%d.uuid", count); + peer_uuid_str = gd_peer_uuid_str (peerinfo); + ret = dict_set_str (friends, key, peer_uuid_str); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.hostname", count); + ret = dict_set_str (friends, key, peerinfo->hostname); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.port", count); + ret = dict_set_int32 (friends, key, peerinfo->port); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.stateId", count); + ret = dict_set_int32 (friends, key, peerinfo->state.state); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.state", count); + ret = dict_set_str (friends, key, + glusterd_friend_sm_state_name_get(peerinfo->state.state)); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d.connected", count); + ret = dict_set_int32 (friends, key, (int32_t)peerinfo->connected); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d", count); + ret = gd_add_peer_hostnames_to_dict (peerinfo, friends, key); + +out: + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.h b/xlators/mgmt/glusterd/src/glusterd-peer-utils.h new file mode 100644 index 00000000000..9877d861af7 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.h @@ -0,0 +1,87 @@ +/* + Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GLUSTERD_PEER_UTILS_H +#define _GLUSTERD_PEER_UTILS_H + +#include "glusterd.h" +#include "glusterd-utils.h" + +int32_t +glusterd_peerinfo_cleanup (glusterd_peerinfo_t *peerinfo); + +int32_t +glusterd_peerinfo_destroy (glusterd_peerinfo_t *peerinfo); + +glusterd_peerinfo_t * +glusterd_peerinfo_find_by_hostname (const char *hoststr); + +int +glusterd_hostname_to_uuid (char *hostname, uuid_t uuid); + +glusterd_peerinfo_t * +glusterd_peerinfo_find_by_uuid (uuid_t uuid); + +glusterd_peerinfo_t * +glusterd_peerinfo_find (uuid_t uuid, const char *hostname); + +glusterd_peerinfo_t * +glusterd_peerinfo_new (glusterd_friend_sm_state_t state, uuid_t *uuid, + const char *hostname, int port); + +gf_boolean_t +glusterd_chk_peers_connected_befriended (uuid_t skip_uuid); + +char * +glusterd_uuid_to_hostname (uuid_t uuid); + +char* +gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo); + +gf_boolean_t +glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, + struct list_head *peers, char **down_peerstr); + +int32_t +glusterd_peer_hostname_new (const char *hostname, + glusterd_peer_hostname_t **name); +void +glusterd_peer_hostname_free (glusterd_peer_hostname_t *name); + +gf_boolean_t +gd_peer_has_address (glusterd_peerinfo_t *peerinfo, const char *address); + +int +gd_add_address_to_peer (glusterd_peerinfo_t *peerinfo, const char *address); + +int +gd_add_friend_to_dict (glusterd_peerinfo_t *friend, dict_t *dict, + const char *prefix); + +glusterd_peerinfo_t * +gd_peerinfo_find_from_hostname (const char *hoststr); + +glusterd_peerinfo_t * +gd_peerinfo_find_from_addrinfo (const struct addrinfo *addr); + +int +gd_update_peerinfo_from_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict, + const char *prefix); + +glusterd_peerinfo_t * +gd_peerinfo_from_dict (dict_t *dict, const char *prefix); + +int +gd_add_peer_hostnames_to_dict (glusterd_peerinfo_t *peerinfo, dict_t *dict, + const char *prefix); +int +gd_add_peer_detail_to_dict (glusterd_peerinfo_t *peerinfo, dict_t *friends, + int count); +#endif /* _GLUSTERD_PEER_UTILS_H */ diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c index d33dc7a32ee..7c2b545905d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c +++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c @@ -521,8 +521,9 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, } if (!gf_is_local_addr (host)) { - ret = glusterd_friend_find (NULL, host, &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find (NULL, host); + if (peerinfo == NULL) { + ret = -1; snprintf (msg, sizeof (msg), "%s, is not a friend", host); *op_errstr = gf_strdup (msg); diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 10d5d7f2752..19b66ac06d8 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -214,25 +214,32 @@ int __glusterd_probe_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) { - gd1_mgmt_probe_rsp rsp = {{0},}; - int ret = 0; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_friend_sm_event_t *event = NULL; - glusterd_probe_ctx_t *ctx = NULL; + gd1_mgmt_probe_rsp rsp = {{0},}; + int ret = 0; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_friend_sm_event_t *event = NULL; + glusterd_probe_ctx_t *ctx = NULL; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; if (-1 == req->rpc_status) { goto out; } + this = THIS; + GF_ASSERT (this != NULL); + conf = this->private; + GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); + ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gd1_mgmt_probe_rsp); if (ret < 0) { - gf_log ("", GF_LOG_ERROR, "error"); + gf_log (this->name, GF_LOG_ERROR, "error"); //rsp.op_ret = -1; //rsp.op_errno = EINVAL; goto out; } - gf_log ("glusterd", GF_LOG_INFO, + gf_log (this->name, GF_LOG_INFO, "Received probe resp from uuid: %s, host: %s", uuid_utoa (rsp.uuid), rsp.hostname); if (rsp.op_ret != 0) { @@ -254,12 +261,82 @@ __glusterd_probe_cbk (struct rpc_req *req, struct iovec *iov, ret = rsp.op_ret; goto out; } - ret = glusterd_friend_find (rsp.uuid, rsp.hostname, &peerinfo); - if (ret) { + + peerinfo = glusterd_peerinfo_find (rsp.uuid, rsp.hostname); + if (peerinfo == NULL) { GF_ASSERT (0); } - if (strncasecmp (rsp.hostname, peerinfo->hostname, 1024)) { + /* + * In the case of a fresh probe rsp.uuid and peerinfo.uuid will not + * match, as peerinfo->uuid will be NULL. + * + * In the case of a peer probe being done to add a new network to a + * peer, rsp.uuid will match an existing peerinfo.uuid. If we have this + * stage it means that the current address/hostname being used isn't + * present in the found peerinfo. If it were, we would have found out + * earlier in the probe process and wouldn't even reach till here. So, + * we need to add the new hostname to the peer. + * + * This addition should only be done for cluster op-version >= + * GD_OP_VERSION_3_6_0 as address lists are only supported from then on. + * Also, this update should only be done when an explicit CLI probe + * command was used to begin the probe process. + */ + if ((conf->op_version >= GD_OP_VERSION_3_6_0) && + (uuid_compare (rsp.uuid, peerinfo->uuid) == 0)) { + ctx = ((call_frame_t *)myframe)->local; + /* Presence of ctx->req implies this probe was started by a cli + * probe command + */ + if (ctx->req == NULL) + goto cont; + + gf_log (this->name, GF_LOG_DEBUG, "Adding address '%s' to " + "existing peer %s", rsp.hostname, uuid_utoa (rsp.uuid)); + + ret = glusterd_friend_remove (NULL, rsp.hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Could not remove " + "stale peerinfo with name %s", rsp.hostname); + goto reply; + } + + ret = gd_add_address_to_peer (peerinfo, rsp.hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Couldn't add hostname to peer list"); + goto reply; + } + + /* Injecting LOCAL_ACC to send update */ + ret = glusterd_friend_sm_new_event (GD_FRIEND_EVENT_LOCAL_ACC, + &event); + if (!ret) { + event->peerinfo = peerinfo; + ret = glusterd_friend_sm_inject_event (event); + } + rsp.op_errno = GF_PROBE_FRIEND; + +reply: + ctx = ((call_frame_t *)myframe)->local; + ((call_frame_t *)myframe)->local = NULL; + + GF_ASSERT (ctx); + + if (ctx->req) { + glusterd_xfer_cli_probe_resp (ctx->req, ret, + rsp.op_errno, + rsp.op_errstr, + ctx->hostname, ctx->port, + ctx->dict); + } + + glusterd_destroy_probe_ctx (ctx); + + goto out; + + } else if (strncasecmp (rsp.hostname, peerinfo->hostname, 1024)) { gf_log (THIS->name, GF_LOG_INFO, "Host: %s with uuid: %s " "already present in cluster with alias hostname: %s", rsp.hostname, uuid_utoa (rsp.uuid), peerinfo->hostname); @@ -283,7 +360,7 @@ __glusterd_probe_cbk (struct rpc_req *req, struct iovec *iov, ret = rsp.op_ret; goto out; } - +cont: uuid_copy (peerinfo->uuid, rsp.uuid); ret = glusterd_friend_sm_new_event @@ -358,9 +435,9 @@ __glusterd_friend_add_cbk (struct rpc_req * req, struct iovec *iov, "Received %s from uuid: %s, host: %s, port: %d", (op_ret)?"RJT":"ACC", uuid_utoa (rsp.uuid), rsp.hostname, rsp.port); - ret = glusterd_friend_find (rsp.uuid, rsp.hostname, &peerinfo); - - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, rsp.hostname); + if (peerinfo == NULL) { + ret = -1; gf_log ("", GF_LOG_ERROR, "received friend add response from" " unknown peer uuid: %s", uuid_utoa (rsp.uuid)); goto out; @@ -469,11 +546,11 @@ __glusterd_friend_remove_cbk (struct rpc_req * req, struct iovec *iov, (op_ret)?"RJT":"ACC", uuid_utoa (rsp.uuid), rsp.hostname, rsp.port); inject: - ret = glusterd_friend_find (rsp.uuid, ctx->hostname, &peerinfo); - - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, ctx->hostname); + if (peerinfo == NULL) { //can happen as part of rpc clnt connection cleanup //when the frame timeout happens after 30 minutes + ret = -1; goto respond; } @@ -610,9 +687,9 @@ out: "Received lock %s from uuid: %s", (op_ret) ? "RJT" : "ACC", uuid_utoa (rsp.uuid)); - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { + ret = -1; gf_log (this->name, GF_LOG_CRITICAL, "Lock response received " "from unknown peer: %s", uuid_utoa (rsp.uuid)); } @@ -687,8 +764,9 @@ glusterd_mgmt_v3_lock_peers_cbk_fn (struct rpc_req *req, struct iovec *iov, "Received mgmt_v3 lock %s from uuid: %s", (op_ret) ? "RJT" : "ACC", uuid_utoa (rsp.uuid)); - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { + ret = -1; gf_log (this->name, GF_LOG_CRITICAL, "mgmt_v3 lock response received " "from unknown peer: %s. Ignoring response", @@ -768,9 +846,9 @@ glusterd_mgmt_v3_unlock_peers_cbk_fn (struct rpc_req *req, struct iovec *iov, (op_ret) ? "RJT" : "ACC", uuid_utoa (rsp.uuid)); - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { + ret = -1; gf_log (this->name, GF_LOG_CRITICAL, "mgmt_v3 unlock response received " "from unknown peer: %s. Ignoring response", @@ -851,9 +929,8 @@ out: "Received unlock %s from uuid: %s", (op_ret)?"RJT":"ACC", uuid_utoa (rsp.uuid)); - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { gf_log (this->name, GF_LOG_CRITICAL, "Unlock response received " "from unknown peer %s", uuid_utoa (rsp.uuid)); } @@ -959,11 +1036,12 @@ out: gf_log (this->name, GF_LOG_DEBUG, "transaction ID = %s", uuid_utoa (*txn_id)); - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - if (ret) + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { gf_log (this->name, GF_LOG_CRITICAL, "Stage response received " "from unknown peer: %s. Ignoring response.", uuid_utoa (rsp.uuid)); + } if (op_ret) { event_type = GD_OP_EVENT_RCVD_RJT; @@ -1094,8 +1172,8 @@ __glusterd_commit_op_cbk (struct rpc_req *req, struct iovec *iov, gf_log (this->name, GF_LOG_DEBUG, "transaction ID = %s", uuid_utoa (*txn_id)); - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { gf_log (this->name, GF_LOG_CRITICAL, "Commit response for " "'Volume %s' received from unknown peer: %s", gd_op_list[opinfo.op], uuid_utoa (rsp.uuid)); diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c index 8807ef94a72..ca047bd3322 100644 --- a/xlators/mgmt/glusterd/src/glusterd-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-sm.c @@ -313,8 +313,8 @@ glusterd_ac_friend_probe (glusterd_friend_sm_event_t *event, void *ctx) GF_ASSERT (conf); - ret = glusterd_friend_find (NULL, probe_ctx->hostname, &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find (NULL, probe_ctx->hostname); + if (peerinfo == NULL) { //We should not reach this state ideally GF_ASSERT (0); goto out; @@ -456,7 +456,6 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) glusterd_conf_t *priv = NULL; dict_t *friends = NULL; char key[100] = {0,}; - char *dup_buf = NULL; int32_t count = 0; GF_ASSERT (event); @@ -483,17 +482,12 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) continue; count++; - snprintf (key, sizeof (key), "friend%d.uuid", count); - dup_buf = gf_strdup (uuid_utoa (peerinfo->uuid)); - ret = dict_set_dynstr (friends, key, dup_buf); - if (ret) - goto out; - snprintf (key, sizeof (key), "friend%d.hostname", count); - ret = dict_set_str (friends, key, peerinfo->hostname); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "friend%d", count); + ret = gd_add_friend_to_dict (peerinfo, friends, key); if (ret) goto out; - gf_log ("", GF_LOG_INFO, "Added uuid: %s, host: %s", - dup_buf, peerinfo->hostname); } ret = dict_set_int32 (friends, "count", count); @@ -622,7 +616,7 @@ glusterd_ac_friend_remove (glusterd_friend_sm_event_t *event, void *ctx) gf_msg (THIS->name, GF_LOG_WARNING, 0, GD_MSG_VOL_CLEANUP_FAIL, "Volumes cleanup failed"); - ret = glusterd_friend_cleanup (event->peerinfo); + ret = glusterd_peerinfo_cleanup (event->peerinfo); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Cleanup returned: %d", ret); } diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.h b/xlators/mgmt/glusterd/src/glusterd-sm.h index 6b3b61dfc5c..294dbacc9d0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-sm.h @@ -59,7 +59,7 @@ typedef struct glusterd_peer_state_info_ { typedef struct glusterd_peer_hostname_ { char *hostname; struct list_head hostname_list; -}glusterd_peer_hostname_t; +} glusterd_peer_hostname_t; typedef struct glusterd_sm_transition_ { int old_state; @@ -84,6 +84,7 @@ struct glusterd_peerinfo_ { */ glusterd_peer_state_info_t state; char *hostname; + struct list_head hostnames; int port; struct list_head uuid_list; struct list_head op_peers_list; @@ -92,7 +93,7 @@ struct glusterd_peerinfo_ { rpc_clnt_prog_t *peer; rpc_clnt_prog_t *mgmt_v3; int connected; - gf_store_handle_t *shandle; + gf_store_handle_t *shandle; glusterd_sm_tr_log_t sm_log; gf_boolean_t quorum_action; gd_quorum_contrib_t quorum_contrib; diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c index 086a6550a72..06e8101a3a5 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -3853,7 +3853,7 @@ glusterd_store_create_peer_shandle (glusterd_peerinfo_t *peerinfo) GF_ASSERT (peerinfo); - if (glusterd_peerinfo_is_uuid_unknown (peerinfo)) { + if (uuid_is_null (peerinfo->uuid)) { ret = glusterd_store_peerinfo_hostname_shandle_create (peerinfo); } else { ret = glusterd_peerinfo_hostname_shandle_check_destroy (peerinfo); @@ -3865,8 +3865,11 @@ glusterd_store_create_peer_shandle (glusterd_peerinfo_t *peerinfo) int32_t glusterd_store_peer_write (int fd, glusterd_peerinfo_t *peerinfo) { - char buf[50] = {0}; - int32_t ret = 0; + char buf[50] = {0}; + int32_t ret = 0; + int32_t i = 1; + glusterd_peer_hostname_t *hostname = NULL; + char *key = NULL; ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_PEER_UUID, uuid_utoa (peerinfo->uuid)); @@ -3878,10 +3881,18 @@ glusterd_store_peer_write (int fd, glusterd_peerinfo_t *peerinfo) if (ret) goto out; - ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_PEER_HOSTNAME "1", - peerinfo->hostname); - if (ret) - goto out; + list_for_each_entry (hostname, &peerinfo->hostnames, hostname_list) { + ret = gf_asprintf (&key, GLUSTERD_STORE_KEY_PEER_HOSTNAME"%d", + i); + if (ret < 0) + goto out; + ret = gf_store_save_value (fd, key, hostname->hostname); + if (ret) + goto out; + GF_FREE (key); + key = NULL; + i++; + } out: gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); @@ -3938,22 +3949,21 @@ out: int32_t glusterd_store_retrieve_peers (xlator_t *this) { - int32_t ret = 0; - glusterd_conf_t *priv = NULL; - DIR *dir = NULL; - struct dirent *entry = NULL; - char path[PATH_MAX] = {0,}; - glusterd_peerinfo_t *peerinfo = NULL; - uuid_t uuid = {0,}; - char *hostname = NULL; - int32_t state = 0; - gf_store_handle_t *shandle = NULL; - char filepath[PATH_MAX] = {0,}; - gf_store_iter_t *iter = NULL; - char *key = NULL; - char *value = NULL; - glusterd_peerctx_args_t args = {0}; - gf_store_op_errno_t op_errno = GD_STORE_SUCCESS; + int32_t ret = 0; + glusterd_conf_t *priv = NULL; + DIR *dir = NULL; + struct dirent *entry = NULL; + char path[PATH_MAX] = {0,}; + glusterd_peerinfo_t *peerinfo = NULL; + char *hostname = NULL; + gf_store_handle_t *shandle = NULL; + char filepath[PATH_MAX] = {0,}; + gf_store_iter_t *iter = NULL; + char *key = NULL; + char *value = NULL; + glusterd_peerctx_args_t args = {0}; + gf_store_op_errno_t op_errno = GD_STORE_SUCCESS; + glusterd_peer_hostname_t *address = NULL; GF_ASSERT (this); priv = this->private; @@ -3987,20 +3997,30 @@ glusterd_store_retrieve_peers (xlator_t *this) if (ret) goto out; + /* Create an empty peerinfo object before reading in the + * details + */ + peerinfo = glusterd_peerinfo_new (GD_FRIEND_STATE_DEFAULT, NULL, + NULL, 0); + if (peerinfo == NULL) { + ret = -1; + goto out; + } + while (!ret) { if (!strncmp (GLUSTERD_STORE_KEY_PEER_UUID, key, strlen (GLUSTERD_STORE_KEY_PEER_UUID))) { if (value) - uuid_parse (value, uuid); + uuid_parse (value, peerinfo->uuid); } else if (!strncmp (GLUSTERD_STORE_KEY_PEER_STATE, key, strlen (GLUSTERD_STORE_KEY_PEER_STATE))) { - state = atoi (value); + peerinfo->state.state = atoi (value); } else if (!strncmp (GLUSTERD_STORE_KEY_PEER_HOSTNAME, key, strlen (GLUSTERD_STORE_KEY_PEER_HOSTNAME))) { - hostname = gf_strdup (value); + ret = gd_add_address_to_peer (peerinfo, value); } else { gf_log ("", GF_LOG_ERROR, "Unknown key: %s", key); @@ -4021,14 +4041,23 @@ glusterd_store_retrieve_peers (xlator_t *this) (void) gf_store_iter_destroy (iter); - ret = glusterd_friend_add (hostname, 0, state, &uuid, - &peerinfo, 1, NULL); + /* Set first hostname from peerinfo->hostnames to + * peerinfo->hostname + */ + address = list_entry (peerinfo->hostnames.next, + glusterd_peer_hostname_t, hostname_list); + if (!address) { + ret = -1; + goto out; + } + peerinfo->hostname = gf_strdup (address->hostname); - GF_FREE (hostname); + ret = glusterd_friend_add_from_peerinfo (peerinfo, 1, NULL); if (ret) goto out; peerinfo->shandle = shandle; + peerinfo = NULL; glusterd_for_each_entry (entry, dir); } @@ -4038,8 +4067,12 @@ glusterd_store_retrieve_peers (xlator_t *this) if (ret) goto out; } + peerinfo = NULL; out: + if (peerinfo) + glusterd_peerinfo_cleanup (peerinfo); + if (dir) closedir (dir); gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c index 6e7a9b6c8be..67ceb20c2e7 100644 --- a/xlators/mgmt/glusterd/src/glusterd-syncop.c +++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c @@ -673,8 +673,9 @@ _gd_syncop_stage_op_cbk (struct rpc_req *req, struct iovec *iov, } } - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { + ret = -1; gf_log (this->name, GF_LOG_CRITICAL, "Staging response " "for 'Volume %s' received from unknown " "peer: %s", gd_op_list[rsp.op], @@ -929,8 +930,9 @@ _gd_syncop_commit_op_cbk (struct rpc_req *req, struct iovec *iov, } } - ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find (rsp.uuid, NULL); + if (peerinfo == NULL) { + ret = -1; gf_log (this->name, GF_LOG_CRITICAL, "Commit response " "for 'Volume %s' received from unknown " "peer: %s", gd_op_list[rsp.op], diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index baa845b0a91..7eddb753dc6 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -82,18 +82,6 @@ static glusterd_lock_t lock; -char* -gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo) -{ - if ((peerinfo == NULL) || uuid_is_null (peerinfo->uuid)) - return NULL; - - if (peerinfo->uuid_str[0] == '\0') - uuid_utoa_r (peerinfo->uuid, peerinfo->uuid_str); - - return peerinfo->uuid_str; -} - int32_t glusterd_get_lock_owner (uuid_t *uuid) @@ -1403,38 +1391,6 @@ out: return decommissioned; } -int32_t -glusterd_friend_cleanup (glusterd_peerinfo_t *peerinfo) -{ - GF_ASSERT (peerinfo); - glusterd_peerctx_t *peerctx = NULL; - gf_boolean_t quorum_action = _gf_false; - glusterd_conf_t *priv = THIS->private; - - if (peerinfo->quorum_contrib != QUORUM_NONE) - quorum_action = _gf_true; - if (peerinfo->rpc) { - /* cleanup the saved-frames before last unref */ - synclock_unlock (&priv->big_lock); - rpc_clnt_connection_cleanup (&peerinfo->rpc->conn); - synclock_lock (&priv->big_lock); - - peerctx = peerinfo->rpc->mydata; - peerinfo->rpc->mydata = NULL; - peerinfo->rpc = glusterd_rpc_clnt_unref (priv, peerinfo->rpc); - peerinfo->rpc = NULL; - if (peerctx) { - GF_FREE (peerctx->errstr); - GF_FREE (peerctx); - } - } - glusterd_peer_destroy (peerinfo); - - if (quorum_action) - glusterd_do_quorum_action (); - return 0; -} - int glusterd_volinfo_find_by_volume_id (uuid_t volume_id, glusterd_volinfo_t **volinfo) { @@ -1986,32 +1942,6 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, return ret; } -int32_t -glusterd_peer_hostname_new (char *hostname, glusterd_peer_hostname_t **name) -{ - glusterd_peer_hostname_t *peer_hostname = NULL; - int32_t ret = -1; - - GF_ASSERT (hostname); - GF_ASSERT (name); - - peer_hostname = GF_CALLOC (1, sizeof (*peer_hostname), - gf_gld_mt_peer_hostname_t); - - if (!peer_hostname) - goto out; - - peer_hostname->hostname = gf_strdup (hostname); - INIT_LIST_HEAD (&peer_hostname->hostname_list); - - *name = peer_hostname; - ret = 0; - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - /* Free LINE[0..N-1] and then the LINE buffer. */ static void free_lines (char **line, size_t n) @@ -7671,163 +7601,6 @@ out: return ret; } -int -glusterd_friend_find_by_uuid (uuid_t uuid, - glusterd_peerinfo_t **peerinfo) -{ - int ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_peerinfo_t *entry = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (peerinfo); - - *peerinfo = NULL; - priv = this->private; - - GF_ASSERT (priv); - - if (uuid_is_null (uuid)) - return -1; - - list_for_each_entry (entry, &priv->peers, uuid_list) { - if (!uuid_compare (entry->uuid, uuid)) { - - gf_log (this->name, GF_LOG_DEBUG, - "Friend found... state: %s", - glusterd_friend_sm_state_name_get (entry->state.state)); - *peerinfo = entry; - return 0; - } - } - - gf_log (this->name, GF_LOG_DEBUG, "Friend with uuid: %s, not found", - uuid_utoa (uuid)); - return ret; -} - - -int -glusterd_friend_find_by_hostname (const char *hoststr, - glusterd_peerinfo_t **peerinfo) -{ - int ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_peerinfo_t *entry = NULL; - struct addrinfo *addr = NULL; - struct addrinfo *p = NULL; - char *host = NULL; - struct sockaddr_in6 *s6 = NULL; - struct sockaddr_in *s4 = NULL; - struct in_addr *in_addr = NULL; - char hname[1024] = {0,}; - xlator_t *this = NULL; - - - this = THIS; - GF_ASSERT (hoststr); - GF_ASSERT (peerinfo); - - *peerinfo = NULL; - priv = this->private; - - GF_ASSERT (priv); - - list_for_each_entry (entry, &priv->peers, uuid_list) { - if (!strncasecmp (entry->hostname, hoststr, - 1024)) { - - gf_log (this->name, GF_LOG_DEBUG, - "Friend %s found.. state: %d", hoststr, - entry->state.state); - *peerinfo = entry; - return 0; - } - } - - ret = getaddrinfo (hoststr, NULL, NULL, &addr); - if (ret != 0) { - gf_log (this->name, GF_LOG_ERROR, - "error in getaddrinfo: %s\n", - gai_strerror(ret)); - goto out; - } - - for (p = addr; p != NULL; p = p->ai_next) { - switch (p->ai_family) { - case AF_INET: - s4 = (struct sockaddr_in *) p->ai_addr; - in_addr = &s4->sin_addr; - break; - case AF_INET6: - s6 = (struct sockaddr_in6 *) p->ai_addr; - in_addr =(struct in_addr *) &s6->sin6_addr; - break; - default: ret = -1; - goto out; - } - host = inet_ntoa(*in_addr); - - ret = getnameinfo (p->ai_addr, p->ai_addrlen, hname, - 1024, NULL, 0, 0); - if (ret) - goto out; - - list_for_each_entry (entry, &priv->peers, uuid_list) { - if (!strncasecmp (entry->hostname, host, - 1024) || !strncasecmp (entry->hostname,hname, - 1024)) { - gf_log (this->name, GF_LOG_DEBUG, - "Friend %s found.. state: %d", - hoststr, entry->state.state); - *peerinfo = entry; - freeaddrinfo (addr); - return 0; - } - } - } - -out: - gf_log (this->name, GF_LOG_DEBUG, "Unable to find friend: %s", hoststr); - if (addr) - freeaddrinfo (addr); - return -1; -} - -int -glusterd_hostname_to_uuid (char *hostname, uuid_t uuid) -{ - GF_ASSERT (hostname); - GF_ASSERT (uuid); - - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_conf_t *priv = NULL; - int ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - ret = glusterd_friend_find_by_hostname (hostname, &peerinfo); - if (ret) { - if (gf_is_local_addr (hostname)) { - uuid_copy (uuid, MY_UUID); - ret = 0; - } else { - goto out; - } - } else { - uuid_copy (uuid, peerinfo->uuid); - } - -out: - gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret); - return ret; -} int glusterd_brick_stop (glusterd_volinfo_t *volinfo, @@ -7946,9 +7719,9 @@ glusterd_new_brick_validate (char *brick, glusterd_brickinfo_t *brickinfo, } } else { - ret = glusterd_friend_find_by_uuid (newbrickinfo->uuid, - &peerinfo); - if (ret) { + peerinfo = glusterd_peerinfo_find_by_uuid (newbrickinfo->uuid); + if (peerinfo == NULL) { + ret = -1; snprintf (op_errstr, len, "Failed to find host %s", newbrickinfo->hostname); goto out; @@ -8375,76 +8148,6 @@ out: } int -glusterd_peerinfo_new (glusterd_peerinfo_t **peerinfo, - glusterd_friend_sm_state_t state, uuid_t *uuid, - const char *hostname, int port) -{ - glusterd_peerinfo_t *new_peer = NULL; - int ret = -1; - - GF_ASSERT (peerinfo); - if (!peerinfo) - goto out; - - new_peer = GF_CALLOC (1, sizeof (*new_peer), gf_gld_mt_peerinfo_t); - if (!new_peer) - goto out; - - new_peer->state.state = state; - if (hostname) - new_peer->hostname = gf_strdup (hostname); - - INIT_LIST_HEAD (&new_peer->uuid_list); - - if (uuid) { - uuid_copy (new_peer->uuid, *uuid); - } - - ret = glusterd_sm_tr_log_init (&new_peer->sm_log, - glusterd_friend_sm_state_name_get, - glusterd_friend_sm_event_name_get, - GLUSTERD_TR_LOG_SIZE); - if (ret) - goto out; - - if (new_peer->state.state == GD_FRIEND_STATE_BEFRIENDED) - new_peer->quorum_contrib = QUORUM_WAITING; - new_peer->port = port; - *peerinfo = new_peer; -out: - if (ret && new_peer) - glusterd_friend_cleanup (new_peer); - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; -} - -int32_t -glusterd_peer_destroy (glusterd_peerinfo_t *peerinfo) -{ - int32_t ret = -1; - - if (!peerinfo) - goto out; - - ret = glusterd_store_delete_peerinfo (peerinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Deleting peer info failed"); - } - - list_del_init (&peerinfo->uuid_list); - GF_FREE (peerinfo->hostname); - glusterd_sm_tr_log_delete (&peerinfo->sm_log); - GF_FREE (peerinfo); - peerinfo = NULL; - - ret = 0; - -out: - return ret; -} - -int glusterd_remove_pending_entry (struct list_head *list, void *elem) { glusterd_pending_node_t *pending_node = NULL; @@ -8479,16 +8182,6 @@ glusterd_clear_pending_nodes (struct list_head *list) return 0; } -gf_boolean_t -glusterd_peerinfo_is_uuid_unknown (glusterd_peerinfo_t *peerinfo) -{ - GF_ASSERT (peerinfo); - - if (uuid_is_null (peerinfo->uuid)) - return _gf_true; - return _gf_false; -} - int32_t glusterd_delete_volume (glusterd_volinfo_t *volinfo) { @@ -9149,36 +8842,6 @@ out: return ret; } -/* Check if the all peers are connected and befriended, except the peer - * specified (the peer being detached) - */ -gf_boolean_t -glusterd_chk_peers_connected_befriended (uuid_t skip_uuid) -{ - gf_boolean_t ret = _gf_true; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_conf_t *priv = NULL; - - priv= THIS->private; - GF_ASSERT (priv); - - list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - - if (!uuid_is_null (skip_uuid) && !uuid_compare (skip_uuid, - peerinfo->uuid)) - continue; - - if ((GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state) - || !(peerinfo->connected)) { - ret = _gf_false; - break; - } - } - gf_log (THIS->name, GF_LOG_DEBUG, "Returning %s", - (ret?"TRUE":"FALSE")); - return ret; -} - void glusterd_get_client_filepath (char *filepath, glusterd_volinfo_t *volinfo, gf_transport_type type) @@ -9303,34 +8966,6 @@ glusterd_volinfo_reset_defrag_stats (glusterd_volinfo_t *volinfo) } -/* Return hostname for given uuid if it exists - * else return NULL - */ -char * -glusterd_uuid_to_hostname (uuid_t uuid) -{ - char *hostname = NULL; - glusterd_conf_t *priv = NULL; - glusterd_peerinfo_t *entry = NULL; - - priv = THIS->private; - GF_ASSERT (priv); - - if (!uuid_compare (MY_UUID, uuid)) { - hostname = gf_strdup ("localhost"); - } - if (!list_empty (&priv->peers)) { - list_for_each_entry (entry, &priv->peers, uuid_list) { - if (!uuid_compare (entry->uuid, uuid)) { - hostname = gf_strdup (entry->hostname); - break; - } - } - } - - return hostname; -} - gf_boolean_t glusterd_is_local_brick (xlator_t *this, glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo) @@ -11787,42 +11422,6 @@ gd_is_remove_brick_committed (glusterd_volinfo_t *volinfo) } gf_boolean_t -glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, - struct list_head *peers, - char **down_peerstr) -{ - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - gf_boolean_t ret = _gf_false; - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (!uuid_compare (brickinfo->uuid, MY_UUID)) - continue; - - list_for_each_entry (peerinfo, peers, uuid_list) { - if (uuid_compare (peerinfo->uuid, brickinfo->uuid)) - continue; - - /*Found peer who owns the brick, return false - * if peer is not connected or not friend */ - if (!(peerinfo->connected) || - (peerinfo->state.state != - GD_FRIEND_STATE_BEFRIENDED)) { - *down_peerstr = gf_strdup (peerinfo->hostname); - gf_log ("", GF_LOG_DEBUG, "Peer %s is down. ", - peerinfo->hostname); - goto out; - } - } - } - - ret = _gf_true; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -gf_boolean_t glusterd_is_status_tasks_op (glusterd_op_t op, dict_t *dict) { int ret = -1; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index aef28de1b8d..f8dfce7ca82 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -29,6 +29,7 @@ #include "protocol-common.h" #include "glusterfs3-xdr.h" +#include "glusterd-peer-utils.h" #define GLUSTERD_SOCK_DIR "/var/run" #define GLUSTERD_ASSIGN_BRICKID_TO_BRICKINFO(brickinfo, volinfo, brickid) do {\ @@ -125,15 +126,6 @@ int32_t glusterd_brickinfo_new_from_brick (char *brick, glusterd_brickinfo_t **brickinfo); int32_t -glusterd_friend_cleanup (glusterd_peerinfo_t *peerinfo); - -int32_t -glusterd_peer_destroy (glusterd_peerinfo_t *peerinfo); - -int32_t -glusterd_peer_hostname_new (char *hostname, glusterd_peer_hostname_t **name); - -int32_t glusterd_snap_volinfo_find (char *volname, glusterd_snap_t *snap, glusterd_volinfo_t **volinfo); int32_t @@ -312,12 +304,6 @@ gf_boolean_t glusterd_is_brick_started (glusterd_brickinfo_t *brickinfo); int -glusterd_friend_find_by_hostname (const char *hoststr, - glusterd_peerinfo_t **peerinfo); -int -glusterd_hostname_to_uuid (char *hostname, uuid_t uuid); - -int glusterd_friend_brick_belongs (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, void *uuid); int @@ -339,9 +325,6 @@ int32_t glusterd_volinfo_bricks_delete (glusterd_volinfo_t *volinfo); int -glusterd_friend_find_by_uuid (uuid_t uuid, - glusterd_peerinfo_t **peerinfo); -int glusterd_new_brick_validate (char *brick, glusterd_brickinfo_t *brickinfo, char *op_errstr, size_t len); int32_t @@ -385,10 +368,6 @@ glusterd_sm_tr_log_transition_add (glusterd_sm_tr_log_t *log, int old_state, int new_state, int event); int -glusterd_peerinfo_new (glusterd_peerinfo_t **peerinfo, - glusterd_friend_sm_state_t state, uuid_t *uuid, - const char *hostname, int port); -int glusterd_sm_tr_log_init (glusterd_sm_tr_log_t *log, char * (*state_name_get) (int), char * (*event_name_get) (int), @@ -403,8 +382,6 @@ int glusterd_remove_pending_entry (struct list_head *list, void *elem); int glusterd_clear_pending_nodes (struct list_head *list); -gf_boolean_t -glusterd_peerinfo_is_uuid_unknown (glusterd_peerinfo_t *peerinfo); int32_t glusterd_brick_connect (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, char *socketpath); @@ -481,9 +458,6 @@ glusterd_friend_contains_vol_bricks (glusterd_volinfo_t *volinfo, int glusterd_friend_remove_cleanup_vols (uuid_t uuid); -gf_boolean_t -glusterd_chk_peers_connected_befriended (uuid_t skip_uuid); - void glusterd_get_client_filepath (char *filepath, glusterd_volinfo_t *volinfo, @@ -503,9 +477,6 @@ int glusterd_add_node_to_dict (char *server, dict_t *dict, int count, dict_t *vol_opts); -char * -glusterd_uuid_to_hostname (uuid_t uuid); - int glusterd_get_dist_leaf_count (glusterd_volinfo_t *volinfo); @@ -577,11 +548,6 @@ glusterd_profile_volume_brick_rsp (void *pending_entry, dict_t *rsp_dict, dict_t *op_ctx, char **op_errstr, gd_node_type type); -gf_boolean_t -glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, - struct list_head *peers, - char **down_peerstr); - int32_t glusterd_set_originator_uuid (dict_t *dict); @@ -632,17 +598,9 @@ gd_update_volume_op_versions (glusterd_volinfo_t *volinfo); int op_version_check (xlator_t *this, int min_op_version, char *msg, int msglen); -char* -gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo); - gf_boolean_t gd_is_remove_brick_committed (glusterd_volinfo_t *volinfo); -gf_boolean_t -glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, - struct list_head *peers, - char **down_peerstr); - int glusterd_get_slave_details_confpath (glusterd_volinfo_t *volinfo, dict_t *dict, char **slave_url, diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index ddbb2c81338..ec036f8cf06 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -651,16 +651,16 @@ glusterd_xfer_friend_add_resp (rpcsvc_request_t *req, char *myhostname, int32_t op_errno); int -glusterd_friend_find (uuid_t uuid, char *hostname, - glusterd_peerinfo_t **peerinfo); - -int glusterd_friend_add (const char *hoststr, int port, glusterd_friend_sm_state_t state, uuid_t *uuid, glusterd_peerinfo_t **friend, gf_boolean_t restore, glusterd_peerctx_args_t *args); int +glusterd_friend_add_from_peerinfo (glusterd_peerinfo_t *friend, + gf_boolean_t restore, + glusterd_peerctx_args_t *args); +int glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo, glusterd_peerctx_args_t *args); int |