glusterd: group server-quorum related code together
Server-quorum implementation was spread in many files. This patch brings them all together into a single file, namely glusterd-server-quorum.c. All exported functions are available via glusterd-server-quorum.h Change-Id: I8fd77114b5bc6b05127cb8a6a641e0295f0be7bb BUG: 1205592 Signed-off-by: Krishnan Parthasarathi <kparthas@redhat.com> Reviewed-on: http://review.gluster.org/9492 Reviewed-by: Atin Mukherjee <amukherj@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Kaushal M <kaushal@redhat.com>
This commit is contained in:
parent
2b949eb89e
commit
4b18fba406
@ -16,7 +16,7 @@ glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \
|
||||
glusterd-proc-mgmt.c glusterd-svc-mgmt.c glusterd-shd-svc.c \
|
||||
glusterd-nfs-svc.c glusterd-quotad-svc.c glusterd-svc-helper.c \
|
||||
glusterd-conn-helper.c glusterd-snapd-svc.c glusterd-snapd-svc-helper.c \
|
||||
glusterd-bitd-svc.c glusterd-scrub-svc.c
|
||||
glusterd-bitd-svc.c glusterd-scrub-svc.c glusterd-server-quorum.c
|
||||
|
||||
|
||||
glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \
|
||||
@ -37,7 +37,8 @@ noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h \
|
||||
glusterd-svc-mgmt.h glusterd-shd-svc.h glusterd-nfs-svc.h \
|
||||
glusterd-quotad-svc.h glusterd-svc-helper.h glusterd-snapd-svc.h \
|
||||
glusterd-snapd-svc-helper.h glusterd-rcu.h glusterd-bitd-svc.h \
|
||||
glusterd-scrub-svc.h $(CONTRIBDIR)/userspace-rcu/rculist-extra.h
|
||||
glusterd-scrub-svc.h $(CONTRIBDIR)/userspace-rcu/rculist-extra.h \
|
||||
glusterd-server-quorum.h
|
||||
|
||||
AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \
|
||||
-I$(rpclibdir) -I$(CONTRIBDIR)/rbtree \
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "glusterd-sm.h"
|
||||
#include "glusterd-op-sm.h"
|
||||
#include "glusterd-utils.h"
|
||||
#include "glusterd-server-quorum.h"
|
||||
#include "glusterd-store.h"
|
||||
#include "glusterd-locks.h"
|
||||
#include "glusterd-snapshot-utils.h"
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "glusterd-shd-svc.h"
|
||||
#include "glusterd-nfs-svc.h"
|
||||
#include "glusterd-quotad-svc.h"
|
||||
#include "glusterd-server-quorum.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "glusterd-peer-utils.h"
|
||||
#include "glusterd-store.h"
|
||||
#include "glusterd-server-quorum.h"
|
||||
#include "common-utils.h"
|
||||
|
||||
void
|
||||
|
423
xlators/mgmt/glusterd/src/glusterd-server-quorum.c
Normal file
423
xlators/mgmt/glusterd/src/glusterd-server-quorum.c
Normal file
@ -0,0 +1,423 @@
|
||||
/*
|
||||
Copyright (c) 2015 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
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "common-utils.h"
|
||||
#include "glusterd.h"
|
||||
#include "glusterd-utils.h"
|
||||
#include "glusterd-messages.h"
|
||||
#include "glusterd-server-quorum.h"
|
||||
#include "glusterd-syncop.h"
|
||||
#include "glusterd-op-sm.h"
|
||||
|
||||
#define CEILING_POS(X) (((X)-(int)(X)) > 0 ? (int)((X)+1) : (int)(X))
|
||||
|
||||
static gf_boolean_t
|
||||
glusterd_is_get_op (xlator_t *this, glusterd_op_t op, dict_t *dict)
|
||||
{
|
||||
char *key = NULL;
|
||||
char *volname = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (op == GD_OP_STATUS_VOLUME)
|
||||
return _gf_true;
|
||||
|
||||
if (op == GD_OP_SET_VOLUME) {
|
||||
/*check for set volume help*/
|
||||
ret = dict_get_str (dict, "volname", &volname);
|
||||
if (volname &&
|
||||
((strcmp (volname, "help") == 0) ||
|
||||
(strcmp (volname, "help-xml") == 0))) {
|
||||
ret = dict_get_str (dict, "key1", &key);
|
||||
if (ret < 0)
|
||||
return _gf_true;
|
||||
}
|
||||
}
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_validation_required (xlator_t *this, glusterd_op_t op,
|
||||
dict_t *dict)
|
||||
{
|
||||
gf_boolean_t required = _gf_true;
|
||||
char *key = NULL;
|
||||
char *key_fixed = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (glusterd_is_get_op (this, op, dict)) {
|
||||
required = _gf_false;
|
||||
goto out;
|
||||
}
|
||||
if ((op != GD_OP_SET_VOLUME) && (op != GD_OP_RESET_VOLUME))
|
||||
goto out;
|
||||
if (op == GD_OP_SET_VOLUME)
|
||||
ret = dict_get_str (dict, "key1", &key);
|
||||
else if (op == GD_OP_RESET_VOLUME)
|
||||
ret = dict_get_str (dict, "key", &key);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = glusterd_check_option_exists (key, &key_fixed);
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
if (key_fixed)
|
||||
key = key_fixed;
|
||||
if (glusterd_is_quorum_option (key))
|
||||
required = _gf_false;
|
||||
out:
|
||||
GF_FREE (key_fixed);
|
||||
return required;
|
||||
}
|
||||
|
||||
/* This function should not be used when the quorum validation needs to happen
|
||||
* on non-global peer list */
|
||||
int
|
||||
glusterd_validate_quorum (xlator_t *this, glusterd_op_t op,
|
||||
dict_t *dict, char **op_errstr)
|
||||
{
|
||||
int ret = 0;
|
||||
char *volname = NULL;
|
||||
glusterd_volinfo_t *volinfo = NULL;
|
||||
char *errstr = NULL;
|
||||
|
||||
errstr = "Quorum not met. Volume operation not allowed.";
|
||||
if (!glusterd_is_quorum_validation_required (this, op, dict))
|
||||
goto out;
|
||||
|
||||
ret = dict_get_str (dict, "volname", &volname);
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = glusterd_volinfo_find (volname, &volinfo);
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Passing NULL implies quorum calculation will happen on global peer
|
||||
* list */
|
||||
if (does_gd_meet_server_quorum (this, NULL, _gf_false)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (glusterd_is_volume_in_server_quorum (volinfo)) {
|
||||
ret = -1;
|
||||
*op_errstr = gf_strdup (errstr);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_option (char *option)
|
||||
{
|
||||
gf_boolean_t res = _gf_false;
|
||||
int i = 0;
|
||||
char *keys[] = {GLUSTERD_QUORUM_TYPE_KEY,
|
||||
GLUSTERD_QUORUM_RATIO_KEY, NULL};
|
||||
|
||||
for (i = 0; keys[i]; i++) {
|
||||
if (strcmp (option, keys[i]) == 0) {
|
||||
res = _gf_true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_changed (dict_t *options, char *option, char *value)
|
||||
{
|
||||
int ret = 0;
|
||||
gf_boolean_t reconfigured = _gf_false;
|
||||
gf_boolean_t all = _gf_false;
|
||||
char *oldquorum = NULL;
|
||||
char *newquorum = NULL;
|
||||
char *oldratio = NULL;
|
||||
char *newratio = NULL;
|
||||
|
||||
if ((strcmp ("all", option) != 0) &&
|
||||
!glusterd_is_quorum_option (option))
|
||||
goto out;
|
||||
|
||||
if (strcmp ("all", option) == 0)
|
||||
all = _gf_true;
|
||||
|
||||
if (all || (strcmp (GLUSTERD_QUORUM_TYPE_KEY, option) == 0)) {
|
||||
newquorum = value;
|
||||
ret = dict_get_str (options, GLUSTERD_QUORUM_TYPE_KEY,
|
||||
&oldquorum);
|
||||
}
|
||||
|
||||
if (all || (strcmp (GLUSTERD_QUORUM_RATIO_KEY, option) == 0)) {
|
||||
newratio = value;
|
||||
ret = dict_get_str (options, GLUSTERD_QUORUM_RATIO_KEY,
|
||||
&oldratio);
|
||||
}
|
||||
|
||||
reconfigured = _gf_true;
|
||||
|
||||
if (oldquorum && newquorum && (strcmp (oldquorum, newquorum) == 0))
|
||||
reconfigured = _gf_false;
|
||||
if (oldratio && newratio && (strcmp (oldratio, newratio) == 0))
|
||||
reconfigured = _gf_false;
|
||||
|
||||
if ((oldratio == NULL) && (newratio == NULL) && (oldquorum == NULL) &&
|
||||
(newquorum == NULL))
|
||||
reconfigured = _gf_false;
|
||||
out:
|
||||
return reconfigured;
|
||||
}
|
||||
|
||||
static inline gf_boolean_t
|
||||
_is_contributing_to_quorum (gd_quorum_contrib_t contrib)
|
||||
{
|
||||
if ((contrib == QUORUM_UP) || (contrib == QUORUM_DOWN))
|
||||
return _gf_true;
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
static inline gf_boolean_t
|
||||
_does_quorum_meet (int active_count, int quorum_count)
|
||||
{
|
||||
return (active_count >= quorum_count);
|
||||
}
|
||||
|
||||
int
|
||||
glusterd_get_quorum_cluster_counts (xlator_t *this, int *active_count,
|
||||
int *quorum_count,
|
||||
struct list_head *peer_list,
|
||||
gf_boolean_t _local_xaction_peers)
|
||||
{
|
||||
glusterd_peerinfo_t *peerinfo = NULL;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
int ret = -1;
|
||||
int inquorum_count = 0;
|
||||
char *val = NULL;
|
||||
double quorum_percentage = 0.0;
|
||||
gf_boolean_t ratio = _gf_false;
|
||||
int count = 0;
|
||||
|
||||
conf = this->private;
|
||||
|
||||
/* Start with counting self */
|
||||
inquorum_count = 1;
|
||||
if (active_count)
|
||||
*active_count = 1;
|
||||
|
||||
if (!peer_list) {
|
||||
list_for_each_entry (peerinfo, &conf->peers, uuid_list) {
|
||||
glusterd_quorum_count(peerinfo, inquorum_count,
|
||||
active_count, out);
|
||||
}
|
||||
} else {
|
||||
if (_local_xaction_peers) {
|
||||
list_for_each_local_xaction_peers (peerinfo,
|
||||
peer_list) {
|
||||
glusterd_quorum_count(peerinfo, inquorum_count,
|
||||
active_count, out);
|
||||
}
|
||||
} else {
|
||||
list_for_each_entry (peerinfo, peer_list,
|
||||
op_peers_list) {
|
||||
glusterd_quorum_count(peerinfo, inquorum_count,
|
||||
active_count, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = dict_get_str (conf->opts, GLUSTERD_QUORUM_RATIO_KEY, &val);
|
||||
if (ret == 0) {
|
||||
ratio = _gf_true;
|
||||
ret = gf_string2percent (val, &quorum_percentage);
|
||||
if (!ret)
|
||||
ratio = _gf_true;
|
||||
}
|
||||
if (ratio)
|
||||
count = CEILING_POS (inquorum_count *
|
||||
quorum_percentage / 100.0);
|
||||
else
|
||||
count = (inquorum_count * 50 / 100) + 1;
|
||||
|
||||
*quorum_count = count;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_volume_in_server_quorum (glusterd_volinfo_t *volinfo)
|
||||
{
|
||||
gf_boolean_t res = _gf_false;
|
||||
char *quorum_type = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ret = dict_get_str (volinfo->dict, GLUSTERD_QUORUM_TYPE_KEY,
|
||||
&quorum_type);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (strcmp (quorum_type, GLUSTERD_SERVER_QUORUM) == 0)
|
||||
res = _gf_true;
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_any_volume_in_server_quorum (xlator_t *this)
|
||||
{
|
||||
glusterd_conf_t *conf = NULL;
|
||||
glusterd_volinfo_t *volinfo = NULL;
|
||||
|
||||
conf = this->private;
|
||||
list_for_each_entry (volinfo, &conf->volumes, vol_list) {
|
||||
if (glusterd_is_volume_in_server_quorum (volinfo)) {
|
||||
return _gf_true;
|
||||
}
|
||||
}
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
does_gd_meet_server_quorum (xlator_t *this, struct list_head *peers_list,
|
||||
gf_boolean_t _local_xaction_peers)
|
||||
{
|
||||
int quorum_count = 0;
|
||||
int active_count = 0;
|
||||
gf_boolean_t in = _gf_false;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
int ret = -1;
|
||||
|
||||
conf = this->private;
|
||||
ret = glusterd_get_quorum_cluster_counts (this, &active_count,
|
||||
&quorum_count,
|
||||
peers_list,
|
||||
_local_xaction_peers);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!_does_quorum_meet (active_count, quorum_count)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
in = _gf_true;
|
||||
out:
|
||||
return in;
|
||||
}
|
||||
|
||||
void
|
||||
glusterd_do_volume_quorum_action (xlator_t *this, glusterd_volinfo_t *volinfo,
|
||||
gf_boolean_t meets_quorum)
|
||||
{
|
||||
glusterd_brickinfo_t *brickinfo = NULL;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
gd_quorum_status_t quorum_status = NOT_APPLICABLE_QUORUM;
|
||||
gf_boolean_t follows_quorum = _gf_false;
|
||||
|
||||
conf = this->private;
|
||||
if (volinfo->status != GLUSTERD_STATUS_STARTED) {
|
||||
volinfo->quorum_status = NOT_APPLICABLE_QUORUM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
follows_quorum = glusterd_is_volume_in_server_quorum (volinfo);
|
||||
if (follows_quorum) {
|
||||
if (meets_quorum)
|
||||
quorum_status = MEETS_QUORUM;
|
||||
else
|
||||
quorum_status = DOESNT_MEET_QUORUM;
|
||||
} else {
|
||||
quorum_status = NOT_APPLICABLE_QUORUM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following check is added to prevent spurious brick starts when
|
||||
* events occur that affect quorum.
|
||||
* Example:
|
||||
* There is a cluster of 10 peers. Volume is in quorum. User
|
||||
* takes down one brick from the volume to perform maintenance.
|
||||
* Suddenly one of the peers go down. Cluster is still in quorum. But
|
||||
* because of this 'peer going down' event, quorum is calculated and
|
||||
* the bricks that are down are brought up again. In this process it
|
||||
* also brings up the brick that is purposefully taken down.
|
||||
*/
|
||||
if (volinfo->quorum_status == quorum_status)
|
||||
goto out;
|
||||
|
||||
if (quorum_status == MEETS_QUORUM) {
|
||||
gf_msg (this->name, GF_LOG_CRITICAL, 0,
|
||||
GD_MSG_SERVER_QUORUM_MET_STARTING_BRICKS,
|
||||
"Server quorum regained for volume %s. Starting local "
|
||||
"bricks.", volinfo->volname);
|
||||
} else if (quorum_status == DOESNT_MEET_QUORUM) {
|
||||
gf_msg (this->name, GF_LOG_CRITICAL, 0,
|
||||
GD_MSG_SERVER_QUORUM_LOST_STOPPING_BRICKS,
|
||||
"Server quorum lost for volume %s. Stopping local "
|
||||
"bricks.", volinfo->volname);
|
||||
}
|
||||
|
||||
list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
|
||||
if (!glusterd_is_local_brick (this, volinfo, brickinfo))
|
||||
continue;
|
||||
if (quorum_status == DOESNT_MEET_QUORUM)
|
||||
glusterd_brick_stop (volinfo, brickinfo, _gf_false);
|
||||
else
|
||||
glusterd_brick_start (volinfo, brickinfo, _gf_false);
|
||||
}
|
||||
volinfo->quorum_status = quorum_status;
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
glusterd_do_quorum_action ()
|
||||
{
|
||||
xlator_t *this = NULL;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
glusterd_volinfo_t *volinfo = NULL;
|
||||
int ret = 0;
|
||||
int active_count = 0;
|
||||
int quorum_count = 0;
|
||||
gf_boolean_t meets = _gf_false;
|
||||
|
||||
this = THIS;
|
||||
conf = this->private;
|
||||
|
||||
conf->pending_quorum_action = _gf_true;
|
||||
ret = glusterd_lock (conf->uuid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
{
|
||||
ret = glusterd_get_quorum_cluster_counts (this, &active_count,
|
||||
&quorum_count, NULL,
|
||||
_gf_false);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
if (_does_quorum_meet (active_count, quorum_count))
|
||||
meets = _gf_true;
|
||||
list_for_each_entry (volinfo, &conf->volumes, vol_list) {
|
||||
glusterd_do_volume_quorum_action (this, volinfo, meets);
|
||||
}
|
||||
}
|
||||
unlock:
|
||||
(void)glusterd_unlock (conf->uuid);
|
||||
conf->pending_quorum_action = _gf_false;
|
||||
out:
|
||||
return ret;
|
||||
}
|
59
xlators/mgmt/glusterd/src/glusterd-server-quorum.h
Normal file
59
xlators/mgmt/glusterd/src/glusterd-server-quorum.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright (c) 2015 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_SERVER_QUORUM_H
|
||||
#define _GLUSTERD_SERVER_QUORUM_H
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define glusterd_quorum_count(peerinfo, inquorum_count,\
|
||||
active_count, _exit)\
|
||||
do {\
|
||||
if (peerinfo->quorum_contrib == QUORUM_WAITING)\
|
||||
goto _exit;\
|
||||
if (_is_contributing_to_quorum (peerinfo->quorum_contrib))\
|
||||
inquorum_count = inquorum_count + 1;\
|
||||
if (active_count && (peerinfo->quorum_contrib == QUORUM_UP))\
|
||||
*active_count = *active_count + 1;\
|
||||
} while (0)
|
||||
|
||||
|
||||
int
|
||||
glusterd_validate_quorum (xlator_t *this, glusterd_op_t op, dict_t *dict,
|
||||
char **op_errstr);
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_changed (dict_t *options, char *option, char *value);
|
||||
|
||||
int
|
||||
glusterd_do_quorum_action ();
|
||||
|
||||
int
|
||||
glusterd_get_quorum_cluster_counts (xlator_t *this, int *active_count,
|
||||
int *quorum_count,
|
||||
struct list_head *peer_list,
|
||||
gf_boolean_t _local__xaction_peers);
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_option (char *option);
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_volume_in_server_quorum (glusterd_volinfo_t *volinfo);
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_any_volume_in_server_quorum (xlator_t *this);
|
||||
|
||||
gf_boolean_t
|
||||
does_gd_meet_server_quorum (xlator_t *this,
|
||||
struct list_head *peers_list,
|
||||
gf_boolean_t _local__xaction_peers);
|
||||
#endif /* _GLUSTERD_SERVER_QUORUM_H */
|
@ -36,6 +36,7 @@
|
||||
#include "glusterd-utils.h"
|
||||
#include "glusterd-store.h"
|
||||
#include "glusterd-snapshot-utils.h"
|
||||
#include "glusterd-server-quorum.h"
|
||||
|
||||
static struct cds_list_head gd_friend_sm_queue;
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "glusterd-svc-helper.h"
|
||||
#include "glusterd-snapd-svc-helper.h"
|
||||
#include "glusterd-snapshot-utils.h"
|
||||
#include "glusterd-server-quorum.h"
|
||||
|
||||
/*
|
||||
* glusterd_snap_geo_rep_restore:
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "glusterd.h"
|
||||
#include "glusterd-op-sm.h"
|
||||
#include "glusterd-utils.h"
|
||||
#include "glusterd-server-quorum.h"
|
||||
#include "glusterd-locks.h"
|
||||
#include "glusterd-snapshot-utils.h"
|
||||
#include "glusterd-messages.h"
|
||||
|
@ -93,8 +93,6 @@
|
||||
#define NLMV4_VERSION 4
|
||||
#define NLMV1_VERSION 1
|
||||
|
||||
#define CEILING_POS(X) (((X)-(int)(X)) > 0 ? (int)((X)+1) : (int)(X))
|
||||
|
||||
extern struct volopt_map_entry glusterd_volopt_map[];
|
||||
|
||||
static glusterd_lock_t lock;
|
||||
@ -1106,106 +1104,6 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_get_op (xlator_t *this, glusterd_op_t op, dict_t *dict)
|
||||
{
|
||||
char *key = NULL;
|
||||
char *volname = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (op == GD_OP_STATUS_VOLUME)
|
||||
return _gf_true;
|
||||
|
||||
if (op == GD_OP_SET_VOLUME) {
|
||||
/*check for set volume help*/
|
||||
ret = dict_get_str (dict, "volname", &volname);
|
||||
if (volname &&
|
||||
((strcmp (volname, "help") == 0) ||
|
||||
(strcmp (volname, "help-xml") == 0))) {
|
||||
ret = dict_get_str (dict, "key1", &key);
|
||||
if (ret < 0)
|
||||
return _gf_true;
|
||||
}
|
||||
}
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_validation_required (xlator_t *this, glusterd_op_t op,
|
||||
dict_t *dict)
|
||||
{
|
||||
gf_boolean_t required = _gf_true;
|
||||
char *key = NULL;
|
||||
char *key_fixed = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (glusterd_is_get_op (this, op, dict)) {
|
||||
required = _gf_false;
|
||||
goto out;
|
||||
}
|
||||
if ((op != GD_OP_SET_VOLUME) && (op != GD_OP_RESET_VOLUME))
|
||||
goto out;
|
||||
if (op == GD_OP_SET_VOLUME)
|
||||
ret = dict_get_str (dict, "key1", &key);
|
||||
else if (op == GD_OP_RESET_VOLUME)
|
||||
ret = dict_get_str (dict, "key", &key);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = glusterd_check_option_exists (key, &key_fixed);
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
if (key_fixed)
|
||||
key = key_fixed;
|
||||
if (glusterd_is_quorum_option (key))
|
||||
required = _gf_false;
|
||||
out:
|
||||
GF_FREE (key_fixed);
|
||||
return required;
|
||||
}
|
||||
|
||||
/* This function should not be used when the quorum validation needs to happen
|
||||
* on non-global peer list */
|
||||
int
|
||||
glusterd_validate_quorum (xlator_t *this, glusterd_op_t op,
|
||||
dict_t *dict, char **op_errstr)
|
||||
{
|
||||
int ret = 0;
|
||||
char *volname = NULL;
|
||||
glusterd_volinfo_t *volinfo = NULL;
|
||||
char *errstr = NULL;
|
||||
|
||||
errstr = "Quorum not met. Volume operation not allowed.";
|
||||
if (!glusterd_is_quorum_validation_required (this, op, dict))
|
||||
goto out;
|
||||
|
||||
ret = dict_get_str (dict, "volname", &volname);
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = glusterd_volinfo_find (volname, &volinfo);
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Passing NULL implies quorum calculation will happen on global peer
|
||||
* list */
|
||||
if (does_gd_meet_server_quorum (this, NULL, _gf_false)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (glusterd_is_volume_in_server_quorum (volinfo)) {
|
||||
ret = -1;
|
||||
*op_errstr = gf_strdup (errstr);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
glusterd_validate_and_create_brickpath (glusterd_brickinfo_t *brickinfo,
|
||||
@ -2823,205 +2721,6 @@ out:
|
||||
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_option (char *option)
|
||||
{
|
||||
gf_boolean_t res = _gf_false;
|
||||
int i = 0;
|
||||
char *keys[] = {GLUSTERD_QUORUM_TYPE_KEY,
|
||||
GLUSTERD_QUORUM_RATIO_KEY, NULL};
|
||||
|
||||
for (i = 0; keys[i]; i++) {
|
||||
if (strcmp (option, keys[i]) == 0) {
|
||||
res = _gf_true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_changed (dict_t *options, char *option, char *value)
|
||||
{
|
||||
int ret = 0;
|
||||
gf_boolean_t reconfigured = _gf_false;
|
||||
gf_boolean_t all = _gf_false;
|
||||
char *oldquorum = NULL;
|
||||
char *newquorum = NULL;
|
||||
char *oldratio = NULL;
|
||||
char *newratio = NULL;
|
||||
|
||||
if ((strcmp ("all", option) != 0) &&
|
||||
!glusterd_is_quorum_option (option))
|
||||
goto out;
|
||||
|
||||
if (strcmp ("all", option) == 0)
|
||||
all = _gf_true;
|
||||
|
||||
if (all || (strcmp (GLUSTERD_QUORUM_TYPE_KEY, option) == 0)) {
|
||||
newquorum = value;
|
||||
ret = dict_get_str (options, GLUSTERD_QUORUM_TYPE_KEY,
|
||||
&oldquorum);
|
||||
}
|
||||
|
||||
if (all || (strcmp (GLUSTERD_QUORUM_RATIO_KEY, option) == 0)) {
|
||||
newratio = value;
|
||||
ret = dict_get_str (options, GLUSTERD_QUORUM_RATIO_KEY,
|
||||
&oldratio);
|
||||
}
|
||||
|
||||
reconfigured = _gf_true;
|
||||
|
||||
if (oldquorum && newquorum && (strcmp (oldquorum, newquorum) == 0))
|
||||
reconfigured = _gf_false;
|
||||
if (oldratio && newratio && (strcmp (oldratio, newratio) == 0))
|
||||
reconfigured = _gf_false;
|
||||
|
||||
if ((oldratio == NULL) && (newratio == NULL) && (oldquorum == NULL) &&
|
||||
(newquorum == NULL))
|
||||
reconfigured = _gf_false;
|
||||
out:
|
||||
return reconfigured;
|
||||
}
|
||||
|
||||
static inline gf_boolean_t
|
||||
_is_contributing_to_quorum (gd_quorum_contrib_t contrib)
|
||||
{
|
||||
if ((contrib == QUORUM_UP) || (contrib == QUORUM_DOWN))
|
||||
return _gf_true;
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
static inline gf_boolean_t
|
||||
_does_quorum_meet (int active_count, int quorum_count)
|
||||
{
|
||||
return (active_count >= quorum_count);
|
||||
}
|
||||
|
||||
int
|
||||
glusterd_get_quorum_cluster_counts (xlator_t *this, int *active_count,
|
||||
int *quorum_count,
|
||||
struct cds_list_head *peer_list,
|
||||
gf_boolean_t _local_xaction_peers)
|
||||
{
|
||||
glusterd_peerinfo_t *peerinfo = NULL;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
int ret = -1;
|
||||
int inquorum_count = 0;
|
||||
char *val = NULL;
|
||||
double quorum_percentage = 0.0;
|
||||
gf_boolean_t ratio = _gf_false;
|
||||
int count = 0;
|
||||
|
||||
conf = this->private;
|
||||
|
||||
//Start with counting self
|
||||
inquorum_count = 1;
|
||||
if (active_count)
|
||||
*active_count = 1;
|
||||
|
||||
rcu_read_lock ();
|
||||
if (!peer_list) {
|
||||
cds_list_for_each_entry_rcu (peerinfo, &conf->peers,
|
||||
uuid_list) {
|
||||
GLUSTERD_QUORUM_COUNT(peerinfo, inquorum_count,
|
||||
active_count, out);
|
||||
}
|
||||
} else {
|
||||
if (_local_xaction_peers) {
|
||||
list_for_each_local_xaction_peers (peerinfo,
|
||||
peer_list) {
|
||||
GLUSTERD_QUORUM_COUNT(peerinfo, inquorum_count,
|
||||
active_count, out);
|
||||
}
|
||||
} else {
|
||||
cds_list_for_each_entry (peerinfo, peer_list,
|
||||
op_peers_list) {
|
||||
GLUSTERD_QUORUM_COUNT(peerinfo, inquorum_count,
|
||||
active_count, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = dict_get_str (conf->opts, GLUSTERD_QUORUM_RATIO_KEY, &val);
|
||||
if (ret == 0) {
|
||||
ratio = _gf_true;
|
||||
ret = gf_string2percent (val, &quorum_percentage);
|
||||
if (!ret)
|
||||
ratio = _gf_true;
|
||||
}
|
||||
if (ratio)
|
||||
count = CEILING_POS (inquorum_count *
|
||||
quorum_percentage / 100.0);
|
||||
else
|
||||
count = (inquorum_count * 50 / 100) + 1;
|
||||
|
||||
*quorum_count = count;
|
||||
ret = 0;
|
||||
out:
|
||||
rcu_read_unlock ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_volume_in_server_quorum (glusterd_volinfo_t *volinfo)
|
||||
{
|
||||
gf_boolean_t res = _gf_false;
|
||||
char *quorum_type = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ret = dict_get_str (volinfo->dict, GLUSTERD_QUORUM_TYPE_KEY,
|
||||
&quorum_type);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (strcmp (quorum_type, GLUSTERD_SERVER_QUORUM) == 0)
|
||||
res = _gf_true;
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_any_volume_in_server_quorum (xlator_t *this)
|
||||
{
|
||||
glusterd_conf_t *conf = NULL;
|
||||
glusterd_volinfo_t *volinfo = NULL;
|
||||
|
||||
conf = this->private;
|
||||
cds_list_for_each_entry (volinfo, &conf->volumes, vol_list) {
|
||||
if (glusterd_is_volume_in_server_quorum (volinfo)) {
|
||||
return _gf_true;
|
||||
}
|
||||
}
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
gf_boolean_t
|
||||
does_gd_meet_server_quorum (xlator_t *this, struct cds_list_head *peers_list,
|
||||
gf_boolean_t _local_xaction_peers)
|
||||
{
|
||||
int quorum_count = 0;
|
||||
int active_count = 0;
|
||||
gf_boolean_t in = _gf_false;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
int ret = -1;
|
||||
|
||||
conf = this->private;
|
||||
ret = glusterd_get_quorum_cluster_counts (this, &active_count,
|
||||
&quorum_count,
|
||||
peers_list,
|
||||
_local_xaction_peers);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!_does_quorum_meet (active_count, quorum_count)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
in = _gf_true;
|
||||
out:
|
||||
return in;
|
||||
}
|
||||
|
||||
int
|
||||
glusterd_spawn_daemons (void *opaque)
|
||||
@ -3041,108 +2740,6 @@ glusterd_spawn_daemons (void *opaque)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
glusterd_do_volume_quorum_action (xlator_t *this, glusterd_volinfo_t *volinfo,
|
||||
gf_boolean_t meets_quorum)
|
||||
{
|
||||
glusterd_brickinfo_t *brickinfo = NULL;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
gd_quorum_status_t quorum_status = NOT_APPLICABLE_QUORUM;
|
||||
gf_boolean_t follows_quorum = _gf_false;
|
||||
|
||||
conf = this->private;
|
||||
if (volinfo->status != GLUSTERD_STATUS_STARTED) {
|
||||
volinfo->quorum_status = NOT_APPLICABLE_QUORUM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
follows_quorum = glusterd_is_volume_in_server_quorum (volinfo);
|
||||
if (follows_quorum) {
|
||||
if (meets_quorum)
|
||||
quorum_status = MEETS_QUORUM;
|
||||
else
|
||||
quorum_status = DOESNT_MEET_QUORUM;
|
||||
} else {
|
||||
quorum_status = NOT_APPLICABLE_QUORUM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following check is added to prevent spurious brick starts when
|
||||
* events occur that affect quorum.
|
||||
* Example:
|
||||
* There is a cluster of 10 peers. Volume is in quorum. User
|
||||
* takes down one brick from the volume to perform maintenance.
|
||||
* Suddenly one of the peers go down. Cluster is still in quorum. But
|
||||
* because of this 'peer going down' event, quorum is calculated and
|
||||
* the bricks that are down are brought up again. In this process it
|
||||
* also brings up the brick that is purposefully taken down.
|
||||
*/
|
||||
if (volinfo->quorum_status == quorum_status)
|
||||
goto out;
|
||||
|
||||
if (quorum_status == MEETS_QUORUM) {
|
||||
gf_msg (this->name, GF_LOG_CRITICAL, 0,
|
||||
GD_MSG_SERVER_QUORUM_MET_STARTING_BRICKS,
|
||||
"Server quorum regained for volume %s. Starting local "
|
||||
"bricks.", volinfo->volname);
|
||||
} else if (quorum_status == DOESNT_MEET_QUORUM) {
|
||||
gf_msg (this->name, GF_LOG_CRITICAL, 0,
|
||||
GD_MSG_SERVER_QUORUM_LOST_STOPPING_BRICKS,
|
||||
"Server quorum lost for volume %s. Stopping local "
|
||||
"bricks.", volinfo->volname);
|
||||
}
|
||||
|
||||
cds_list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
|
||||
if (!glusterd_is_local_brick (this, volinfo, brickinfo))
|
||||
continue;
|
||||
if (quorum_status == DOESNT_MEET_QUORUM)
|
||||
glusterd_brick_stop (volinfo, brickinfo, _gf_false);
|
||||
else
|
||||
glusterd_brick_start (volinfo, brickinfo, _gf_false);
|
||||
}
|
||||
volinfo->quorum_status = quorum_status;
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
glusterd_do_quorum_action ()
|
||||
{
|
||||
xlator_t *this = NULL;
|
||||
glusterd_conf_t *conf = NULL;
|
||||
glusterd_volinfo_t *volinfo = NULL;
|
||||
int ret = 0;
|
||||
int active_count = 0;
|
||||
int quorum_count = 0;
|
||||
gf_boolean_t meets = _gf_false;
|
||||
|
||||
this = THIS;
|
||||
conf = this->private;
|
||||
|
||||
conf->pending_quorum_action = _gf_true;
|
||||
ret = glusterd_lock (conf->uuid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
{
|
||||
ret = glusterd_get_quorum_cluster_counts (this, &active_count,
|
||||
&quorum_count, NULL,
|
||||
_gf_false);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
if (_does_quorum_meet (active_count, quorum_count))
|
||||
meets = _gf_true;
|
||||
cds_list_for_each_entry (volinfo, &conf->volumes, vol_list) {
|
||||
glusterd_do_volume_quorum_action (this, volinfo, meets);
|
||||
}
|
||||
}
|
||||
unlock:
|
||||
(void)glusterd_unlock (conf->uuid);
|
||||
conf->pending_quorum_action = _gf_false;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
glusterd_import_friend_volume_opts (dict_t *peer_data, int count,
|
||||
|
@ -37,15 +37,6 @@
|
||||
volinfo->volname, brickid);\
|
||||
} while (0)
|
||||
|
||||
#define GLUSTERD_QUORUM_COUNT(peerinfo, inquorum_count, active_count, _exit) do {\
|
||||
if (peerinfo->quorum_contrib == QUORUM_WAITING)\
|
||||
goto _exit;\
|
||||
if (_is_contributing_to_quorum (peerinfo->quorum_contrib))\
|
||||
inquorum_count = inquorum_count + 1;\
|
||||
if (active_count && (peerinfo->quorum_contrib == QUORUM_UP))\
|
||||
*active_count = *active_count + 1;\
|
||||
} while (0)
|
||||
|
||||
#define list_for_each_local_xaction_peers(xact_peer, xact_peers_head) \
|
||||
glusterd_local_peers_t *pos = NULL; \
|
||||
for (pos = cds_list_entry ((xact_peers_head)->next, \
|
||||
@ -149,10 +140,6 @@ glusterd_service_stop(const char *service, char *pidfile, int sig,
|
||||
int
|
||||
glusterd_get_next_available_brickid (glusterd_volinfo_t *volinfo);
|
||||
|
||||
int
|
||||
glusterd_validate_quorum (xlator_t *this, glusterd_op_t op, dict_t *dict,
|
||||
char **op_errstr);
|
||||
|
||||
int32_t
|
||||
glusterd_resolve_brick (glusterd_brickinfo_t *brickinfo);
|
||||
|
||||
@ -479,29 +466,8 @@ glusterd_set_originator_uuid (dict_t *dict);
|
||||
gf_boolean_t
|
||||
is_origin_glusterd (dict_t *dict);
|
||||
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_changed (dict_t *options, char *option, char *value);
|
||||
|
||||
int
|
||||
glusterd_do_quorum_action ();
|
||||
|
||||
int
|
||||
glusterd_get_quorum_cluster_counts (xlator_t *this, int *active_count,
|
||||
int *quorum_count,
|
||||
struct cds_list_head *peer_list,
|
||||
gf_boolean_t _local__xaction_peers);
|
||||
|
||||
int
|
||||
glusterd_get_next_global_opt_version_str (dict_t *opts, char **version_str);
|
||||
gf_boolean_t
|
||||
glusterd_is_quorum_option (char *option);
|
||||
gf_boolean_t
|
||||
glusterd_is_volume_in_server_quorum (glusterd_volinfo_t *volinfo);
|
||||
gf_boolean_t
|
||||
glusterd_is_any_volume_in_server_quorum (xlator_t *this);
|
||||
gf_boolean_t
|
||||
does_gd_meet_server_quorum (xlator_t *this, struct cds_list_head *peers_list,
|
||||
gf_boolean_t _local__xaction_peers);
|
||||
|
||||
int
|
||||
glusterd_generate_and_set_task_id (dict_t *dict, char *key);
|
||||
|
Loading…
x
Reference in New Issue
Block a user