diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-peer-utils.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-peer-utils.c | 151 |
1 files changed, 94 insertions, 57 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c index 3a145264b79..49fab4cb8b9 100644 --- a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c @@ -12,44 +12,21 @@ #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) +void +glusterd_peerinfo_destroy (struct rcu_head *head) { - int32_t ret = -1; + int32_t ret = -1; + glusterd_peerinfo_t *peerinfo = NULL; glusterd_peer_hostname_t *hostname = NULL; - glusterd_peer_hostname_t *tmp = NULL; + glusterd_peer_hostname_t *tmp = NULL; - if (!peerinfo) - goto out; + /* This works as rcu_head is the first member of gd_rcu_head */ + peerinfo = caa_container_of (head, glusterd_peerinfo_t, head); + + /* Set THIS to the saved this. Needed by some functions below */ + THIS = peerinfo->head.this; - cds_list_del_init (&peerinfo->uuid_list); + CDS_INIT_LIST_HEAD (&peerinfo->uuid_list); ret = glusterd_store_delete_peerinfo (peerinfo); if (ret) { @@ -65,13 +42,44 @@ glusterd_peerinfo_destroy (glusterd_peerinfo_t *peerinfo) } glusterd_sm_tr_log_delete (&peerinfo->sm_log); + pthread_mutex_destroy (&peerinfo->delete_lock); GF_FREE (peerinfo); + peerinfo = NULL; - ret = 0; + return; +} -out: - return ret; +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 (pthread_mutex_trylock (&peerinfo->delete_lock)) { + /* Someone else is already deleting the peer, so give up */ + return 0; + } + + uatomic_set (&peerinfo->deleting, _gf_true); + + if (peerinfo->quorum_contrib != QUORUM_NONE) + quorum_action = _gf_true; + if (peerinfo->rpc) { + peerinfo->rpc = glusterd_rpc_clnt_unref (priv, peerinfo->rpc); + peerinfo->rpc = NULL; + } + + cds_list_del_rcu (&peerinfo->uuid_list); + /* Saving THIS, as it is needed by the callback function */ + peerinfo->head.this = THIS; + call_rcu (&peerinfo->head.head, glusterd_peerinfo_destroy); + + if (quorum_action) + glusterd_do_quorum_action (); + return 0; } /* glusterd_peerinfo_find_by_hostname searches for a peer which matches the @@ -166,6 +174,7 @@ 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; this = THIS; @@ -178,19 +187,23 @@ glusterd_peerinfo_find_by_uuid (uuid_t uuid) if (uuid_is_null (uuid)) return NULL; - cds_list_for_each_entry (entry, &priv->peers, uuid_list) { + rcu_read_lock (); + cds_list_for_each_entry_rcu (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; + found = entry; /* Probably should be rcu_dereferenced */ + break; } } + rcu_read_unlock (); - gf_log (this->name, GF_LOG_DEBUG, "Friend with uuid: %s, not found", - uuid_utoa (uuid)); - return NULL; + if (!found) + gf_log (this->name, GF_LOG_DEBUG, + "Friend with uuid: %s, not found", uuid_utoa (uuid)); + return found; } /* glusterd_peerinfo_find will search for a peer matching either @uuid or @@ -282,6 +295,8 @@ glusterd_peerinfo_new (glusterd_friend_sm_state_t state, uuid_t *uuid, if (new_peer->state.state == GD_FRIEND_STATE_BEFRIENDED) new_peer->quorum_contrib = QUORUM_WAITING; new_peer->port = port; + + pthread_mutex_init (&new_peer->delete_lock, NULL); out: if (ret && new_peer) { glusterd_peerinfo_cleanup (new_peer); @@ -303,7 +318,8 @@ glusterd_chk_peers_connected_befriended (uuid_t skip_uuid) priv= THIS->private; GF_ASSERT (priv); - cds_list_for_each_entry (peerinfo, &priv->peers, uuid_list) { + rcu_read_lock (); + cds_list_for_each_entry_rcu (peerinfo, &priv->peers, uuid_list) { if (!uuid_is_null (skip_uuid) && !uuid_compare (skip_uuid, peerinfo->uuid)) @@ -315,6 +331,8 @@ glusterd_chk_peers_connected_befriended (uuid_t skip_uuid) break; } } + rcu_read_unlock (); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %s", (ret?"TRUE":"FALSE")); return ret; @@ -336,14 +354,16 @@ glusterd_uuid_to_hostname (uuid_t uuid) if (!uuid_compare (MY_UUID, uuid)) { hostname = gf_strdup ("localhost"); } + rcu_read_lock (); if (!cds_list_empty (&priv->peers)) { - cds_list_for_each_entry (entry, &priv->peers, uuid_list) { + cds_list_for_each_entry_rcu (entry, &priv->peers, uuid_list) { if (!uuid_compare (entry->uuid, uuid)) { hostname = gf_strdup (entry->hostname); break; } } } + rcu_read_unlock (); return hostname; } @@ -373,7 +393,8 @@ glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, if (!uuid_compare (brickinfo->uuid, MY_UUID)) continue; - cds_list_for_each_entry (peerinfo, peers, uuid_list) { + rcu_read_lock (); + cds_list_for_each_entry_rcu (peerinfo, peers, uuid_list) { if (uuid_compare (peerinfo->uuid, brickinfo->uuid)) continue; @@ -385,9 +406,11 @@ glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, *down_peerstr = gf_strdup (peerinfo->hostname); gf_log ("", GF_LOG_DEBUG, "Peer %s is down. ", peerinfo->hostname); + rcu_read_unlock (); goto out; } } + rcu_read_unlock (); } ret = _gf_true; @@ -479,7 +502,7 @@ gd_add_address_to_peer (glusterd_peerinfo_t *peerinfo, const char *address) if (ret) goto out; - cds_list_add_tail (&hostname->hostname_list, &peerinfo->hostnames); + cds_list_add_tail_rcu (&hostname->hostname_list, &peerinfo->hostnames); ret = 0; out: @@ -584,6 +607,7 @@ 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; @@ -593,19 +617,24 @@ gd_peerinfo_find_from_hostname (const char *hoststr) GF_VALIDATE_OR_GOTO (this->name, (hoststr != NULL), out); - cds_list_for_each_entry (peer, &priv->peers, uuid_list) { - cds_list_for_each_entry (tmphost, &peer->hostnames, - hostname_list) { + 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_log (this->name, GF_LOG_DEBUG, "Friend %s found.. state: %d", tmphost->hostname, peer->state.state); - return peer; + found = peer; /* Probably needs to be + dereferenced*/ + goto unlock; } } } +unlock: + rcu_read_unlock (); out: - return NULL; + return found; } /* gd_peerinfo_find_from_addrinfo iterates over all the addresses saved for each @@ -624,6 +653,7 @@ 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; @@ -636,9 +666,10 @@ gd_peerinfo_find_from_addrinfo (const struct addrinfo *addr) GF_VALIDATE_OR_GOTO (this->name, (addr != NULL), out); - cds_list_for_each_entry (peer, &conf->peers, uuid_list) { - cds_list_for_each_entry (address, &peer->hostnames, - hostname_list) { + 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 */ @@ -658,14 +689,20 @@ gd_peerinfo_find_from_addrinfo (const struct addrinfo *addr) for (tmp = paddr; tmp != NULL; tmp = tmp->ai_next) { if (gf_compare_sockaddr (addr->ai_addr, tmp->ai_addr)) { - freeaddrinfo (paddr); - return peer; + found = peer; /* (de)referenced? */ + break; } } + + freeaddrinfo (paddr); + if (found) + goto unlock; } } +unlock: + rcu_read_unlock (); out: - return NULL; + return found; } /* gd_update_peerinfo_from_dict will update the hostnames for @peerinfo from |