diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-sm.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-sm.c | 217 |
1 files changed, 156 insertions, 61 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c index a0c25f521..c671edf68 100644 --- a/xlators/mgmt/glusterd/src/glusterd-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-sm.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is GF_FREE software; you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ + Copyright (c) 2006-2012 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 _CONFIG_H #define _CONFIG_H @@ -100,8 +90,7 @@ glusterd_destroy_probe_ctx (glusterd_probe_ctx_t *ctx) if (!ctx) return; - if (ctx->hostname) - GF_FREE (ctx->hostname); + GF_FREE (ctx->hostname); GF_FREE (ctx); } @@ -113,8 +102,7 @@ glusterd_destroy_friend_req_ctx (glusterd_friend_req_ctx_t *ctx) if (ctx->vols) dict_unref (ctx->vols); - if (ctx->hostname) - GF_FREE (ctx->hostname); + GF_FREE (ctx->hostname); GF_FREE (ctx); } @@ -123,8 +111,7 @@ glusterd_destroy_friend_update_ctx (glusterd_friend_update_ctx_t *ctx) { if (!ctx) return; - if (ctx->hostname) - GF_FREE (ctx->hostname); + GF_FREE (ctx->hostname); GF_FREE (ctx); } @@ -168,7 +155,7 @@ glusterd_broadcast_friend_delete (char *hostname, uuid_t uuid) goto out; list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - if (!peerinfo->connected || !peerinfo->mgmt) + if (!peerinfo->connected || !peerinfo->peer) continue; ret = dict_set_static_ptr (friends, "peerinfo", peerinfo); @@ -177,7 +164,7 @@ glusterd_broadcast_friend_delete (char *hostname, uuid_t uuid) goto out; } - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_FRIEND_UPDATE]; + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_UPDATE]; if (proc->fn) { ret = proc->fn (NULL, this, friends); } @@ -257,12 +244,9 @@ glusterd_ac_reverse_probe_begin (glusterd_friend_sm_event_t *event, void *ctx) out: if (ret) { - if (new_event) - GF_FREE (new_event); - if (new_ev_ctx->hostname) - GF_FREE (new_ev_ctx->hostname); - if (new_ev_ctx) - GF_FREE (new_ev_ctx); + GF_FREE (new_event); + GF_FREE (new_ev_ctx->hostname); + GF_FREE (new_ev_ctx); } gf_log ("", GF_LOG_DEBUG, "returning with %d", ret); return ret; @@ -286,9 +270,9 @@ glusterd_ac_friend_add (glusterd_friend_sm_event_t *event, void *ctx) GF_ASSERT (conf); - if (!peerinfo->mgmt) + if (!peerinfo->peer) goto out; - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_FRIEND_ADD]; + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_ADD]; if (proc->fn) { frame = create_frame (this, this->ctx->pool); if (!frame) { @@ -335,9 +319,9 @@ glusterd_ac_friend_probe (glusterd_friend_sm_event_t *event, void *ctx) goto out; } - if (!peerinfo->mgmt) + if (!peerinfo->peer) goto out; - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_PROBE_QUERY]; + proc = &peerinfo->peer->proctable[GLUSTERD_PROBE_QUERY]; if (proc->fn) { frame = create_frame (this, this->ctx->pool); if (!frame) { @@ -415,7 +399,9 @@ glusterd_ac_send_friend_remove_req (glusterd_friend_sm_event_t *event, if (ctx) ret = glusterd_xfer_cli_deprobe_resp (ctx->req, ret, 0, - ctx->hostname); + NULL, + ctx->hostname, + ctx->dict); glusterd_friend_sm (); glusterd_op_sm (); @@ -426,9 +412,9 @@ glusterd_ac_send_friend_remove_req (glusterd_friend_sm_event_t *event, goto out; } - if (!peerinfo->mgmt) + if (!peerinfo->peer) goto out; - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_FRIEND_REMOVE]; + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_REMOVE]; if (proc->fn) { frame = create_frame (this, this->ctx->pool); if (!frame) { @@ -444,22 +430,36 @@ out: return ret; } +static gf_boolean_t +glusterd_should_update_peer (glusterd_peerinfo_t *peerinfo, + glusterd_peerinfo_t *cur_peerinfo) +{ + gf_boolean_t is_valid = _gf_false; + + if ((peerinfo == cur_peerinfo) || + (peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED)) + is_valid = _gf_true; + + return is_valid; +} + static int glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) { - int ret = 0; - glusterd_peerinfo_t *peerinfo = NULL; - rpc_clnt_procedure_t *proc = NULL; - xlator_t *this = NULL; - glusterd_friend_update_ctx_t ev_ctx = {{0}}; - glusterd_conf_t *priv = NULL; - dict_t *friends = NULL; - char key[100] = {0,}; - char *dup_buf = NULL; - int32_t count = 0; + int ret = 0; + glusterd_peerinfo_t *cur_peerinfo = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + rpc_clnt_procedure_t *proc = NULL; + xlator_t *this = NULL; + glusterd_friend_update_ctx_t ev_ctx = {{0}}; + glusterd_conf_t *priv = NULL; + dict_t *friends = NULL; + char key[100] = {0,}; + char *dup_buf = NULL; + int32_t count = 0; GF_ASSERT (event); - peerinfo = event->peerinfo; + cur_peerinfo = event->peerinfo; this = THIS; priv = this->private; @@ -478,6 +478,9 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) goto out; list_for_each_entry (peerinfo, &priv->peers, uuid_list) { + if (!glusterd_should_update_peer (peerinfo, cur_peerinfo)) + continue; + count++; snprintf (key, sizeof (key), "friend%d.uuid", count); dup_buf = gf_strdup (uuid_utoa (peerinfo->uuid)); @@ -488,7 +491,7 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) ret = dict_set_str (friends, key, peerinfo->hostname); if (ret) goto out; - gf_log ("", GF_LOG_NORMAL, "Added uuid: %s, host: %s", + gf_log ("", GF_LOG_INFO, "Added uuid: %s, host: %s", dup_buf, peerinfo->hostname); } @@ -497,7 +500,10 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) goto out; list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - if (!peerinfo->connected || !peerinfo->mgmt) + if (!peerinfo->connected || !peerinfo->peer) + continue; + + if (!glusterd_should_update_peer (peerinfo, cur_peerinfo)) continue; ret = dict_set_static_ptr (friends, "peerinfo", peerinfo); @@ -506,7 +512,7 @@ glusterd_ac_send_friend_update (glusterd_friend_sm_event_t *event, void *ctx) goto out; } - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_FRIEND_UPDATE]; + proc = &peerinfo->peer->proctable[GLUSTERD_FRIEND_UPDATE]; if (proc->fn) { ret = proc->fn (NULL, this, friends); } @@ -521,6 +527,34 @@ out: return ret; } +static int +glusterd_peer_detach_cleanup (glusterd_conf_t *priv) +{ + int ret = -1; + glusterd_volinfo_t *volinfo = NULL; + glusterd_volinfo_t *tmp_volinfo = NULL; + + GF_ASSERT (priv); + + list_for_each_entry_safe (volinfo,tmp_volinfo, + &priv->volumes, vol_list) { + if (!glusterd_friend_contains_vol_bricks (volinfo, + MY_UUID)) { + gf_log (THIS->name, GF_LOG_INFO, + "Deleting stale volume %s", volinfo->volname); + ret = glusterd_delete_volume (volinfo); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Error deleting stale volume"); + goto out; + } + } + } + ret = 0; +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} static int glusterd_ac_handle_friend_remove_req (glusterd_friend_sm_event_t *event, @@ -556,9 +590,14 @@ glusterd_ac_handle_friend_remove_req (glusterd_friend_sm_event_t *event, if (ret) goto out; } - + ret = glusterd_peer_detach_cleanup (priv); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, + "Peer detach cleanup was not successful"); + ret = 0; + } out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } @@ -568,10 +607,13 @@ glusterd_ac_friend_remove (glusterd_friend_sm_event_t *event, void *ctx) { int ret = -1; - ret = glusterd_friend_cleanup (event->peerinfo); + ret = glusterd_friend_remove_cleanup_vols (event->peerinfo->uuid); + if (ret) + gf_log (THIS->name, GF_LOG_WARNING, "Volumes cleanup failed"); + ret = glusterd_friend_cleanup (event->peerinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Cleanup returned: %d", ret); + gf_log (THIS->name, GF_LOG_ERROR, "Cleanup returned: %d", ret); } return 0; @@ -609,15 +651,15 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) uuid_copy (peerinfo->uuid, ev_ctx->uuid); //Build comparison logic here. - ret = glusterd_compare_friend_data (ev_ctx->vols, &status); + ret = glusterd_compare_friend_data (ev_ctx->vols, &status, + peerinfo->hostname); if (ret) goto out; if (GLUSTERD_VOL_COMP_RJT != status) { event_type = GD_FRIEND_EVENT_LOCAL_ACC; op_ret = 0; - } - else { + } else { event_type = GD_FRIEND_EVENT_LOCAL_RJT; op_errno = GF_PROBE_VOLUME_CONFLICT; op_ret = -1; @@ -647,7 +689,8 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) glusterd_friend_sm_inject_event (new_event); ret = glusterd_xfer_friend_add_resp (ev_ctx->req, ev_ctx->hostname, - ev_ctx->port, op_ret, op_errno); + peerinfo->hostname, ev_ctx->port, + op_ret, op_errno); out: gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); @@ -890,7 +933,7 @@ int glusterd_friend_sm_inject_event (glusterd_friend_sm_event_t *event) { GF_ASSERT (event); - gf_log ("glusterd", GF_LOG_DEBUG, "Enqueuing event: '%s'", + gf_log ("glusterd", GF_LOG_DEBUG, "Enqueue event: '%s'", glusterd_friend_sm_event_name_get (event->event)); list_add_tail (&event->list, &gd_friend_sm_queue); @@ -919,6 +962,27 @@ glusterd_destroy_friend_event_context (glusterd_friend_sm_event_t *event) } } +gf_boolean_t +gd_does_peer_affect_quorum (glusterd_friend_sm_state_t old_state, + glusterd_friend_sm_event_type_t event_type, + glusterd_peerinfo_t *peerinfo) +{ + gf_boolean_t affects = _gf_false; + + //When glusterd comes up with friends in BEFRIENDED state in store, + //wait until compare-data happens. + if ((old_state == GD_FRIEND_STATE_BEFRIENDED) && + (event_type != GD_FRIEND_EVENT_RCVD_ACC) && + (event_type != GD_FRIEND_EVENT_LOCAL_ACC)) + goto out; + if ((peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED) + && peerinfo->connected) { + affects = _gf_true; + } +out: + return affects; +} + int glusterd_friend_sm () { @@ -930,6 +994,8 @@ glusterd_friend_sm () glusterd_peerinfo_t *peerinfo = NULL; glusterd_friend_sm_event_type_t event_type = 0; gf_boolean_t is_await_conn = _gf_false; + gf_boolean_t quorum_action = _gf_false; + glusterd_friend_sm_state_t old_state = GD_FRIEND_STATE_DEFAULT; while (!list_empty (&gd_friend_sm_queue)) { list_for_each_entry_safe (event, tmp, &gd_friend_sm_queue, list) { @@ -949,6 +1015,7 @@ glusterd_friend_sm () glusterd_friend_sm_event_name_get (event_type)); + old_state = peerinfo->state.state; state = glusterd_friend_state_table[peerinfo->state.state]; GF_ASSERT (state); @@ -989,6 +1056,15 @@ glusterd_friend_sm () goto out; } + if (gd_does_peer_affect_quorum (old_state, event_type, + peerinfo)) { + peerinfo->quorum_contrib = QUORUM_UP; + if (peerinfo->quorum_action) { + peerinfo->quorum_action = _gf_false; + quorum_action = _gf_true; + } + } + ret = glusterd_store_peerinfo (peerinfo); glusterd_destroy_friend_event_context (event); @@ -1002,6 +1078,25 @@ glusterd_friend_sm () ret = 0; out: + if (quorum_action) { + /* When glusterd is restarted, it needs to wait until the 'friends' view + * of the volumes settle, before it starts any of the internal daemons. + * + * Every friend that was part of the cluster, would send its + * cluster-view, 'our' way. For every friend, who belongs to + * a partition which has a different cluster-view from our + * partition, we may update our cluster-view. For subsequent + * friends from that partition would agree with us, if the first + * friend wasn't rejected. For every first friend, whom we agreed with, + * we would need to start internal daemons/bricks belonging to the + * new volumes. + * glusterd_spawn_daemons calls functions that are idempotent. ie, + * the functions spawn process(es) only if they are not started yet. + * + * */ + glusterd_spawn_daemons (NULL); + glusterd_do_quorum_action (); + } return ret; } |
