diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-peer-utils.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-peer-utils.c | 312 |
1 files changed, 168 insertions, 144 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c index 5b5959ee721..18d355cb186 100644 --- a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c @@ -48,6 +48,7 @@ glusterd_peerinfo_destroy(struct rcu_head *head) } glusterd_sm_tr_log_delete(&peerinfo->sm_log); + pthread_mutex_unlock(&peerinfo->delete_lock); pthread_mutex_destroy(&peerinfo->delete_lock); GF_FREE(peerinfo); @@ -81,10 +82,112 @@ glusterd_peerinfo_cleanup(glusterd_peerinfo_t *peerinfo) call_rcu(&peerinfo->rcu_head.head, glusterd_peerinfo_destroy); if (quorum_action) + /* coverity[SLEEP] */ glusterd_do_quorum_action(); return 0; } +/* 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 + */ +static glusterd_peerinfo_t * +gd_peerinfo_find_from_hostname(const char *hoststr) +{ + xlator_t *this = THIS; + glusterd_conf_t *priv = NULL; + glusterd_peerinfo_t *peer = NULL; + glusterd_peerinfo_t *found = NULL; + glusterd_peer_hostname_t *tmphost = NULL; + + 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); + + RCU_READ_LOCK; + cds_list_for_each_entry_rcu(peer, &priv->peers, uuid_list) + { + cds_list_for_each_entry_rcu(tmphost, &peer->hostnames, hostname_list) + { + if (!strncasecmp(tmphost->hostname, hoststr, 1024)) { + gf_msg_debug(this->name, 0, "Friend %s found.. state: %d", + tmphost->hostname, peer->state.state); + found = peer; /* Probably needs to be + dereferenced*/ + goto unlock; + } + } + } +unlock: + RCU_READ_UNLOCK; +out: + return found; +} + +/* 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 + */ +static glusterd_peerinfo_t * +gd_peerinfo_find_from_addrinfo(const struct addrinfo *addr) +{ + xlator_t *this = THIS; + glusterd_conf_t *conf = NULL; + glusterd_peerinfo_t *peer = NULL; + glusterd_peerinfo_t *found = NULL; + glusterd_peer_hostname_t *address = NULL; + int ret = 0; + struct addrinfo *paddr = NULL; + struct addrinfo *tmp = NULL; + + GF_ASSERT(this != NULL); + conf = this->private; + GF_VALIDATE_OR_GOTO(this->name, (conf != NULL), out); + + RCU_READ_LOCK; + cds_list_for_each_entry_rcu(peer, &conf->peers, uuid_list) + { + cds_list_for_each_entry_rcu(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_msg_trace(this->name, 0, "getaddrinfo for %s failed (%s)", + address->hostname, gai_strerror(ret)); + continue; + } + + for (tmp = paddr; tmp != NULL; tmp = tmp->ai_next) { + if (gf_compare_sockaddr(addr->ai_addr, tmp->ai_addr)) { + found = peer; /* (de)referenced? */ + break; + } + } + + freeaddrinfo(paddr); + if (found) + goto unlock; + } + } +unlock: + RCU_READ_UNLOCK; +out: + return found; +} + /* 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. @@ -99,14 +202,11 @@ glusterd_peerinfo_find_by_hostname(const char *hoststr) int ret = -1; struct addrinfo *addr = NULL; struct addrinfo *p = NULL; - xlator_t *this = NULL; + xlator_t *this = THIS; glusterd_peerinfo_t *peerinfo = NULL; - this = THIS; GF_ASSERT(hoststr); - peerinfo = NULL; - peerinfo = gd_peerinfo_find_from_hostname(hoststr); if (peerinfo) return peerinfo; @@ -176,31 +276,33 @@ glusterd_peerinfo_find_by_uuid(uuid_t uuid) glusterd_conf_t *priv = NULL; glusterd_peerinfo_t *entry = NULL; glusterd_peerinfo_t *found = NULL; - xlator_t *this = NULL; + xlator_t *this = THIS; + glusterd_friend_sm_state_t state; - this = THIS; GF_ASSERT(this); + if (gf_uuid_is_null(uuid)) + return NULL; + priv = this->private; GF_ASSERT(priv); - if (gf_uuid_is_null(uuid)) - return NULL; - RCU_READ_LOCK; cds_list_for_each_entry_rcu(entry, &priv->peers, uuid_list) { if (!gf_uuid_compare(entry->uuid, uuid)) { - gf_msg_debug(this->name, 0, "Friend found... state: %s", - glusterd_friend_sm_state_name_get(entry->state.state)); found = entry; /* Probably should be rcu_dereferenced */ + state = found->state.state; break; } } RCU_READ_UNLOCK; - if (!found) + if (found) + gf_msg_debug(this->name, 0, "Friend found... state: %s", + glusterd_friend_sm_state_name_get(state)); + else gf_msg_debug(this->name, 0, "Friend with uuid: %s, not found", uuid_utoa(uuid)); return found; @@ -214,9 +316,8 @@ glusterd_peerinfo_t * glusterd_peerinfo_find(uuid_t uuid, const char *hostname) { glusterd_peerinfo_t *peerinfo = NULL; - xlator_t *this = NULL; + xlator_t *this = THIS; - this = THIS; GF_ASSERT(this); if (uuid) { @@ -266,8 +367,10 @@ glusterd_peerinfo_new(glusterd_friend_sm_state_t state, uuid_t *uuid, GF_ASSERT(conf); new_peer = GF_CALLOC(1, sizeof(*new_peer), gf_gld_mt_peerinfo_t); - if (!new_peer) + if (!new_peer) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, NULL); goto out; + } CDS_INIT_LIST_HEAD(&new_peer->uuid_list); @@ -357,6 +460,7 @@ glusterd_uuid_to_hostname(uuid_t uuid) if (!gf_uuid_compare(MY_UUID, uuid)) { hostname = gf_strdup("localhost"); + return hostname; } RCU_READ_LOCK; if (!cds_list_empty(&priv->peers)) { @@ -439,9 +543,8 @@ glusterd_are_vol_all_peers_up(glusterd_volinfo_t *volinfo, if (!(peerinfo->connected) || (peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED)) { *down_peerstr = gf_strdup(peerinfo->hostname); - gf_msg_debug(THIS->name, 0, "Peer %s is down. ", - peerinfo->hostname); RCU_READ_UNLOCK; + gf_msg_debug(THIS->name, 0, "Peer %s is down. ", *down_peerstr); goto out; } } @@ -463,12 +566,16 @@ glusterd_peer_hostname_new(const char *hostname, GF_ASSERT(hostname); GF_ASSERT(name); + xlator_t *this = THIS; + GF_ASSERT(this); peer_hostname = GF_CALLOC(1, sizeof(*peer_hostname), gf_gld_mt_peer_hostname_t); - if (!peer_hostname) + if (!peer_hostname) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, NULL); goto out; + } peer_hostname->hostname = gf_strdup(hostname); CDS_INIT_LIST_HEAD(&peer_hostname->hostname_list); @@ -500,7 +607,6 @@ glusterd_peer_hostname_free(glusterd_peer_hostname_t *name) 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); @@ -509,13 +615,12 @@ gd_peer_has_address(glusterd_peerinfo_t *peerinfo, const char *address) cds_list_for_each_entry(hostname, &peerinfo->hostnames, hostname_list) { if (strcmp(hostname->hostname, address) == 0) { - ret = _gf_true; - break; + return _gf_true; } } out: - return ret; + return _gf_false; } int @@ -624,112 +729,6 @@ out: 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_peerinfo_t *found = 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); - - RCU_READ_LOCK; - cds_list_for_each_entry_rcu(peer, &priv->peers, uuid_list) - { - cds_list_for_each_entry_rcu(tmphost, &peer->hostnames, hostname_list) - { - if (!strncasecmp(tmphost->hostname, hoststr, 1024)) { - gf_msg_debug(this->name, 0, "Friend %s found.. state: %d", - tmphost->hostname, peer->state.state); - found = peer; /* Probably needs to be - dereferenced*/ - goto unlock; - } - } - } -unlock: - RCU_READ_UNLOCK; -out: - return found; -} - -/* 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_peerinfo_t *found = 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); - - RCU_READ_LOCK; - cds_list_for_each_entry_rcu(peer, &conf->peers, uuid_list) - { - cds_list_for_each_entry_rcu(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_msg_trace(this->name, 0, "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)) { - found = peer; /* (de)referenced? */ - break; - } - } - - freeaddrinfo(paddr); - if (found) - goto unlock; - } - } -unlock: - RCU_READ_UNLOCK; -out: - return found; -} - /* gd_update_peerinfo_from_dict will update the hostnames for @peerinfo from * peer details with @prefix in @dict. * Returns 0 on success and -1 on failure. @@ -830,7 +829,7 @@ gd_peerinfo_from_dict(dict_t *dict, const char *prefix) xlator_t *this = NULL; glusterd_conf_t *conf = NULL; glusterd_peerinfo_t *new_peer = NULL; - char key[100] = { + char key[64] = { 0, }; char *uuid_str = NULL; @@ -875,14 +874,14 @@ out: return new_peer; } -int +static 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] = { + char key[64] = { 0, }; glusterd_peer_hostname_t *addr = NULL; @@ -907,8 +906,11 @@ gd_add_peer_hostnames_to_dict(glusterd_peerinfo_t *peerinfo, dict_t *dict, { snprintf(key, sizeof(key), "%s.hostname%d", prefix, count); ret = dict_set_dynstr_with_alloc(dict, key, addr->hostname); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Key=%s", key, NULL); goto out; + } count++; } @@ -924,47 +926,67 @@ gd_add_peer_detail_to_dict(glusterd_peerinfo_t *peerinfo, dict_t *friends, int count) { int ret = -1; - char key[64] = { + char key[32] = { 0, }; int keylen; char *peer_uuid_str = NULL; + xlator_t *this = THIS; + GF_ASSERT(this); GF_ASSERT(peerinfo); GF_ASSERT(friends); peer_uuid_str = gd_peer_uuid_str(peerinfo); keylen = snprintf(key, sizeof(key), "friend%d.uuid", count); ret = dict_set_strn(friends, key, keylen, peer_uuid_str); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "Key=%s", + key, NULL); goto out; + } keylen = snprintf(key, sizeof(key), "friend%d.hostname", count); ret = dict_set_strn(friends, key, keylen, peerinfo->hostname); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "Key=%s", + key, NULL); goto out; + } keylen = snprintf(key, sizeof(key), "friend%d.port", count); ret = dict_set_int32n(friends, key, keylen, peerinfo->port); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "Key=%s", + key, NULL); goto out; + } keylen = snprintf(key, sizeof(key), "friend%d.stateId", count); ret = dict_set_int32n(friends, key, keylen, peerinfo->state.state); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Key=%s in dict", key, NULL); goto out; + } keylen = snprintf(key, sizeof(key), "friend%d.state", count); ret = dict_set_strn( friends, key, keylen, glusterd_friend_sm_state_name_get(peerinfo->state.state)); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "key=%s", + key, NULL); goto out; + } keylen = snprintf(key, sizeof(key), "friend%d.connected", count); ret = dict_set_int32n(friends, key, keylen, (int32_t)peerinfo->connected); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, "Key=%s", + key, NULL); goto out; + } snprintf(key, sizeof(key), "friend%d", count); ret = gd_add_peer_hostnames_to_dict(peerinfo, friends, key); @@ -983,9 +1005,9 @@ glusterd_peerinfo_find_by_generation(uint32_t generation) glusterd_conf_t *priv = NULL; glusterd_peerinfo_t *entry = NULL; glusterd_peerinfo_t *found = NULL; - xlator_t *this = NULL; + xlator_t *this = THIS; + glusterd_friend_sm_state_t state; - this = THIS; GF_ASSERT(this); priv = this->private; @@ -996,15 +1018,17 @@ glusterd_peerinfo_find_by_generation(uint32_t generation) cds_list_for_each_entry_rcu(entry, &priv->peers, uuid_list) { if (entry->generation == generation) { - gf_msg_debug(this->name, 0, "Friend found... state: %s", - glusterd_friend_sm_state_name_get(entry->state.state)); found = entry; /* Probably should be rcu_dereferenced */ + state = found->state.state; break; } } RCU_READ_UNLOCK; - if (!found) + if (found) + gf_msg_debug(this->name, 0, "Friend found... state: %s", + glusterd_friend_sm_state_name_get(state)); + else gf_msg_debug(this->name, 0, "Friend with generation: %" PRIu32 ", not found", generation); |
