diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-sm.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-sm.c | 158 |
1 files changed, 125 insertions, 33 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c index 72af8c05b..7a8b2c94f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-sm.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU 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 - General Public License for more details. - - You should have received a copy of the GNU 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 @@ -44,6 +34,7 @@ #include "glusterd-op-sm.h" #include "glusterd-utils.h" #include "glusterd-store.h" +#include "glusterd-etcd.h" static struct list_head gd_friend_sm_queue; @@ -100,8 +91,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 +103,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 +112,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); } @@ -257,12 +245,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; @@ -415,7 +400,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 (); @@ -541,6 +528,9 @@ out: return ret; } +/* Clean up stale volumes on the peer being detached. The volumes which have + * bricks on other peers are stale with respect to the detached peer. + */ static int glusterd_peer_detach_cleanup (glusterd_conf_t *priv) { @@ -552,8 +542,14 @@ glusterd_peer_detach_cleanup (glusterd_conf_t *priv) list_for_each_entry_safe (volinfo,tmp_volinfo, &priv->volumes, vol_list) { + /* The peer detach checks make sure that, at this point in the + * detach process, there are only volumes contained completely + * within or completely outside the detached peer. + * The only stale volumes at this point are the ones + * completely outside the peer and can be safely deleted. + */ if (!glusterd_friend_contains_vol_bricks (volinfo, - priv->uuid)) { + MY_UUID)) { gf_log (THIS->name, GF_LOG_INFO, "Deleting stale volume %s", volinfo->volname); ret = glusterd_delete_volume (volinfo); @@ -610,6 +606,9 @@ glusterd_ac_handle_friend_remove_req (glusterd_friend_sm_event_t *event, "Peer detach cleanup was not successful"); ret = 0; } + gf_log (THIS->name, GF_LOG_INFO, "detached, stopping etcd"); + stop_etcd(priv->etcd_pid); + nuke_etcd_dir(); out: gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); @@ -653,10 +652,14 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) glusterd_friend_update_ctx_t *new_ev_ctx = NULL; glusterd_friend_sm_event_t *new_event = NULL; glusterd_friend_sm_event_type_t event_type = GD_FRIEND_EVENT_NONE; + glusterd_conf_t *conf = NULL; int status = 0; int32_t op_ret = -1; int32_t op_errno = 0; + xlator_t *this = NULL; + this = THIS; + GF_ASSERT (this); GF_ASSERT (ctx); ev_ctx = ctx; uuid_copy (uuid, ev_ctx->uuid); @@ -664,8 +667,12 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) GF_ASSERT (peerinfo); uuid_copy (peerinfo->uuid, ev_ctx->uuid); + conf = this->private; + GF_ASSERT (conf); + //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; @@ -678,6 +685,31 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) op_ret = -1; } + /* Compare missed_snapshot list with the peer * + * if volume comparison is successful */ + if ((op_ret == 0) && + (conf->op_version >= GD_OP_VERSION_4)) { + ret = glusterd_import_friend_missed_snap_list (ev_ctx->vols); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to import peer's " + "missed_snaps_list."); + event_type = GD_FRIEND_EVENT_LOCAL_RJT; + op_errno = GF_PROBE_MISSED_SNAP_CONFLICT; + op_ret = -1; + } + + ret = glusterd_compare_friend_snapshots (ev_ctx->vols, + peerinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Conflict in comparing peer's snapshots"); + event_type = GD_FRIEND_EVENT_LOCAL_RJT; + op_errno = GF_PROBE_SNAP_CONFLICT; + op_ret = -1; + } + } + ret = glusterd_friend_sm_new_event (event_type, &new_event); if (ret) { @@ -702,7 +734,15 @@ 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); + + // apply a deterministic function to decide via whom we should join the cluster + if (strcmp(peerinfo->hostname, ev_ctx->hostname) > 0) { + stop_etcd(conf->etcd_pid); + nuke_etcd_dir(); + conf->etcd_pid = start_etcd (uuid_utoa(MY_UUID), peerinfo->hostname); + } out: gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); @@ -974,6 +1014,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 () { @@ -985,6 +1046,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) { @@ -1004,6 +1067,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); @@ -1044,6 +1108,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); @@ -1057,6 +1130,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; } |
