diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-op-sm.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 9028 |
1 files changed, 3670 insertions, 5358 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index d5676d79a..1666f5e4d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-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 @@ -25,6 +15,7 @@ #include <time.h> #include <sys/uio.h> #include <sys/resource.h> +#include <sys/mount.h> #include <libgen.h> #include "uuid.h" @@ -44,20 +35,198 @@ #include "glusterd-op-sm.h" #include "glusterd-utils.h" #include "glusterd-store.h" +#include "glusterd-hooks.h" #include "glusterd-volgen.h" +#include "glusterd-locks.h" #include "syscall.h" -#include "cli1.h" +#include "cli1-xdr.h" #include "common-utils.h" +#include "run.h" #include <sys/types.h> #include <signal.h> - -#define glusterd_op_start_volume_args_get(dict, volname, flags) \ - glusterd_op_stop_volume_args_get (dict, volname, flags) +#include <sys/wait.h> + +#define ALL_VOLUME_OPTION_CHECK(volname, key, ret, op_errstr, label) \ + do { \ + gf_boolean_t _all = !strcmp ("all", volname); \ + gf_boolean_t _ratio = !strcmp (key, \ + GLUSTERD_QUORUM_RATIO_KEY); \ + if (_all && !_ratio) { \ + ret = -1; \ + *op_errstr = gf_strdup ("Not a valid option for all " \ + "volumes"); \ + goto label; \ + } else if (!_all && _ratio) { \ + ret = -1; \ + *op_errstr = gf_strdup ("Not a valid option for " \ + "single volume"); \ + goto label; \ + } \ + } while (0) static struct list_head gd_op_sm_queue; pthread_mutex_t gd_op_sm_lock; glusterd_op_info_t opinfo = {{0},}; +uuid_t global_txn_id = {"\0"}; /* To be used in + * heterogeneous + * cluster with no + * transaction ids */ + +static dict_t *txn_opinfo; + +struct txn_opinfo_object_ { + glusterd_op_info_t opinfo; +}; +typedef struct txn_opinfo_object_ txn_opinfo_obj; + +int32_t +glusterd_txn_opinfo_dict_init () +{ + int32_t ret = -1; + + txn_opinfo = dict_new (); + if (!txn_opinfo) { + ret = -1; + goto out; + } + + ret = 0; +out: + return ret; +} + +void +glusterd_txn_opinfo_dict_fini () +{ + if (txn_opinfo) + dict_destroy (txn_opinfo); +} + +void +glusterd_txn_opinfo_init (glusterd_op_info_t *opinfo, + glusterd_op_sm_state_info_t *state, + glusterd_op_t *op, + dict_t *op_ctx, + rpcsvc_request_t *req) +{ + GF_ASSERT (opinfo); + + if (state) + opinfo->state = *state; + + if (op) + opinfo->op = *op; + + opinfo->op_ctx = dict_ref(op_ctx); + + if (req) + opinfo->req = req; + + return; +} + +int32_t +glusterd_get_txn_opinfo (uuid_t *txn_id, glusterd_op_info_t *opinfo) +{ + int32_t ret = -1; + txn_opinfo_obj *opinfo_obj = NULL; + + if (!txn_id || !opinfo) { + gf_log ("", GF_LOG_ERROR, + "Empty transaction id or opinfo received."); + ret = -1; + goto out; + } + + ret = dict_get_bin(txn_opinfo, uuid_utoa (*txn_id), + (void **) &opinfo_obj); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Unable to get transaction opinfo"); + goto out; + } + + (*opinfo) = opinfo_obj->opinfo; + + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +glusterd_set_txn_opinfo (uuid_t *txn_id, glusterd_op_info_t *opinfo) +{ + int32_t ret = -1; + txn_opinfo_obj *opinfo_obj = NULL; + + if (!txn_id) { + gf_log ("", GF_LOG_ERROR, "Empty transaction id received."); + ret = -1; + goto out; + } + + ret = dict_get_bin(txn_opinfo, uuid_utoa (*txn_id), + (void **) &opinfo_obj); + if (ret) { + opinfo_obj = GF_CALLOC (1, sizeof(txn_opinfo_obj), + gf_common_mt_txn_opinfo_obj_t); + if (!opinfo_obj) { + ret = -1; + goto out; + } + + ret = dict_set_bin(txn_opinfo, uuid_utoa (*txn_id), opinfo_obj, + sizeof(txn_opinfo_obj)); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Unable to set opinfo for transaction ID : %s", + uuid_utoa (*txn_id)); + goto out; + } + } + + opinfo_obj->opinfo = (*opinfo); + + ret = 0; +out: + if (ret) + if (opinfo_obj) + GF_FREE (opinfo_obj); + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +glusterd_clear_txn_opinfo (uuid_t *txn_id) +{ + int32_t ret = -1; + glusterd_op_info_t txn_op_info = {{0},}; + + if (!txn_id) { + gf_log ("", GF_LOG_ERROR, "Empty transaction id received."); + ret = -1; + goto out; + } + + ret = glusterd_get_txn_opinfo (txn_id, &txn_op_info); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Transaction opinfo not found"); + goto out; + } + + dict_unref (txn_op_info.op_ctx); + + dict_del(txn_opinfo, uuid_utoa (*txn_id)); + + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + static int glusterfs_port = GLUSTERD_DEFAULT_PORT; static char *glusterd_op_sm_state_names[] = { "Default", @@ -74,6 +243,7 @@ static char *glusterd_op_sm_state_names[] = { "Brick op failed", "Brick op Committed", "Brick op Commit failed", + "Ack drain", "Invalid", }; @@ -91,25 +261,11 @@ static char *glusterd_op_sm_event_names[] = { "GD_OP_EVENT_UNLOCK", "GD_OP_EVENT_START_UNLOCK", "GD_OP_EVENT_ALL_ACK", + "GD_OP_EVENT_LOCAL_UNLOCK_NO_RESP", "GD_OP_EVENT_INVALID" }; -static char *gsync_opname[] = { - "gluster-command", - "gluster-log-file", - "gluster-log-level", - "log-file", - "log-level", - "remote-gsyncd", - "ssh-command", - "rsync-command", - "timeout", - "sync-jobs", - NULL -}; - -static int -glusterd_restart_brick_servers (glusterd_volinfo_t *); +extern struct volopt_map_entry glusterd_volopt_map[]; char* glusterd_op_sm_state_name_get (int state) @@ -150,32 +306,11 @@ glusterd_is_volume_started (glusterd_volinfo_t *volinfo) return (volinfo->status == GLUSTERD_STATUS_STARTED); } -gf_boolean_t -glusterd_are_all_volumes_stopped () -{ - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - glusterd_volinfo_t *voliter = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - list_for_each_entry (voliter, &priv->volumes, vol_list) { - if (voliter->status == GLUSTERD_STATUS_STARTED) - return _gf_false; - } - - return _gf_true; - -} - static int -glusterd_op_sm_inject_all_acc () +glusterd_op_sm_inject_all_acc (uuid_t *txn_id) { int32_t ret = -1; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, txn_id, NULL); gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -186,11 +321,13 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin { int ret = -1; gd1_mgmt_brick_op_req *brick_req = NULL; - gf1_cli_top_op top_op = 0; - double throughput = 0; - double time = 0; - int32_t blk_size = 0; - int32_t blk_count = 0; + char *volname = NULL; + char name[1024] = {0,}; + gf_xl_afr_op_t heal_op = GF_AFR_OP_INVALID; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); GF_ASSERT (op < GD_OP_MAX); GF_ASSERT (op > GD_OP_NONE); @@ -202,67 +339,83 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin case GD_OP_STOP_VOLUME: brick_req = GF_CALLOC (1, sizeof (*brick_req), gf_gld_mt_mop_brick_req_t); - if (!brick_req) { - gf_log ("", GF_LOG_ERROR, "Out of Memory"); + if (!brick_req) goto out; - } - brick_req->op = GF_BRICK_TERMINATE; + brick_req->op = GLUSTERD_BRICK_TERMINATE; brick_req->name = ""; break; case GD_OP_PROFILE_VOLUME: brick_req = GF_CALLOC (1, sizeof (*brick_req), gf_gld_mt_mop_brick_req_t); - if (!brick_req) { - gf_log ("", GF_LOG_ERROR, "Out of Memory"); + if (!brick_req) goto out; - } - brick_req->op = GF_BRICK_XLATOR_INFO; + brick_req->op = GLUSTERD_BRICK_XLATOR_INFO; brick_req->name = brickinfo->path; - ret = dict_get_int32 (dict, "top-op", (int32_t*)&top_op); + break; + case GD_OP_HEAL_VOLUME: + { + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) + goto out; + + brick_req->op = GLUSTERD_BRICK_XLATOR_OP; + brick_req->name = ""; + ret = dict_get_int32 (dict, "heal-op", (int32_t*)&heal_op); + if (ret) + goto out; + ret = dict_set_int32 (dict, "xl-op", heal_op); + } + break; + case GD_OP_STATUS_VOLUME: + { + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) + goto out; + brick_req->op = GLUSTERD_BRICK_STATUS; + brick_req->name = ""; + } + break; + case GD_OP_REBALANCE: + case GD_OP_DEFRAG_BRICK_VOLUME: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) + goto out; + + brick_req->op = GLUSTERD_BRICK_XLATOR_DEFRAG; + ret = dict_get_str (dict, "volname", &volname); if (ret) - goto cont; - if (top_op == GF_CLI_TOP_READ_PERF || - top_op == GF_CLI_TOP_WRITE_PERF) { + goto out; + snprintf (name, 1024, "%s-dht",volname); + brick_req->name = gf_strdup (name); - ret = dict_get_int32 (dict, "blk-size", &blk_size); - if (ret) { - goto cont; - } - ret = dict_get_int32 (dict, "blk-cnt", &blk_count); - if (ret) - goto out; - if (top_op == GF_CLI_TOP_READ_PERF) - ret = glusterd_volume_stats_read_perf ( - brickinfo->path, blk_size, blk_count, - &throughput, &time); - else if (!ret && top_op == GF_CLI_TOP_WRITE_PERF) - ret = glusterd_volume_stats_write_perf ( - brickinfo->path, blk_size, blk_count, - &throughput, &time); - - if (ret) - goto out; + break; + case GD_OP_SNAP: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) + goto out; + + brick_req->op = GLUSTERD_VOLUME_BARRIER_OP; + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + snprintf (name, 1024, "%s-server",volname); + brick_req->name = gf_strdup (name); - ret = dict_set_double (dict, "throughput", - throughput); - if (ret) - goto out; - ret = dict_set_double (dict, "time", time); - if (ret) - goto out; - } break; default: goto out; break; } -cont: ret = dict_allocate_and_serialize (dict, &brick_req->input.input_val, - (size_t*)&brick_req->input.input_len); + &brick_req->input.input_len); if (ret) goto out; *req = brick_req; @@ -271,1023 +424,397 @@ cont: out: if (ret && brick_req) GF_FREE (brick_req); - gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } -static int -glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) +int +glusterd_node_op_build_payload (glusterd_op_t op, gd1_mgmt_brick_op_req **req, + dict_t *dict) { - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char *bricks = NULL; - char *brick_list = NULL; - char *free_ptr = NULL; - glusterd_brickinfo_t *brick_info = NULL; - int32_t brick_count = 0; - int32_t i = 0; - char *brick = NULL; - char *tmpptr = NULL; - char cmd_str[1024]; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - char msg[2048] = {0}; - - this = THIS; - if (!this) { - gf_log ("glusterd", GF_LOG_ERROR, - "this is NULL"); - goto out; - } - - priv = this->private; - if (!priv) { - gf_log ("glusterd", GF_LOG_ERROR, - "priv is NULL"); - goto out; - } - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - - if (exists) { - snprintf (msg, sizeof (msg), "Volume %s already exists", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } else { - ret = 0; - } - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } + int ret = -1; + gd1_mgmt_brick_op_req *brick_req = NULL; - if (bricks) { - brick_list = gf_strdup (bricks); - if (!brick_list) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "Out of memory"); - goto out; - } else { - free_ptr = brick_list; - } - } + GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT (op > GD_OP_NONE); + GF_ASSERT (req); - while ( i < brick_count) { - i++; - brick= strtok_r (brick_list, " \n", &tmpptr); - brick_list = tmpptr; - ret = glusterd_brickinfo_from_brick (brick, &brick_info); - if (ret) - goto out; - snprintf (cmd_str, 1024, "%s", brick_info->path); - ret = glusterd_resolve_brick (brick_info); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "cannot resolve " - "brick: %s:%s", brick_info->hostname, - brick_info->path); + switch (op) { + case GD_OP_PROFILE_VOLUME: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) goto out; - } - if (!uuid_compare (brick_info->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brick_info->hostname, - brick_info->path, - 0777, op_errstr); - if (ret) - goto out; - brick_list = tmpptr; - } - glusterd_brickinfo_delete (brick_info); - brick_info = NULL; - } -out: - if (free_ptr) - GF_FREE (free_ptr); - if (brick_info) - glusterd_brickinfo_delete (brick_info); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, - int *flags) -{ - int ret = -1; - - if (!dict || !volname || !flags) - goto out; + brick_req->op = GLUSTERD_NODE_PROFILE; + brick_req->name = ""; - ret = dict_get_str (dict, "volname", volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } + break; - ret = dict_get_int32 (dict, "flags", flags); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get flags"); - goto out; - } -out: - return ret; -} + case GD_OP_STATUS_VOLUME: + brick_req = GF_CALLOC (1, sizeof (*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) + goto out; -static int -glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - int flags = 0; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - char msg[2048]; - glusterd_conf_t *priv = NULL; + brick_req->op = GLUSTERD_NODE_STATUS; + brick_req->name = ""; - priv = THIS->private; - if (!priv) { - gf_log ("glusterd", GF_LOG_ERROR, - "priv is NULL"); - ret = -1; - goto out; - } + break; - ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); - if (ret) + default: goto out; - - exists = glusterd_check_volume_exists (volname); - - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); - gf_log ("", GF_LOG_ERROR, "%s", - msg); - *op_errstr = gf_strdup (msg); - ret = -1; - } else { - ret = 0; } - ret = glusterd_volinfo_find (volname, &volinfo); + ret = dict_allocate_and_serialize (dict, &brick_req->input.input_val, + &brick_req->input.input_len); if (ret) goto out; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_resolve_brick (brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to resolve brick %s:%s", - brickinfo->hostname, brickinfo->path); - goto out; - } - - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brickinfo->hostname, - brickinfo->path, - 0777, op_errstr); - if (ret) - goto out; - } - - if (!(flags & GF_CLI_FLAG_OP_FORCE)) { - if (glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s already" - " started", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - } - } - + *req = brick_req; ret = 0; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +out: + if (ret && brick_req) + GF_FREE (brick_req); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } static int -glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) +glusterd_validate_quorum_options (xlator_t *this, char *fullkey, char *value, + char **op_errstr) { - int ret = -1; - char *volname = NULL; - int flags = 0; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - char msg[2048] = {0}; - - - ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); - if (ret) - goto out; - - exists = glusterd_check_volume_exists (volname); - - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } else { - ret = 0; - } - - ret = glusterd_volinfo_find (volname, &volinfo); + int ret = 0; + char *key = NULL; + volume_option_t *opt = NULL; - if (ret) + if (!glusterd_is_quorum_option (fullkey)) goto out; - - if (!(flags & GF_CLI_FLAG_OP_FORCE)) { - if (_gf_false == glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof(msg), "Volume %s " - "is not in the started state", volname); - gf_log ("", GF_LOG_ERROR, "Volume %s " - "has not been started", volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - } - - + key = strchr (fullkey, '.'); + key++; + opt = xlator_volume_option_get (this, key); + ret = xlator_option_validate (this, key, value, opt, op_errstr); out: - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; } static int -glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr) +glusterd_check_client_op_version_support (char *volname, uint32_t op_version, + char **op_errstr) { - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - char msg[2048] = {0}; - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } + int ret = 0; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + rpc_transport_t *xprt = NULL; - exists = glusterd_check_volume_exists (volname); + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } else { - ret = 0; + pthread_mutex_lock (&priv->xprt_lock); + list_for_each_entry (xprt, &priv->xprt_list, list) { + if ((!strcmp(volname, xprt->peerinfo.volname)) && + ((op_version > xprt->peerinfo.max_op_version) || + (op_version < xprt->peerinfo.min_op_version))) { + ret = -1; + break; + } } + pthread_mutex_unlock (&priv->xprt_lock); - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) - goto out; - - if (glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s has been started." - "Volume needs to be stopped before deletion.", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "One or more clients " + "don't support the required op-version"); + ret = gf_asprintf (op_errstr, "One or more connected clients " + "cannot support the feature being set. " + "These clients need to be upgraded or " + "disconnected before running this command" + " again"); + return -1; } - - ret = 0; - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; + return 0; } static int -glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr) +glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) { - int ret = 0; - char *volname = NULL; - int count = 0; - int i = 0; - char *bricks = NULL; - char *brick_list = NULL; - char *saveptr = NULL; - char *free_ptr = NULL; - char *brick = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - glusterd_volinfo_t *volinfo = NULL; - char cmd_str[1024]; - glusterd_conf_t *priv = NULL; - char msg[2048] = {0,}; - gf_boolean_t brick_alloc = _gf_false; - char *all_bricks = NULL; - char *str_ret = NULL; - - priv = THIS->private; - if (!priv) - goto out; + int ret = -1; + char *volname = NULL; + int exists = 0; + char *key = NULL; + char *key_fixed = NULL; + char *value = NULL; + char str[100] = {0, }; + int count = 0; + int dict_count = 0; + char errstr[2048] = {0, }; + glusterd_volinfo_t *volinfo = NULL; + dict_t *val_dict = NULL; + gf_boolean_t global_opt = _gf_false; + glusterd_volinfo_t *voliter = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + uint32_t new_op_version = 0; + uint32_t local_new_op_version = 0; + uint32_t key_op_version = 0; + uint32_t local_key_op_version = 0; + gf_boolean_t origin_glusterd = _gf_true; + gf_boolean_t check_op_version = _gf_true; + gf_boolean_t all_vol = _gf_false; + struct volopt_map_entry *vme = NULL; - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to find volume: %s", volname); - goto out; - } + GF_ASSERT (dict); + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); - if (glusterd_is_defrag_on(volinfo)) { - snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " - "progress. Please retry after completion", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); + val_dict = dict_new(); + if (!val_dict) goto out; - } - ret = dict_get_str (dict, "bricks", &bricks); + ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name"); goto out; } - if (bricks) { - brick_list = gf_strdup (bricks); - all_bricks = gf_strdup (bricks); - free_ptr = brick_list; - } - - /* Check whether any of the bricks given is the destination brick of the - replace brick running */ - - str_ret = glusterd_check_brick_rb_part (all_bricks, count, volinfo); - if (str_ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "%s", str_ret); - *op_errstr = gf_strdup (str_ret); - ret = -1; - goto out; - } + /* Check if we can support the required op-version + * This check is not done on the originator glusterd. The originator + * glusterd sets this value. + */ + origin_glusterd = is_origin_glusterd (dict); - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); + if (!origin_glusterd) { + /* Check for v3.3.x origin glusterd */ + check_op_version = dict_get_str_boolean (dict, + "check-op-version", + _gf_false); - - while ( i < count) { - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - &brickinfo); - if (!ret) { - gf_log ("", GF_LOG_ERROR, "Adding duplicate brick: %s", - brick); - ret = -1; - goto out; - } else { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (check_op_version) { + ret = dict_get_uint32 (dict, "new-op-version", + &new_op_version); if (ret) { - gf_log ("", GF_LOG_ERROR, "Add-brick: Unable" - " to get brickinfo"); + gf_log (this->name, GF_LOG_ERROR, + "Failed to get new_op_version"); goto out; } - brick_alloc = _gf_true; - } - snprintf (cmd_str, 1024, "%s", brickinfo->path); - ret = glusterd_resolve_brick (brickinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "resolve brick failed"); - goto out; - } - - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brickinfo->hostname, - brickinfo->path, - 0777, op_errstr); - if (ret) + if ((new_op_version > GD_OP_VERSION_MAX) || + (new_op_version < GD_OP_VERSION_MIN)) { + ret = -1; + snprintf (errstr, sizeof (errstr), + "Required op_version (%d) is not " + "supported", new_op_version); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); goto out; + } } - - glusterd_brickinfo_delete (brickinfo); - brick_alloc = _gf_false; - brickinfo = NULL; - brick = strtok_r (NULL, " \n", &saveptr); - i++; } -out: - if (free_ptr) - GF_FREE (free_ptr); - if (brick_alloc && brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (str_ret) - GF_FREE (str_ret); - if (all_bricks) - GF_FREE (all_bricks); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -char * -glusterd_check_brick_rb_part (char *bricks, int count, glusterd_volinfo_t *volinfo) -{ - char *saveptr = NULL; - char *brick = NULL; - char *brick_list = NULL; - int ret = 0; - glusterd_brickinfo_t *brickinfo = NULL; - uint32_t i = 0; - char *str = NULL; - char msg[2048] = {0,}; - - brick_list = gf_strdup (bricks); - if (!brick_list) { - gf_log ("glusterd", GF_LOG_ERROR, - "Out of memory"); - ret = -1; + ret = dict_get_int32 (dict, "count", &dict_count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Count(dict),not set in Volume-Set"); goto out; } - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - - while ( i < count) { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) { - snprintf (msg, sizeof(msg), "Unable to" - " get brickinfo"); - gf_log ("", GF_LOG_ERROR, "%s", msg); - ret = -1; + if (dict_count == 0) { + /*No options would be specified of volume set help */ + if (dict_get (dict, "help" )) { + ret = 0; goto out; } - if (glusterd_is_replace_running (volinfo, brickinfo)) { - snprintf (msg, sizeof(msg), "Volume %s: replace brick is running" - " and the brick %s:%s you are trying to add is the destination brick" - " for replace brick", volinfo->volname, brickinfo->hostname, brickinfo->path); - ret = -1; + if (dict_get (dict, "help-xml" )) { +#if (HAVE_LIB_XML) + ret = 0; goto out; +#else + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "libxml not present in the system"); + *op_errstr = gf_strdup ("Error: xml libraries not " + "present to produce xml-output"); + goto out; +#endif } - - glusterd_brickinfo_delete (brickinfo); - brickinfo = NULL; - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } - -out: - if (brick_list) - GF_FREE(brick_list); - if (brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (ret) - str = gf_strdup (msg); - return str; -} - -static int -glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t **brickinfo) -{ - int32_t ret = -1; - - if (!volinfo || !brickinfo) - goto out; - - *brickinfo = volinfo->dst_brick; - - ret = 0; - -out: - return ret; -} - -static int -glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, - dict_t *rsp_dict) -{ - int ret = 0; - char *src_brick = NULL; - char *dst_brick = NULL; - char *volname = NULL; - int replace_op = 0; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *src_brickinfo = NULL; - char *host = NULL; - char *path = NULL; - char msg[2048] = {0}; - char *dup_dstbrick = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_brickinfo_t *dst_brickinfo = NULL; - - ret = dict_get_str (dict, "src-brick", &src_brick); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, "src brick=%s", src_brick); - - ret = dict_get_str (dict, "dst-brick", &dst_brick); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); + gf_log (this->name, GF_LOG_ERROR, "No options received "); + *op_errstr = gf_strdup ("Options not specified"); + ret = -1; goto out; } - gf_log ("", GF_LOG_DEBUG, "dst brick=%s", dst_brick); - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name"); goto out; } - ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "dict get on replace-brick operation failed"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - snprintf (msg, sizeof (msg), "volume: %s does not exist", - volname); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - ret = -1; - snprintf (msg, sizeof (msg), "volume: %s is not started", - volname); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (glusterd_is_defrag_on(volinfo)) { - snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " - "progress. Please retry after completion", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - switch (replace_op) { - case GF_REPLACE_OP_START: - if (glusterd_is_rb_started (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is already " - "started for volume "); + if (strcasecmp (volname, "all") != 0) { + exists = glusterd_check_volume_exists (volname); + if (!exists) { + snprintf (errstr, sizeof (errstr), + FMTSTR_CHECK_VOL_EXISTS, volname); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); ret = -1; goto out; } - break; - case GF_REPLACE_OP_PAUSE: - if (glusterd_is_rb_paused (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is already " - "paused for volume "); - ret = -1; - goto out; - } else if (!glusterd_is_rb_started(volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is not" - " started for volume "); - ret = -1; - goto out; - } - break; - - case GF_REPLACE_OP_ABORT: - if ((!glusterd_is_rb_paused (volinfo)) && - (!glusterd_is_rb_started (volinfo))) { - gf_log ("", GF_LOG_ERROR, "Replace brick is not " - " started or paused for volume "); - ret = -1; - goto out; - } - break; - case GF_REPLACE_OP_COMMIT: - if (!glusterd_is_rb_started (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is not " - "started for volume "); - ret = -1; + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + FMTSTR_CHECK_VOL_EXISTS, volname); goto out; } - break; - - case GF_REPLACE_OP_COMMIT_FORCE: break; - case GF_REPLACE_OP_STATUS: - break; - default: - ret = -1; - goto out; - } - - ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, - &src_brickinfo); - if (ret) { - snprintf (msg, sizeof (msg), "brick: %s does not exist in " - "volume: %s", src_brick, volname); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - gf_log ("", GF_LOG_DEBUG, - "I AM THE SOURCE HOST"); - if (src_brickinfo->port && rsp_dict) { - ret = dict_set_int32 (rsp_dict, "src-brick-port", - src_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set src-brick-port=%d", - src_brickinfo->port); - } - } - - } - - dup_dstbrick = gf_strdup (dst_brick); - if (!dup_dstbrick) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "Memory allocation failed"); - goto out; - } - host = strtok (dup_dstbrick, ":"); - path = strtok (NULL, ":"); - - if (!host || !path) { - gf_log ("", GF_LOG_ERROR, - "dst brick %s is not of form <HOSTNAME>:<export-dir>", - dst_brick); - ret = -1; - goto out; - } - if (!glusterd_brickinfo_get (NULL, host, path, NULL)) { - snprintf(msg, sizeof(msg), "Brick: %s:%s already in use", - host, path); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - if ((volinfo->rb_status ==GF_RB_STATUS_NONE) && - (replace_op == GF_REPLACE_OP_START)) { - ret = glusterd_brickinfo_from_brick (dst_brick, &dst_brickinfo); - volinfo->src_brick = src_brickinfo; - volinfo->dst_brick = dst_brickinfo; - } else { - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); - } - if (glusterd_rb_check_bricks (volinfo, src_brickinfo, dst_brickinfo)) { - gf_log ("", GF_LOG_ERROR, "replace brick: incorrect source or" - " destination bricks specified"); - ret = -1; - goto out; - } - if (!glusterd_is_local_addr (host)) { - ret = glusterd_brick_create_path (host, path, 0777, op_errstr); + ret = glusterd_validate_volume_id (dict, volinfo); if (ret) goto out; } else { - ret = glusterd_friend_find (NULL, host, &peerinfo); - if (ret) { - snprintf (msg, sizeof (msg), "%s, is not a friend", - host); - *op_errstr = gf_strdup (msg); - goto out; - } - - if (!peerinfo->connected) { - snprintf (msg, sizeof (msg), "%s, is not connected at " - "the moment", host); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - if (GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state) { - snprintf (msg, sizeof (msg), "%s, is not befriended " - "at the moment", host); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } + all_vol = _gf_true; } - ret = 0; -out: - if (dup_dstbrick) - GF_FREE (dup_dstbrick); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_log_filename (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0}; - char *path = NULL; - char hostname[2048] = {0}; - char *brick = NULL; - glusterd_volinfo_t *volinfo = NULL; + local_new_op_version = priv->op_version; - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if (!exists || ret) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "brick", &brick); - if (ret) - goto out; + for ( count = 1; ret != 1 ; count++ ) { + global_opt = _gf_false; + sprintf (str, "key%d", count); + ret = dict_get_str (dict, str, &key); + if (ret) + break; - if (strchr (brick, ':')) { - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - NULL); + sprintf (str, "value%d", count); + ret = dict_get_str (dict, str, &value); if (ret) { - snprintf (msg, sizeof (msg), "Incorrect brick %s " - "for volume %s", brick, volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); + gf_log (this->name, GF_LOG_ERROR, + "invalid key,value pair in 'volume set'"); + ret = -1; goto out; } - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "path not found"); - goto out; - } - - ret = gethostname (hostname, sizeof (hostname)); - if (ret) { - snprintf (msg, sizeof (msg), "Failed to get hostname, error:%s", - strerror (errno)); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - goto out; - } - - ret = glusterd_brick_create_path (hostname, path, 0777, op_errstr); - if (ret) - goto out; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_log_rotate (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0}; - char *brick = NULL; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - if (_gf_false == glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s needs to be started before" - " log rotate.", volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - ret = dict_get_str (dict, "brick", &brick); - if (ret) - goto out; - - if (strchr (brick, ':')) { - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - NULL); - if (ret) { - snprintf (msg, sizeof (msg), "Incorrect brick %s " - "for volume %s", brick, volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - goto out; + if (strcmp (key, "config.memory-accounting") == 0) { + gf_log (this->name, GF_LOG_DEBUG, + "enabling memory accounting for volume %s", + volname); + ret = 0; } - } -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -static int -glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - int exists = 0; - char *key = NULL; - char *key_fixed = NULL; - char *value = NULL; - char str[100] = {0, }; - int count = 0; - int dict_count = 0; - char errstr[2048] = {0, }; - glusterd_volinfo_t *volinfo = NULL; - dict_t *val_dict = NULL; - gf_boolean_t global_opt = _gf_false; - glusterd_volinfo_t *voliter = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - - GF_ASSERT (dict); - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - val_dict = dict_new(); - if (!val_dict) - goto out; - - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - exists = glusterd_check_volume_exists (volname); - - if (!exists) { - snprintf (errstr, sizeof (errstr), "Volume %s does not exist", - volname); - gf_log ("", GF_LOG_ERROR, "%s", errstr); - *op_errstr = gf_strdup (errstr); - ret = -1; - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &dict_count); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Count(dict),not set in Volume-Set"); - goto out; - } - - if ( dict_count == 1 ) { - if (dict_get (dict, "history" )) { + if (strcmp (key, "config.transport") == 0) { + gf_log (this->name, GF_LOG_DEBUG, + "changing transport-type for volume %s", + volname); ret = 0; - goto out; + /* if value is none of 'tcp/rdma/tcp,rdma' error out */ + if (!((strcasecmp (value, "rdma") == 0) || + (strcasecmp (value, "tcp") == 0) || + (strcasecmp (value, "tcp,rdma") == 0) || + (strcasecmp (value, "rdma,tcp") == 0))) { + ret = snprintf (errstr, sizeof (errstr), + "transport-type %s does " + "not exist", value); + /* lets not bother about above return value, + its a failure anyways */ + ret = -1; + goto out; + } } - gf_log ("", GF_LOG_ERROR, "No options received "); - *op_errstr = gf_strdup ("Options not specified"); - ret = -1; - goto out; - } - - - - for ( count = 1; ret != 1 ; count++ ) { - global_opt = _gf_false; - sprintf (str, "key%d", count); - ret = dict_get_str (dict, str, &key); - + if (is_key_glusterd_hooks_friendly (key)) + continue; - if (ret) - break; + for (vme = &glusterd_volopt_map[0]; vme->key; vme++) { + if ((vme->validate_fn) && + ((!strcmp (key, vme->key)) || + (!strcmp (key, strchr (vme->key, '.') + 1)))) { + ret = vme->validate_fn (dict, key, value, + op_errstr); + if (ret) + goto out; + break; + } + } - exists = glusterd_check_option_exists (key, &key_fixed); + exists = glusterd_check_option_exists (key, &key_fixed); if (exists == -1) { ret = -1; goto out; } - if (!exists) { - gf_log ("", GF_LOG_ERROR, "Option with name: %s " - "does not exist", key); - ret = snprintf (errstr, 2048, + + if (!exists) { + gf_log (this->name, GF_LOG_ERROR, + "Option with name: %s does not exist", key); + ret = snprintf (errstr, sizeof (errstr), "option : %s does not exist", key); if (key_fixed) - snprintf (errstr + ret, 2048 - ret, + snprintf (errstr + ret, sizeof (errstr) - ret, "\nDid you mean %s?", key_fixed); - *op_errstr = gf_strdup (errstr); - ret = -1; - goto out; - } - - sprintf (str, "value%d", count); - ret = dict_get_str (dict, str, &value); - - if (ret) { - gf_log ("", GF_LOG_ERROR, - "invalid key,value pair in 'volume set'"); ret = -1; goto out; } if (key_fixed) key = key_fixed; - - ret = glusterd_check_globaloption (key); + ALL_VOLUME_OPTION_CHECK (volname, key, ret, op_errstr, out); + ret = glusterd_validate_quorum_options (this, key, value, + op_errstr); if (ret) + goto out; + + local_key_op_version = glusterd_get_op_version_for_key (key); + if (local_key_op_version > local_new_op_version) + local_new_op_version = local_key_op_version; + + sprintf (str, "op-version%d", count); + if (origin_glusterd) { + ret = dict_set_uint32 (dict, str, local_key_op_version); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set key-op-version in dict"); + goto out; + } + } else if (check_op_version) { + ret = dict_get_uint32 (dict, str, &key_op_version); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to get key-op-version from" + " dict"); + goto out; + } + if (local_key_op_version != key_op_version) { + ret = -1; + snprintf (errstr, sizeof (errstr), + "option: %s op-version mismatch", + key); + gf_log (this->name, GF_LOG_ERROR, + "%s, required op-version = %"PRIu32", " + "available op-version = %"PRIu32, + errstr, key_op_version, + local_key_op_version); + goto out; + } + } + + if (glusterd_check_globaloption (key)) global_opt = _gf_true; ret = dict_set_str (val_dict, key, value); if (ret) { - gf_log ("", GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "Unable to set the options in 'volume set'"); ret = -1; goto out; } *op_errstr = NULL; - if (!global_opt) + if (!global_opt && !all_vol) ret = glusterd_validate_reconfopts (volinfo, val_dict, op_errstr); - else { + else if (!all_vol) { voliter = NULL; list_for_each_entry (voliter, &priv->volumes, vol_list) { ret = glusterd_validate_globalopts (voliter, val_dict, op_errstr); @@ -1297,8 +824,9 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) } if (ret) { - gf_log ("glusterd", GF_LOG_DEBUG, "Could not create temp " - "volfile, some option failed: %s", *op_errstr); + gf_log (this->name, GF_LOG_ERROR, "Could not create " + "temp volfile, some option failed: %s", + *op_errstr); goto out; } dict_del (val_dict, key); @@ -1309,6 +837,35 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) } } + // Check if all the connected clients support the new op-version + ret = glusterd_check_client_op_version_support (volname, + local_new_op_version, + op_errstr); + if (ret) + goto out; + + if (origin_glusterd) { + ret = dict_set_uint32 (dict, "new-op-version", + local_new_op_version); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set new-op-version in dict"); + goto out; + } + /* Set this value in dict so other peers know to check for + * op-version. This is a hack for 3.3.x compatibility + * + * TODO: Remove this and the other places this is referred once + * 3.3.x compatibility is not required + */ + ret = dict_set_uint32 (dict, "check-op-version", + _gf_true); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set check-op-version in dict"); + goto out; + } + } ret = 0; @@ -1316,17 +873,18 @@ out: if (val_dict) dict_unref (val_dict); - if (key_fixed) - GF_FREE (key_fixed); + GF_FREE (key_fixed); + if (errstr[0] != '\0') + *op_errstr = gf_strdup (errstr); if (ret) { if (!(*op_errstr)) { *op_errstr = gf_strdup ("Error, Validation Failed"); - gf_log ("glsuterd", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "Error, Cannot Validate option :%s", *op_errstr); } else { - gf_log ("glsuterd", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "Error, Cannot Validate option"); } } @@ -1340,292 +898,83 @@ glusterd_op_stage_reset_volume (dict_t *dict, char **op_errstr) char *volname = NULL; gf_boolean_t exists = _gf_false; char msg[2048] = {0}; + char *key = NULL; + char *key_fixed = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s does not " - "exist", volname); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - - -static int -glusterd_op_perform_remove_brick (glusterd_volinfo_t *volinfo, char *brick) -{ - - glusterd_brickinfo_t *brickinfo = NULL; - char *dup_brick = NULL; - glusterd_conf_t *priv = NULL; - int32_t ret = -1; - - GF_ASSERT (volinfo); - GF_ASSERT (brick); - - priv = THIS->private; - - dup_brick = gf_strdup (brick); - if (!dup_brick) - goto out; - - ret = glusterd_volume_brickinfo_get_by_brick (dup_brick, volinfo, &brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_stop (volinfo, brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to stop " - "glusterfs, ret: %d", ret); - goto out; - } - } - glusterd_delete_brick (volinfo, brickinfo); -out: - if (dup_brick) - GF_FREE (dup_brick); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo, - char *old_brick, char *new_brick) -{ - glusterd_brickinfo_t *old_brickinfo = NULL; - glusterd_brickinfo_t *new_brickinfo = NULL; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - - GF_ASSERT (volinfo); - - ret = glusterd_brickinfo_from_brick (new_brick, - &new_brickinfo); - if (ret) - goto out; - - ret = glusterd_volume_brickinfo_get_by_brick (old_brick, volinfo, - &old_brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (new_brickinfo); - if (ret) - goto out; - - list_add_tail (&new_brickinfo->brick_list, - &old_brickinfo->brick_list); - - volinfo->brick_count++; - - ret = glusterd_op_perform_remove_brick (volinfo, old_brick); - if (ret) - goto out; - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_start (volinfo, new_brickinfo); - if (ret) - goto out; - } - - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_op_perform_add_bricks (glusterd_volinfo_t *volinfo, int32_t count, - char *bricks) -{ - glusterd_brickinfo_t *brickinfo = NULL; - char *brick = NULL; - int32_t i = 1; - char *brick_list = NULL; - char *free_ptr1 = NULL; - char *free_ptr2 = NULL; - char *saveptr = NULL; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - - priv = THIS->private; - - GF_ASSERT (volinfo); - - if (bricks) { - brick_list = gf_strdup (bricks); - free_ptr1 = brick_list; - } - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - while ( i <= count) { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - list_add_tail (&brickinfo->brick_list, &volinfo->bricks); - brick = strtok_r (NULL, " \n", &saveptr); - i++; - volinfo->brick_count++; - - } - - brick_list = gf_strdup (bricks); - free_ptr2 = brick_list; - i = 1; - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) - goto out; - - while (i <= count) { - - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - &brickinfo); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_start (volinfo, brickinfo); - if (ret) - goto out; - } - i++; - brick = strtok_r (NULL, " \n", &saveptr); - } - -out: - if (free_ptr1) - GF_FREE (free_ptr1); - if (free_ptr2) - GF_FREE (free_ptr2); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - - -static int -glusterd_op_stage_remove_brick (dict_t *dict) -{ - int ret = -1; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - dict_t *ctx = NULL; - char *errstr = NULL; - int32_t brick_count = 0; + this = THIS; + GF_ASSERT (this); ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Volume %s does not exist", volname); + gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name"); goto out; } - if (glusterd_is_defrag_on(volinfo)) { - ctx = glusterd_op_get_ctx (GD_OP_REMOVE_BRICK); - errstr = gf_strdup("Rebalance is in progress. Please retry" - " after completion"); - if (!errstr) { + if (strcasecmp (volname, "all") != 0) { + exists = glusterd_check_volume_exists (volname); + if (!exists) { + snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, + volname); ret = -1; goto out; } - gf_log ("glusterd", GF_LOG_ERROR, "%s", errstr); - ret = dict_set_dynstr (ctx, "errstr", errstr); + ret = glusterd_volinfo_find (volname, &volinfo); if (ret) { - GF_FREE (errstr); - gf_log ("", GF_LOG_DEBUG, - "failed to set errstr ctx"); + snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, + volname); goto out; } - ret = -1; - goto out; + ret = glusterd_validate_volume_id (dict, volinfo); + if (ret) + goto out; } - ret = dict_get_int32 (dict, "count", &brick_count); + ret = dict_get_str (dict, "key", &key); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get brick count"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get option key"); goto out; } - - if (volinfo->brick_count == brick_count) { - ctx = glusterd_op_get_ctx (GD_OP_REMOVE_BRICK); - if (!ctx) { - gf_log ("", GF_LOG_ERROR, - "Operation Context is not present"); + if (strcmp(key, "all")) { + exists = glusterd_check_option_exists (key, &key_fixed); + if (exists == -1) { ret = -1; goto out; } - errstr = gf_strdup ("Deleting all the bricks of the " - "volume is not allowed"); - if (!errstr) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); + if (!exists) { + ret = snprintf (msg, sizeof (msg), + "Option %s does not exist", key); + if (key_fixed) + snprintf (msg + ret, sizeof (msg) - ret, + "\nDid you mean %s?", key_fixed); ret = -1; goto out; + } else if (exists > 0) { + if (key_fixed) + key = key_fixed; + ALL_VOLUME_OPTION_CHECK (volname, key, ret, + op_errstr, out); } + } - ret = dict_set_dynstr (ctx, "errstr", errstr); - if (ret) { - GF_FREE (errstr); - gf_log ("", GF_LOG_DEBUG, - "failed to set pump status in ctx"); - goto out; - } +out: + GF_FREE (key_fixed); - ret = -1; - goto out; + if (msg[0] != '\0') { + gf_log (this->name, GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); } -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } + + static int glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) { @@ -1635,6 +984,7 @@ glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) gf_boolean_t exists = _gf_false; glusterd_peerinfo_t *peerinfo = NULL; char msg[2048] = {0,}; + glusterd_volinfo_t *volinfo = NULL; ret = dict_get_str (dict, "hostname", &hostname); if (ret) { @@ -1644,8 +994,26 @@ glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) goto out; } - ret = glusterd_is_local_addr (hostname); - if (ret) { + if (gf_is_local_addr (hostname)) { + //volname is not present in case of sync all + ret = dict_get_str (dict, "volname", &volname); + if (!ret) { + exists = glusterd_check_volume_exists (volname); + if (!exists) { + snprintf (msg, sizeof (msg), "Volume %s " + "does not exist", volname); + *op_errstr = gf_strdup (msg); + ret = -1; + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) + goto out; + + } else { + ret = 0; + } + } else { ret = glusterd_friend_find (NULL, hostname, &peerinfo); if (ret) { snprintf (msg, sizeof (msg), "%s, is not a friend", @@ -1661,22 +1029,7 @@ glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) ret = -1; goto out; } - } else { - //volname is not present in case of sync all - ret = dict_get_str (dict, "volname", &volname); - if (!ret) { - exists = glusterd_check_volume_exists (volname); - if (!exists) { - snprintf (msg, sizeof (msg), "Volume %s " - "does not exist", volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } - } else { - ret = 0; - } } out: @@ -1685,356 +1038,144 @@ out: return ret; } -char * -volname_from_master (char *master) -{ - if (master == NULL) - return NULL; - - return gf_strdup (master+1); -} - -int -glusterd_gsync_get_pid_file (char *pidfile, char *master, char *slave) -{ - FILE *in = NULL; - char buff[PATH_MAX] = {0, }; - char cmd[PATH_MAX] = {0, }; - char *ptr = NULL; - char buffer[PATH_MAX] = {0, }; - char pidfolder[PATH_MAX] = {0, }; - glusterd_conf_t *priv = NULL; - int ret = 0; - - GF_ASSERT (THIS); - - priv = THIS->private; - - snprintf (cmd, PATH_MAX, GSYNCD_PREFIX"/gsyncd --canonicalize-escape-url" - " %s %s", master, slave); - if (!(in = popen(cmd, "r"))) { - gf_log ("", GF_LOG_ERROR, "popen failed"); - return -1; - } - - ptr = fgets(buff, sizeof(buff), in); - if (ptr) { - buff[strlen(buff)-1]='\0'; //strip off \n - snprintf (buffer, PATH_MAX, "%s/gsync/%s", priv->workdir, buff); - strncpy (pidfolder, buffer, PATH_MAX); - } else { - ret = -1; - goto out; - } - - memset (buff, 0, PATH_MAX); - memset (buffer, 0, PATH_MAX); - - ptr = fgets(buff, sizeof(buff), in); - if (ptr) { - buff[strlen(buff)-1]='\0'; //strip off \n - snprintf (buffer, PATH_MAX, "%s/%s.pid", pidfolder, buff); - strncpy (pidfile, buffer, PATH_MAX); - } +static int +glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) +{ + int ret = -1; + uint32_t cmd = 0; + char msg[2048] = {0,}; + char *volname = NULL; + char *brick = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; + dict_t *vol_opts = NULL; + gf_boolean_t nfs_disabled = _gf_false; + gf_boolean_t shd_enabled = _gf_true; - out: - ret |= pclose (in); + GF_ASSERT (dict); + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT(priv); + ret = dict_get_uint32 (dict, "cmd", &cmd); if (ret) - gf_log ("", GF_LOG_ERROR, "popen failed"); - - return ret ? -1 : 0; -} - -/* status: return 0 when gsync is running - * return -1 when not running - */ -int -gsync_status (char *master, char *slave, int *status) -{ - int ret = -1; - char pidfile[PATH_MAX] = {0,}; - FILE *file = NULL; - - GF_VALIDATE_OR_GOTO ("gsync", master, out); - GF_VALIDATE_OR_GOTO ("gsync", slave, out); - GF_VALIDATE_OR_GOTO ("gsync", status, out); - - ret = glusterd_gsync_get_pid_file (pidfile, master, slave); - if (ret == -1) { - ret = -1; - gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); goto out; - } - - file = fopen (pidfile, "r+"); - if (file) { - ret = lockf (fileno (file), F_TEST, 0); - if (ret == 0) - *status = -1; - else - *status = 0; - } else - *status = -1; - ret = 0; -out: - return ret; -} - -int -gsync_validate_config_type (int32_t config_type) -{ - switch (config_type) { - case GF_GSYNC_OPTION_TYPE_CONFIG_SET: - case GF_GSYNC_OPTION_TYPE_CONFIG_DEL: - case GF_GSYNC_OPTION_TYPE_CONFIG_GET: - case GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL:return 0; - default: return -1; - } - return 0; -} - - -int32_t -glusterd_gsync_volinfo_dict_set (glusterd_volinfo_t *volinfo, - char *key, char *value) -{ - int32_t ret = -1; - char *gsync_status = NULL; - gsync_status = gf_strdup (value); - if (!gsync_status) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + if (cmd & GF_CLI_STATUS_ALL) goto out; - } - ret = dict_set_dynstr (volinfo->dict, key, gsync_status); + ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set dict"); - goto out; - } - - ret = 0; -out: - return 0; -} - -int -gsync_validate_config_option (dict_t *dict, int32_t config_type, - char **op_errstr) -{ - int ret = -1; - int i = 0; - char *op_name = NULL; - - if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL) - return 0; - - ret = dict_get_str (dict, "op_name", &op_name); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "option not specified"); - *op_errstr = gf_strdup ("Please specify the option"); + gf_log (THIS->name, GF_LOG_ERROR, + "Unable to get volume name"); goto out; } - i = 0; - while (gsync_opname[i] != NULL) { - if (strcmp (gsync_opname[i], op_name) == 0) { - ret = 0; - goto out; - } - i++; - } - - gf_log ("", GF_LOG_WARNING, "Invalid option"); - *op_errstr = gf_strdup ("Invalid option"); - - ret = -1; - -out: - return ret; -} - -int -gsync_verify_config_options (dict_t *dict, char **op_errstr) -{ - int ret = -1; - int config_type = 0; - - GF_VALIDATE_OR_GOTO ("gsync", dict, out); - GF_VALIDATE_OR_GOTO ("gsync", op_errstr, out); - - ret = dict_get_int32 (dict, "config_type", &config_type); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "config type is missing"); - *op_errstr = gf_strdup ("config-type missing"); - goto out; - } - - ret = gsync_validate_config_type (config_type); - if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "Invalid config type"); - *op_errstr = gf_strdup ("Invalid config type"); - goto out; - } - - ret = gsync_validate_config_option (dict, config_type, op_errstr); - if (ret < 0) - goto out; - - ret = 0; -out: - return ret; -} - -static int -glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) -{ - int ret = 0; - int type = 0; - int status = 0; - dict_t *ctx = NULL; - char *volname = NULL; - char *master = NULL; - char *slave = NULL; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - - ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); - if (!ctx) { - gf_log ("gsync", GF_LOG_DEBUG, "gsync command doesn't " - "correspond to this glusterd"); - goto out; - } - - ret = dict_get_str (dict, "master", &master); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "master not found"); - *op_errstr = gf_strdup ("master not found"); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "slave not found"); - *op_errstr = gf_strdup ("slave not found"); - ret = -1; - goto out; - } - - volname = volname_from_master (master); - if (volname == NULL) { - gf_log ("", GF_LOG_WARNING, "volname couldn't be found"); - *op_errstr = gf_strdup ("volname not found"); + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof(msg), "Volume %s does not exist", + volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); ret = -1; goto out; } - exists = glusterd_check_volume_exists (volname); - if (!exists) { - gf_log ("", GF_LOG_WARNING, "volname doesnot exist"); - *op_errstr = gf_strdup ("volname doesnot exist"); - ret = -1; + ret = glusterd_validate_volume_id (dict, volinfo); + if (ret) goto out; - } - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "command type not found"); - *op_errstr = gf_strdup ("command unsuccessful"); + ret = glusterd_is_volume_started (volinfo); + if (!ret) { + snprintf (msg, sizeof (msg), "Volume %s is not started", + volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); ret = -1; goto out; } - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_WARNING, "volinfo not found " - "for %s", volname); - *op_errstr = gf_strdup ("command unsuccessful"); - ret = -1; - goto out; - } + vol_opts = volinfo->dict; - if (type == GF_GSYNC_OPTION_TYPE_START) { - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - gf_log ("", GF_LOG_WARNING, "%s volume not started", - volname); - *op_errstr = gf_strdup ("please start the volume"); + if ((cmd & GF_CLI_STATUS_NFS) != 0) { + nfs_disabled = dict_get_str_boolean (vol_opts, "nfs.disable", + _gf_false); + if (nfs_disabled) { ret = -1; + snprintf (msg, sizeof (msg), + "NFS server is disabled for volume %s", + volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); goto out; } - //check if the gsync is already started - ret = gsync_status (master, slave, &status); - if (ret == 0 && status == 0) { - gf_log ("", GF_LOG_WARNING, "gsync already started"); - *op_errstr = gf_strdup ("gsync already started"); + } else if ((cmd & GF_CLI_STATUS_SHD) != 0) { + if (!glusterd_is_volume_replicate (volinfo)) { ret = -1; - goto out; - } else if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "gsync start validation " - " failed"); - *op_errstr = gf_strdup ("command to failed, please " - "check the log file"); + snprintf (msg, sizeof (msg), + "Volume %s is not of type replicate", + volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); goto out; } - ret = 0; - goto out; - } - if (type == GF_GSYNC_OPTION_TYPE_STOP) { - ret = gsync_status (master, slave, &status); - if (ret == 0 && status == -1) { - gf_log ("", GF_LOG_WARNING, "gsync not running"); - *op_errstr = gf_strdup ("gsync not running"); - glusterd_gsync_volinfo_dict_set (volinfo, - "features.marker-gsync", "off"); + shd_enabled = dict_get_str_boolean (vol_opts, + "cluster.self-heal-daemon", + _gf_true); + if (!shd_enabled) { ret = -1; - goto out; - } else if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "gsync stop validation " - " failed"); - *op_errstr = gf_strdup ("command failed, please " - "check the log file"); + snprintf (msg, sizeof (msg), + "Self-heal Daemon is disabled for volume %s", + volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); goto out; } - ret = 0; - goto out; - } - if (type == GF_GSYNC_OPTION_TYPE_CONFIGURE) { - ret = gsync_verify_config_options (dict, op_errstr); - if (ret < 0) + } else if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brick); + if (ret) goto out; + + ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, + &brickinfo); + if (ret) { + snprintf (msg, sizeof(msg), "No brick %s in" + " volume %s", brick, volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + + ret = -1; + goto out; + } } ret = 0; -out: - if (volname) - GF_FREE (volname); + out: + if (ret) { + if (msg[0] != '\0') + *op_errstr = gf_strdup (msg); + else + *op_errstr = gf_strdup ("Validation Failed for Status"); + } + + gf_log (THIS->name, GF_LOG_DEBUG, "Returning: %d", ret); return ret; } + static gf_boolean_t glusterd_is_profile_on (glusterd_volinfo_t *volinfo) { int ret = -1; - char *latency_key = NULL; - char *fd_stats_key = NULL; gf_boolean_t is_latency_on = _gf_false; gf_boolean_t is_fd_stats_on = _gf_false; GF_ASSERT (volinfo); - latency_key = "diagnostics.latency-measurement"; - fd_stats_key = "diagnostics.dump-fd-stats"; - ret = dict_get_str_boolean (volinfo->dict, fd_stats_key, - _gf_false); + ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_CNT_FOP_HITS); if (ret != -1) is_fd_stats_on = ret; - ret = dict_get_str_boolean (volinfo->dict, latency_key, - _gf_false); + ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_LAT_MEASUREMENT); if (ret != -1) is_latency_on = ret; if ((_gf_true == is_latency_on) && @@ -2068,6 +1209,10 @@ glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) goto out; } + ret = glusterd_validate_volume_id (dict, volinfo); + if (ret) + goto out; + ret = dict_get_int32 (dict, "op", &stats_op); if (ret) { snprintf (msg, sizeof (msg), "Volume profile op get failed"); @@ -2081,6 +1226,7 @@ glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) ret = -1; goto out; } + } if ((GF_CLI_STATS_STOP == stats_op) || (GF_CLI_STATS_INFO == stats_op)) { @@ -2088,6 +1234,7 @@ glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) snprintf (msg, sizeof (msg), "Profile on Volume %s is" " not started", volinfo->volname); ret = -1; + goto out; } } @@ -2111,1437 +1258,83 @@ out: return ret; } -static int -glusterd_op_create_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - xlator_t *this = NULL; - char *brick = NULL; - int32_t count = 0; - int32_t i = 1; - char *bricks = NULL; - char *brick_list = NULL; - char *free_ptr = NULL; - char *saveptr = NULL; - int32_t sub_count = 0; - char *trans_type = NULL; - char *str = NULL; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - ret = glusterd_volinfo_new (&volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); - GF_ASSERT (volinfo->volname); - - ret = dict_get_int32 (dict, "type", &volinfo->type); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get type"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &volinfo->brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - ret = dict_get_int32 (dict, "port", &volinfo->port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get port"); - goto out; - } - - count = volinfo->brick_count; - - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } - - if (GF_CLUSTER_TYPE_REPLICATE == volinfo->type) { - ret = dict_get_int32 (dict, "replica-count", - &sub_count); - if (ret) - goto out; - } else if (GF_CLUSTER_TYPE_STRIPE == volinfo->type) { - ret = dict_get_int32 (dict, "stripe-count", - &sub_count); - if (ret) - goto out; - } - - ret = dict_get_str (dict, "transport", &trans_type); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get transport"); - goto out; - } - - ret = dict_get_str (dict, "volume-id", &str); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume-id"); - goto out; - } - ret = uuid_parse (str, volinfo->volume_id); - if (ret) { - gf_log ("", GF_LOG_ERROR, "unable to parse uuid %s", str); - goto out; - } - - if (strcasecmp (trans_type, "rdma") == 0) { - volinfo->transport_type = GF_TRANSPORT_RDMA; - } else if (strcasecmp (trans_type, "tcp") == 0) { - volinfo->transport_type = GF_TRANSPORT_TCP; - } else { - volinfo->transport_type = GF_TRANSPORT_BOTH_TCP_RDMA; - } - - volinfo->sub_count = sub_count; - - if (bricks) { - brick_list = gf_strdup (bricks); - free_ptr = brick_list; - } - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - while ( i <= count) { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) - goto out; - - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - list_add_tail (&brickinfo->brick_list, &volinfo->bricks); - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - *op_errstr = gf_strdup ("Failed to store the Volume information"); - goto out; - } - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - *op_errstr = gf_strdup ("Failed to create volume files"); - goto out; - } - - ret = glusterd_volume_compute_cksum (volinfo); - if (ret) { - *op_errstr = gf_strdup ("Failed to compute checksum of volume"); - goto out; - } - - volinfo->defrag_status = 0; - list_add_tail (&volinfo->vol_list, &priv->volumes); -out: - if (free_ptr) - GF_FREE(free_ptr); - - return ret; -} - -static int -glusterd_op_add_brick (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - xlator_t *this = NULL; - char *bricks = NULL; - int32_t count = 0; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } - - ret = glusterd_op_perform_add_bricks (volinfo, count, bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to add bricks"); - goto out; - } - - volinfo->defrag_status = 0; - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - -out: - return ret; -} static int -rb_regenerate_volfiles (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *brickinfo, - int32_t pump_needed) -{ - dict_t *dict = NULL; - int ret = 0; - - dict = volinfo->dict; - - gf_log ("", GF_LOG_DEBUG, - "attempting to set pump value=%d", pump_needed); - - ret = dict_set_int32 (dict, "enable-pump", pump_needed); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "could not dict_set enable-pump"); - goto out; - } - - ret = glusterd_create_rb_volfiles (volinfo, brickinfo); - -out: - return ret; -} - -static int -rb_src_brick_restart (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - int activate_pump) +_delete_reconfig_opt (dict_t *this, char *key, data_t *value, void *data) { - int ret = 0; - - gf_log ("", GF_LOG_DEBUG, - "Attempting to kill src"); - - ret = glusterd_nfs_server_stop (); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to stop nfs, ret: %d", - ret); - } - - ret = glusterd_volume_stop_glusterfs (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to stop " - "glusterfs, ret: %d", ret); - goto out; - } + int32_t *is_force = 0; - glusterd_delete_volfile (volinfo, src_brickinfo); + GF_ASSERT (data); + is_force = (int32_t*)data; - if (activate_pump) { - ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 1); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not regenerate volfiles with pump"); - goto out; - } - } else { - ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 0); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not regenerate volfiles without pump"); + if (*is_force != 1) { + if (_gf_true == glusterd_check_voloption_flags (key, + OPT_FLAG_FORCE)) { + /* indicate to caller that we don't set the option + * due to being protected + */ + *is_force = *is_force | GD_OP_PROTECTED; goto out; + } else { + *is_force = *is_force | GD_OP_UNPROTECTED; } - - } - - sleep (2); - ret = glusterd_volume_start_glusterfs (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to start " - "glusterfs, ret: %d", ret); - goto out; - } - -out: - ret = glusterd_nfs_server_start (); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to start nfs, ret: %d", - ret); - } - return ret; -} - -static int -rb_send_xattr_command (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo, - const char *xattr_key, - const char *value) -{ - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - struct stat buf; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Could not send " - " %s command", xattr_key); - goto out; - } - - ret = sys_lsetxattr (mount_point_path, xattr_key, - value, - strlen (value) + 1, - 0); - - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "setxattr failed"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *brickinfo) -{ - glusterd_conf_t *priv = NULL; - char cmd_str[8192] = {0,}; - int ret = -1; - int32_t port = 0; - - priv = THIS->private; - - port = pmap_registry_alloc (THIS); - brickinfo->port = port; - - GF_ASSERT (port); - - snprintf (cmd_str, 8192, - "%s/sbin/glusterfs -f %s/vols/%s/%s -p %s/vols/%s/%s " - "--xlator-option src-server.listen-port=%d", - GFS_PREFIX, priv->workdir, volinfo->volname, - RB_DSTBRICKVOL_FILENAME, - priv->workdir, volinfo->volname, - RB_DSTBRICK_PIDFILE, - port); - - ret = gf_system (cmd_str); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not start glusterfs"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "Successfully started glusterfs: brick=%s:%s", - brickinfo->hostname, brickinfo->path); - - ret = 0; - -out: - return ret; -} - -static int -rb_spawn_glusterfs_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *brickinfo) -{ - glusterd_conf_t *priv = NULL; - char cmd_str[8192] = {0,}; - struct stat buf; - int ret = -1; - - priv = THIS->private; - - snprintf (cmd_str, 4096, - "%s/sbin/glusterfs -f %s/vols/%s/%s %s/vols/%s/%s", - GFS_PREFIX, priv->workdir, volinfo->volname, - RB_CLIENTVOL_FILENAME, - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = gf_system (cmd_str); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not start glusterfs"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "Successfully started glusterfs: brick=%s:%s", - brickinfo->hostname, brickinfo->path); - - memset (cmd_str, 0, sizeof (cmd_str)); - - snprintf (cmd_str, 4096, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = stat (cmd_str, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat on mountpoint failed"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "stat on mountpoint succeeded"); - - ret = 0; - -out: - return ret; -} - -static const char *client_volfile_str = "volume mnt-client\n" - " type protocol/client\n" - " option remote-host %s\n" - " option remote-subvolume %s\n" - " option remote-port %d\n" - "end-volume\n" - "volume mnt-wb\n" - " type performance/write-behind\n" - " subvolumes mnt-client\n" - "end-volume\n"; - -static int -rb_generate_client_volfile (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - FILE *file = NULL; - char filename[PATH_MAX]; - int ret = -1; - - priv = THIS->private; - - gf_log ("", GF_LOG_DEBUG, - "Creating volfile"); - - snprintf (filename, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENTVOL_FILENAME); - - file = fopen (filename, "w+"); - if (!file) { - gf_log ("", GF_LOG_DEBUG, - "Open of volfile failed"); - ret = -1; - goto out; - } - - GF_ASSERT (src_brickinfo->port); - - fprintf (file, client_volfile_str, src_brickinfo->hostname, - src_brickinfo->path, src_brickinfo->port); - - fclose (file); - - ret = 0; - -out: - return ret; -} - -static const char *dst_brick_volfile_str = "volume src-posix\n" - " type storage/posix\n" - " option directory %s\n" - "end-volume\n" - "volume %s\n" - " type features/locks\n" - " subvolumes src-posix\n" - "end-volume\n" - "volume src-server\n" - " type protocol/server\n" - " option auth.addr.%s.allow *\n" - " option transport-type tcp\n" - " subvolumes %s\n" - "end-volume\n"; - -static int -rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - glusterd_conf_t *priv = NULL; - FILE *file = NULL; - char filename[PATH_MAX]; - int ret = -1; - - priv = THIS->private; - - gf_log ("", GF_LOG_DEBUG, - "Creating volfile"); - - snprintf (filename, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_DSTBRICKVOL_FILENAME); - - file = fopen (filename, "w+"); - if (!file) { - gf_log ("", GF_LOG_DEBUG, - "Open of volfile failed"); - ret = -1; - goto out; - } - - fprintf (file, dst_brick_volfile_str, dst_brickinfo->path, - dst_brickinfo->path, dst_brickinfo->path, - dst_brickinfo->path); - - fclose (file); - - ret = 0; - -out: - return ret; -} - -static int -rb_mountpoint_mkdir (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = mkdir (mount_point_path, 0777); - if (ret && (errno != EEXIST)) { - gf_log ("", GF_LOG_DEBUG, "mkdir failed, errno: %d", - errno); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_mountpoint_rmdir (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = rmdir (mount_point_path); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "rmdir failed"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_destroy_maintenance_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - glusterd_conf_t *priv = NULL; - char cmd_str[8192] = {0,}; - char filename[PATH_MAX] = {0,}; - struct stat buf; - char mount_point_path[PATH_MAX] = {0,}; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Cannot destroy maintenance " - "client"); - goto out; - } - - snprintf (cmd_str, 8192, "/bin/umount -f %s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = gf_system (cmd_str); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "umount failed on maintenance client"); - goto out; - } - - ret = rb_mountpoint_rmdir (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "rmdir of mountpoint failed"); - goto out; - } - - snprintf (filename, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENTVOL_FILENAME); - - ret = unlink (filename); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "unlink failed"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static int -rb_spawn_maintenance_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) -{ - int ret = -1; - - ret = rb_generate_client_volfile (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to generate client " - "volfile"); - goto out; - } - - ret = rb_mountpoint_mkdir (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to mkdir " - "mountpoint"); - goto out; - } - - ret = rb_spawn_glusterfs_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); - goto out; - } - - ret = 0; -out: - return ret; -} - -static int -rb_spawn_destination_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) - -{ - int ret = -1; - - ret = rb_generate_dst_brick_volfile (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to generate client " - "volfile"); - goto out; - } - - ret = rb_spawn_dst_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); - goto out; - } - - ret = 0; -out: - return ret; -} - -static int -rb_do_operation_start (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - char start_value[8192] = {0,}; - int ret = -1; - - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending start xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - snprintf (start_value, 8192, "%s:%s:%d", - dst_brickinfo->hostname, - dst_brickinfo->path, - dst_brickinfo->port); - - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_START_CMD, - start_value); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - ret = 0; - -out: - return ret; -} - -static int -rb_do_operation_pause (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - - gf_log ("", GF_LOG_NORMAL, - "replace-brick send pause xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_PAUSE_CMD, - "jargon"); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; - -out: - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - ret = rb_src_brick_restart (volinfo, src_brickinfo, - 0); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not restart src-brick"); - } - } - return ret; -} - -static int -rb_kill_destination_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - glusterd_conf_t *priv = NULL; - char pidfile[PATH_MAX] = {0,}; - - priv = THIS->private; - - snprintf (pidfile, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_DSTBRICK_PIDFILE); - - return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_true); -} - -static int -rb_do_operation_abort (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending abort xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; } - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_ABORT_CMD, - "jargon"); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; - + gf_log ("", GF_LOG_DEBUG, "deleting dict with key=%s,value=%s", + key, value->data); + dict_del (this, key); out: - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - ret = rb_src_brick_restart (volinfo, src_brickinfo, - 0); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not restart src-brick"); - } - } - return ret; + return 0; } - static int -rb_get_xattr_command (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo, - const char *xattr_key, - char *value) +_delete_reconfig_global_opt (dict_t *this, char *key, data_t *value, void *data) { - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - struct stat buf; - int ret = -1; - - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); + int32_t *is_force = 0; - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Could not send " - " %s command", xattr_key); - goto out; - } + GF_ASSERT (data); + is_force = (int32_t*)data; - ret = lgetxattr (mount_point_path, xattr_key, - value, - 8192); - - if (ret < 0) { - gf_log ("", GF_LOG_DEBUG, - "getxattr failed"); + if (strcmp (GLUSTERD_GLOBAL_OPT_VERSION, key) == 0) goto out; - } - - ret = 0; + _delete_reconfig_opt (this, key, value, data); out: - return ret; -} - -static int -rb_do_operation_status (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - char status[2048] = {0,}; - char *status_reply = NULL; - dict_t *ctx = NULL; - int ret = 0; - gf_boolean_t origin = _gf_false; - - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (!ctx) { - gf_log ("", GF_LOG_ERROR, - "Operation Context is not present"); - goto out; - } - - origin = _gf_true; - - if (origin) { - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - ret = rb_get_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_STATUS_CMD, - status); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to get status from pump"); - goto umount; - } - - gf_log ("", GF_LOG_DEBUG, - "pump status is %s", status); - - status_reply = gf_strdup (status); - if (!status_reply) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); - ret = -1; - goto umount; - } - - ret = dict_set_dynstr (ctx, "status-reply", - status_reply); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "failed to set pump status in ctx"); - - } - - umount: - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); -out: - return ret; -} - -/* Set src-brick's port number to be used in the maintainance mount - * after all commit acks are received. - */ -static int -rb_update_srcbrick_port (glusterd_brickinfo_t *src_brickinfo, dict_t *rsp_dict, - dict_t *req_dict, int32_t replace_op) -{ - xlator_t *this = NULL; - dict_t *ctx = NULL; - int ret = 0; - int dict_ret = 0; - int src_port = 0; - - this = THIS; - - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - dict_ret = dict_get_int32 (req_dict, "src-brick-port", &src_port); - if (src_port) - src_brickinfo->port = src_port; - } - - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - gf_log ("", GF_LOG_NORMAL, - "adding src-brick port no"); - - src_brickinfo->port = pmap_registry_search (this, - src_brickinfo->path, GF_PMAP_PORT_BRICKSERVER); - if (!src_brickinfo->port && - replace_op != GF_REPLACE_OP_COMMIT_FORCE ) { - gf_log ("", GF_LOG_ERROR, - "Src brick port not available"); - ret = -1; - goto out; - } - - if (rsp_dict) { - ret = dict_set_int32 (rsp_dict, "src-brick-port", src_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set src-brick port no"); - goto out; - } - } - - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - ret = dict_set_int32 (ctx, "src-brick-port", src_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set src-brick port no"); - goto out; - } - } - - } - -out: - return ret; - -} - -static int -rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict, - dict_t *req_dict, int32_t replace_op) -{ - dict_t *ctx = NULL; - int ret = 0; - int dict_ret = 0; - int dst_port = 0; - - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port); - if (dst_port) - dst_brickinfo->port = dst_port; - - } - - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_NORMAL, - "adding dst-brick port no"); - - if (rsp_dict) { - ret = dict_set_int32 (rsp_dict, "dst-brick-port", - dst_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set dst-brick port no in rsp dict"); - goto out; - } - } - - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - ret = dict_set_int32 (ctx, "dst-brick-port", - dst_brickinfo->port); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not set dst-brick port no"); - goto out; - } - } - } -out: - return ret; + return 0; } - - static int -glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) +glusterd_options_reset (glusterd_volinfo_t *volinfo, char *key, + int32_t *is_force) { - int ret = 0; - dict_t *ctx = NULL; - int replace_op = 0; - glusterd_volinfo_t *volinfo = NULL; - char *volname = NULL; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - char *src_brick = NULL; - char *dst_brick = NULL; - glusterd_brickinfo_t *src_brickinfo = NULL; - glusterd_brickinfo_t *dst_brickinfo = NULL; + int ret = 0; + data_t *value = NULL; + char *key_fixed = NULL; + xlator_t *this = NULL; this = THIS; GF_ASSERT (this); + GF_ASSERT (volinfo->dict); + GF_ASSERT (key); - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "src-brick", &src_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); - goto out; - } - - gf_log (this->name, GF_LOG_DEBUG, - "src brick=%s", src_brick); - - ret = dict_get_str (dict, "dst-brick", &dst_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); - goto out; - } - - gf_log (this->name, GF_LOG_DEBUG, - "dst brick=%s", dst_brick); - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); - if (ret) { - gf_log (this->name, GF_LOG_DEBUG, - "dict_get on operation failed"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); - goto out; - } - - - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get " - "replace brick destination brickinfo"); - goto out; - } - - ret = glusterd_resolve_brick (dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); - goto out; - } - - ret = rb_update_srcbrick_port (src_brickinfo, rsp_dict, - dict, replace_op); - if (ret) - goto out; - - if ((GF_REPLACE_OP_START != replace_op)) { - ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, - dict, replace_op); - if (ret) - goto out; - } - - switch (replace_op) { - case GF_REPLACE_OP_START: - { - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_NORMAL, - "I AM THE DESTINATION HOST"); - if (!glusterd_is_rb_paused (volinfo)) { - ret = rb_spawn_destination_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to spawn destination brick"); - goto out; - } - } else { - gf_log ("", GF_LOG_ERROR, "Replace brick is already " - "started=> no need to restart dst brick "); - } - } - - - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - ret = rb_src_brick_restart (volinfo, src_brickinfo, - 1); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not restart src-brick"); - goto out; - } - } - - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_NORMAL, - "adding dst-brick port no"); - - ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, - dict, replace_op); - if (ret) - goto out; - } - - glusterd_set_rb_status (volinfo, GF_RB_STATUS_STARTED); - break; - } - - case GF_REPLACE_OP_COMMIT: - case GF_REPLACE_OP_COMMIT_FORCE: - { - ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); - gf_log ("", GF_LOG_DEBUG, - "Received commit - will be adding dst brick and " - "removing src brick"); - - if (!glusterd_is_local_addr (dst_brickinfo->hostname) && - replace_op != GF_REPLACE_OP_COMMIT_FORCE) { - gf_log ("", GF_LOG_NORMAL, - "I AM THE DESTINATION HOST"); - ret = rb_kill_destination_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to kill destination brick"); - goto out; - } - } - - if (ret) { - gf_log ("", GF_LOG_CRITICAL, - "Unable to cleanup dst brick"); + if (!strncmp(key, "all", 3)) + dict_foreach (volinfo->dict, _delete_reconfig_opt, is_force); + else { + value = dict_get (volinfo->dict, key); + if (!value) { + gf_log (this->name, GF_LOG_DEBUG, + "no value set for option %s", key); goto out; } - - - ret = glusterd_nfs_server_stop (); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to stop nfs server, ret: %d", ret); - } - - ret = glusterd_op_perform_replace_brick (volinfo, src_brick, - dst_brick); - if (ret) { - gf_log ("", GF_LOG_CRITICAL, "Unable to add " - "dst-brick: %s to volume: %s", - dst_brick, volinfo->volname); - (void) glusterd_check_generate_start_nfs (); - goto out; - } - - volinfo->defrag_status = 0; - - ret = glusterd_check_generate_start_nfs (); - if (ret) { - gf_log ("", GF_LOG_CRITICAL, - "Failed to generate nfs volume file"); - } - - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - - if (ret) - goto out; - - ret = glusterd_fetchspec_notify (THIS); - glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); - glusterd_brickinfo_delete (volinfo->dst_brick); - volinfo->src_brick = volinfo->dst_brick = NULL; - } - break; - - case GF_REPLACE_OP_PAUSE: - { - gf_log ("", GF_LOG_DEBUG, - "Received pause - doing nothing"); - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - ret = rb_do_operation_pause (volinfo, src_brickinfo, - dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Pause operation failed"); - goto out; - } - } - - glusterd_set_rb_status (volinfo, GF_RB_STATUS_PAUSED); - } - break; - - case GF_REPLACE_OP_ABORT: - { - - ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); - if (ret) { - gf_log ("", GF_LOG_CRITICAL, "Unable to disable pump"); - } - - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_NORMAL, - "I AM THE DESTINATION HOST"); - ret = rb_kill_destination_brick (volinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to kill destination brick"); - goto out; - } - } - - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - ret = rb_do_operation_abort (volinfo, src_brickinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Abort operation failed"); - goto out; - } - } - glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); - glusterd_brickinfo_delete (volinfo->dst_brick); - volinfo->src_brick = volinfo->dst_brick = NULL; - } - break; - - case GF_REPLACE_OP_STATUS: - { - gf_log ("", GF_LOG_DEBUG, - "received status - doing nothing"); - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - ret = rb_do_operation_status (volinfo, src_brickinfo, - dst_brickinfo); - if (ret) - goto out; - } - - } - break; - - default: - ret = -1; - goto out; - } - - if (ret) - goto out; - -out: - return ret; -} - -void -_delete_reconfig_opt (dict_t *this, char *key, data_t *value, void *data) -{ - - int exists = 0; - - exists = glusterd_check_option_exists(key, NULL); - - if (exists == 1) { - gf_log ("", GF_LOG_DEBUG, "deleting dict with key=%s,value=%s", - key, value->data); - dict_del (this, key); + _delete_reconfig_opt (volinfo->dict, key, value, is_force); } -} - -int -glusterd_options_reset (glusterd_volinfo_t *volinfo) -{ - int ret = 0; - - gf_log ("", GF_LOG_DEBUG, "Received volume set reset command"); - - GF_ASSERT (volinfo->dict); - - dict_foreach (volinfo->dict, _delete_reconfig_opt, volinfo->dict); + gd_update_volume_op_versions (volinfo); ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" - " 'volume set'"); + gf_log (this->name, GF_LOG_ERROR, "Unable to create volfile for" + " 'volume reset'"); ret = -1; goto out; } @@ -3550,1129 +1343,311 @@ glusterd_options_reset (glusterd_volinfo_t *volinfo) if (ret) goto out; - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - if (ret) - goto out; + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_nodesvcs_handle_reconfigure (volinfo); + if (ret) + goto out; + } ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + GF_FREE (key_fixed); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } - static int -glusterd_op_reset_volume (dict_t *dict) +glusterd_op_reset_all_volume_options (xlator_t *this, dict_t *dict) { - glusterd_volinfo_t *volinfo = NULL; - int ret = -1; - char *volname = NULL; + char *key = NULL; + char *key_fixed = NULL; + int ret = -1; + int32_t is_force = 0; + glusterd_conf_t *conf = NULL; + dict_t *dup_opt = NULL; + gf_boolean_t all = _gf_false; + char *next_version = NULL; + gf_boolean_t quorum_action = _gf_false; - ret = dict_get_str (dict, "volname", &volname); + conf = this->private; + ret = dict_get_str (dict, "key", &key); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = glusterd_options_reset (volinfo); - -out: - gf_log ("", GF_LOG_DEBUG, "'volume reset' returning %d", ret); - return ret; - -} - -int -stop_gsync (char *master, char *slave, char **op_errstr) -{ - int32_t ret = -1; - int32_t status = 0; - pid_t pid = 0; - FILE *file = NULL; - char pidfile[PATH_MAX] = {0,}; - char buf [1024] = {0,}; - int i = 0; - - ret = gsync_status (master, slave, &status); - if (ret == 0 && status == -1) { - gf_log ("", GF_LOG_WARNING, "gsync is not running"); - *op_errstr = gf_strdup ("gsync is not running"); - ret = -1; - goto out; - } else if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "gsync stop validation " - " failed"); - *op_errstr = gf_strdup ("command to failed, please " - "check the log file"); + gf_log (this->name, GF_LOG_ERROR, "Failed to get key"); goto out; } - ret = glusterd_gsync_get_pid_file (pidfile, master, slave); - if (ret == -1) { - ret = -1; - gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); - goto out; - } - - file = fopen (pidfile, "r+"); - if (!file) { - gf_log ("", GF_LOG_WARNING, "cannot open pid file"); - *op_errstr = gf_strdup ("stop unsuccessful"); - ret = -1; - goto out; - } + ret = dict_get_int32 (dict, "force", &is_force); + if (ret) + is_force = 0; - ret = read (fileno(file), buf, 1024); - if (ret > 0) { - pid = strtol (buf, NULL, 10); - ret = kill (-pid, SIGTERM); - if (ret) { - gf_log ("", GF_LOG_WARNING, - "failed to stop gsyncd"); + if (strcmp (key, "all")) { + ret = glusterd_check_option_exists (key, &key_fixed); + if (ret <= 0) { + gf_log (this->name, GF_LOG_ERROR, "Option %s does not " + "exist", key); + ret = -1; goto out; } - for (i = 0; i < 20; i++) { - if (gsync_status (master, slave, &status) == -1 || - status == -1) { - /* monitor gsyncd is dead but worker may - * still be alive, give some more time - * before SIGKILL (hack) - */ - sleep (0.05); - break; - } - sleep (0.05); - } - kill (-pid, SIGKILL); - unlink (pidfile); - } - ret = 0; - - *op_errstr = gf_strdup ("gsync stopped successfully"); - -out: - return ret; -} - -int -gsync_config_set (char *master, char *slave, - dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - char *op_name = NULL; - char *op_value = NULL; - char cmd[1024] = {0,}; - glusterd_conf_t *priv = NULL; - - if (THIS == NULL) { - gf_log ("", GF_LOG_ERROR, "THIS of glusterd not present"); - *op_errstr = gf_strdup ("Error! Glusterd cannot start gsyncd"); - goto out; - } - - priv = THIS->private; - - if (priv == NULL) { - gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); - *op_errstr = gf_strdup ("Error! Glusterd cannot start gsyncd"); - goto out; - } - - ret = dict_get_str (dict, "op_name", &op_name); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "failed to get the " - "option name for %s %s", master, slave); - - *op_errstr = gf_strdup ("configure command failed, " - "please check the log-file\n"); - goto out; - } - - ret = dict_get_str (dict, "op_value", &op_value); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "failed to get " - "the option value for %s %s", - master, slave); - - *op_errstr = gf_strdup ("configure command " - "failed, please check " - "the log-file\n"); - goto out; - } - - ret = snprintf (cmd, 1024, GSYNCD_PREFIX"/gsyncd -c %s/%s %s %s" - " --config-set %s %s", priv->workdir, - GSYNC_CONF, master, slave, op_name, op_value); - if (ret <= 0) { - gf_log ("", GF_LOG_WARNING, "failed to " - "construct the gsyncd command"); - - *op_errstr = gf_strdup ("configure command failed, " - "please check the log-file\n"); - goto out; - } - - ret = system (cmd); - if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "gsyncd failed to " - "set %s option for %s %s peer", - op_name, master, slave); - - *op_errstr = gf_strdup ("configure command " - "failed, please check " - "the log-file\n"); - goto out; - } - ret = 0; - *op_errstr = gf_strdup ("config-set successful"); - -out: - return ret; -} - -int -gsync_config_del (char *master, char *slave, - dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - char *op_name = NULL; - char cmd[PATH_MAX] = {0,}; - glusterd_conf_t *priv = NULL; - - if (THIS == NULL) { - gf_log ("", GF_LOG_ERROR, "THIS of glusterd not present"); - *op_errstr = gf_strdup ("Error! Glusterd cannot start gsyncd"); - goto out; - } - - priv = THIS->private; - - if (priv == NULL) { - gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); - *op_errstr = gf_strdup ("Error! Glusterd cannot start gsyncd"); - goto out; - } - - ret = dict_get_str (dict, "op_name", &op_name); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "failed to get " - "the option for %s %s", master, slave); - - *op_errstr = gf_strdup ("configure command " - "failed, please check " - "the log-file\n"); - goto out; - } - - ret = snprintf (cmd, PATH_MAX, GSYNCD_PREFIX"/gsyncd -c %s/%s %s %s" - " --config-del %s ", priv->workdir, - GSYNC_CONF, master, slave, op_name); - if (ret <= 0) { - gf_log ("", GF_LOG_WARNING, "failed to " - "construct the gsyncd command"); - *op_errstr = gf_strdup ("configure command " - "failed, please check " - "the log-file\n"); - goto out; - } - - ret = system (cmd); - if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "failed to delete " - "%s option for %s %s peer", op_name, - master, slave); - *op_errstr = gf_strdup ("configure command " - "failed, please check " - "the log-file\n"); - goto out; - } - ret = 0; - *op_errstr = gf_strdup ("config-del successful"); -out: - return ret; -} - - -int -gsync_configure (char *master, char *slave, - dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - int32_t config_type = 0; - - ret = dict_get_int32 (dict, "config_type", &config_type); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "couldn't get the " - "config-type for %s %s", master, slave); - *op_errstr = gf_strdup ("configure command failed, " - "please check the log-file\n"); - goto out; - } - - if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_SET) { - ret = gsync_config_set (master, slave, dict, op_errstr); - goto out; + } else { + all = _gf_true; } - if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_DEL) { - ret = gsync_config_del (master, slave, dict, op_errstr); - goto out; - } + if (key_fixed) + key = key_fixed; - if ((config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL) || - (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET)) + ret = -1; + dup_opt = dict_new (); + if (!dup_opt) goto out; - else { - gf_log ("", GF_LOG_WARNING, "Invalid config type"); - *op_errstr = gf_strdup ("Invalid config type"); - ret = -1; + if (!all) { + dict_copy (conf->opts, dup_opt); + dict_del (dup_opt, key); } - -out: - return ret; -} - -int -gsync_command_exec (dict_t *dict, char **op_errstr) -{ - char *master = NULL; - char *slave = NULL; - int32_t ret = -1; - int32_t type = -1; - - GF_VALIDATE_OR_GOTO ("gsync", dict, out); - GF_VALIDATE_OR_GOTO ("gsync", op_errstr, out); - - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) + ret = glusterd_get_next_global_opt_version_str (conf->opts, + &next_version); + if (ret) goto out; - ret = dict_get_str (dict, "master", &master); - if (ret < 0) + ret = dict_set_str (dup_opt, GLUSTERD_GLOBAL_OPT_VERSION, next_version); + if (ret) goto out; - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) + ret = glusterd_store_options (this, dup_opt); + if (ret) goto out; - if (type == GF_GSYNC_OPTION_TYPE_START) { - ret = 0; - goto out; - } + if (glusterd_is_quorum_changed (conf->opts, key, NULL)) + quorum_action = _gf_true; - if (type == GF_GSYNC_OPTION_TYPE_STOP) { - ret = stop_gsync (master, slave, op_errstr); + ret = dict_set_dynstr (conf->opts, GLUSTERD_GLOBAL_OPT_VERSION, + next_version); + if (ret) goto out; - } + else + next_version = NULL; - if (type == GF_GSYNC_OPTION_TYPE_CONFIGURE) { - ret = gsync_configure (master, slave, dict, op_errstr); - goto out; + if (!all) { + dict_del (conf->opts, key); } else { - gf_log ("", GF_LOG_WARNING, "Invalid config type"); - *op_errstr = gf_strdup ("Invalid config type"); - ret = -1; + dict_foreach (conf->opts, _delete_reconfig_global_opt, + &is_force); } out: + GF_FREE (key_fixed); + if (dup_opt) + dict_unref (dup_opt); + + gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret); + if (quorum_action) + glusterd_do_quorum_action (); + GF_FREE (next_version); return ret; } -int32_t -glusterd_marker_create_volfile (glusterd_volinfo_t *volinfo) +static int +glusterd_op_reset_volume (dict_t *dict, char **op_rspstr) { - int32_t ret = 0; + glusterd_volinfo_t *volinfo = NULL; + int ret = -1; + char *volname = NULL; + char *key = NULL; + char *key_fixed = NULL; + int32_t is_force = 0; + gf_boolean_t quorum_action = _gf_false; + xlator_t *this = NULL; - ret = glusterd_create_volfiles_and_notify_services (volinfo); + this = THIS; + ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile" - " for setting of marker while 'gsync start'"); - ret = -1; + gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name" ); goto out; } - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - ret = 0; -out: - return ret; -} - -int -glusterd_set_marker_gsync (char *master, char *value) -{ - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - int ret = -1; - - volname = volname_from_master (master); - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Volume not Found"); - ret = -1; + if (strcasecmp (volname, "all") == 0) { + ret = glusterd_op_reset_all_volume_options (this, dict); goto out; } - ret = glusterd_gsync_volinfo_dict_set (volinfo, - "features.marker-gsync", value); - if (ret < 0) - goto out; + ret = dict_get_int32 (dict, "force", &is_force); + if (ret) + is_force = 0; - ret = glusterd_marker_create_volfile (volinfo); + ret = dict_get_str (dict, "key", &key); if (ret) { - gf_log ("", GF_LOG_ERROR, "Setting dict failed"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get option key"); goto out; } -out: - return ret; - -} - -int -glusterd_op_gsync_set (dict_t *dict) -{ - char *master = NULL; - int32_t ret = -1; - int32_t type = -1; - dict_t *ctx = NULL; - char *gsync_status = NULL; - char *op_errstr = NULL; - - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) - goto out; - - ret = dict_get_str (dict, "master", &master); - if (ret < 0) - goto out; - - if (type == GF_GSYNC_OPTION_TYPE_START) { - gsync_status = gf_strdup ("on"); - if (gsync_status == NULL) { - ret = -1; - goto out; - } - - ret = glusterd_set_marker_gsync (master, gsync_status); - if (ret != 0) { - gf_log ("", GF_LOG_WARNING, "marker start failed"); - op_errstr = gf_strdup ("gsync start failed"); - ret = -1; - goto out; - } - } - - if (type == GF_GSYNC_OPTION_TYPE_STOP) { - gsync_status = gf_strdup ("off"); - if (gsync_status == NULL) { - ret = -1; - goto out; - } - - ret = glusterd_set_marker_gsync (master, gsync_status); - if (ret != 0) { - gf_log ("", GF_LOG_WARNING, "marker stop failed"); - op_errstr = gf_strdup ("gsync stop failed"); - ret = -1; - goto out; - } - } -out: - ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); - if (ctx) { - ret = gsync_command_exec (dict, &op_errstr); - if (op_errstr) { - ret = dict_set_str (ctx, "errstr", op_errstr); - if (ret) { - GF_FREE (op_errstr); - gf_log ("", GF_LOG_WARNING, "failed to set " - "error message in ctx"); - } - } - } - - return ret; -} - -int32_t -glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo) -{ - int32_t ret = 0; - char *quota_status = NULL; - gf_boolean_t flag = _gf_false; - - ret = glusterd_volinfo_get (volinfo, "features.quota", "a_status); + ret = glusterd_volinfo_find (volname, &volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota status"); - ret = -1; + gf_log (this->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS, + volname); goto out; } - ret = gf_string2boolean (quota_status, &flag); - if (ret != 0) - goto out; - - if (flag == _gf_false) { - gf_log ("", GF_LOG_ERROR, "first enable the quota translator"); + if (strcmp (key, "all") && + glusterd_check_option_exists (key, &key_fixed) != 1) { + gf_log (this->name, GF_LOG_ERROR, + "volinfo dict inconsistency: option %s not found", + key); ret = -1; goto out; } - ret = 0; -out: - return ret; -} - -int32_t -_glusterd_quota_remove_limits (char **quota_limits, char *path) -{ - int ret = 0; - int i = 0; - int size = 0; - int len = 0; - int pathlen = 0; - int skiplen = 0; - int flag = 0; - char *limits = NULL; - char *qlimits = NULL; - - if (*quota_limits == NULL) - return -1; - - qlimits = *quota_limits; - - pathlen = strlen (path); - - len = strlen (qlimits); - - limits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); - - if (!limits) - return -1; - - while (i < len) { - if (!memcmp ((void *) &qlimits [i], (void *)path, pathlen)) - if (qlimits [i + pathlen] == ':') - flag = 1; + if (key_fixed) + key = key_fixed; - while (qlimits [i + size] != ',' && - qlimits [i + size] != '\0') - size++; + if (glusterd_is_quorum_changed (volinfo->dict, key, NULL)) + quorum_action = _gf_true; - if (!flag) { - memcpy ((void *) &limits [i], (void *) &qlimits [i], size + 1); + ret = glusterd_options_reset (volinfo, key, &is_force); + if (ret == -1) { + gf_asprintf(op_rspstr, "Volume reset : failed"); + } else if (is_force & GD_OP_PROTECTED) { + if (is_force & GD_OP_UNPROTECTED) { + gf_asprintf (op_rspstr, "All unprotected fields were" + " reset. To reset the protected fields," + " use 'force'."); } else { - skiplen = size + 1; - size = len - i - size; - memcpy ((void *) &limits [i], (void *) &qlimits [i + skiplen], size); - break; - } - - i += size + 1; - size = 0; - } - - if (!flag) { - ret = 1; - } else { - len = strlen (limits); - - if (len == 0) { - GF_FREE (qlimits); - - *quota_limits = NULL; - - goto out; - } - - if (limits[len - 1] == ',') { - limits[len - 1] = '\0'; - len --; - } - - GF_FREE (qlimits); - - qlimits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); - - if (!qlimits) { ret = -1; - goto out; + gf_asprintf (op_rspstr, "'%s' is protected. To reset" + " use 'force'.", key); } - - memcpy ((void *) qlimits, (void *) limits, len + 1); - - *quota_limits = qlimits; - - ret = 0; } out: - if (limits) - GF_FREE (limits); + GF_FREE (key_fixed); + if (quorum_action) + glusterd_do_quorum_action (); + gf_log (this->name, GF_LOG_DEBUG, "'volume reset' returning %d", ret); return ret; } -void * -glusterd_quota_start_crawl (void *data) -{ - int32_t ret = 0; - char cmd_str [1024] = {0, }; - char *mount = NULL; - - mount = (char *) data; - - snprintf (cmd_str, 1024, "find %s", mount); - - gf_log ("quota crawl", GF_LOG_INFO, "crawl started"); - - ret = system (cmd_str); - if (ret == -1) - gf_log ("crawl", GF_LOG_ERROR, "quota crawl failed"); - - gf_log ("quota crawl", GF_LOG_INFO, "crawl ended"); - - return NULL; -} - -int32_t -glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname) -{ - pthread_t th; - int32_t ret = 0; - char mount [1024] = {0, }; - char cmd_str [1024] = {0, }; - - snprintf (mount, 1024, "%s/mount/%s", - priv->workdir, volname); - - snprintf (cmd_str, 1024, "mkdir -p %s", mount); - - ret = system (cmd_str); - if (ret == -1) { - gf_log ("glusterd", GF_LOG_DEBUG, "command: %s failed", cmd_str); - goto out; - } - - snprintf (cmd_str, 1024, "%s/sbin/glusterfs -s localhost " - "--volfile-id %s %s", GFS_PREFIX, volname, mount); - - ret = system (cmd_str); - if (ret == -1) { - gf_log("glusterd", GF_LOG_DEBUG, "command: %s failed", cmd_str); - goto out; - } - - ret = pthread_create (&th, NULL, glusterd_quota_start_crawl, mount); - if (ret) { - snprintf (cmd_str, 1024, "umount -l %s", mount); - ret = system (cmd_str); - } -out: - return ret; -} - -char * -glusterd_quota_get_limit_value (char *quota_limits, char *path) +int +glusterd_stop_bricks (glusterd_volinfo_t *volinfo) { - int32_t i, j, k, l, len; - int32_t pat_len, diff; - char *ret_str = NULL; - - len = strlen (quota_limits); - pat_len = strlen (path); - i = 0; - j = 0; - - while (i < len) { - j = i; - k = 0; - while (path [k] == quota_limits [j]) { - j++; - k++; - } - - l = j; - - while (quota_limits [j] != ',' && - quota_limits [j] != '\0') - j++; - - if (quota_limits [l] == ':' && pat_len == (l - i)) { - diff = j - i; - ret_str = GF_CALLOC (diff + 1, sizeof (char), - gf_gld_mt_char); - - strncpy (ret_str, "a_limits [i], diff); + glusterd_brickinfo_t *brickinfo = NULL; - break; - } - i = ++j; //skip ',' + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + /*TODO: Need to change @del_brick in brick_stop to _gf_true + * once we enable synctask in peer rpc prog */ + if (glusterd_brick_stop (volinfo, brickinfo, _gf_false)) + return -1; } - return ret_str; + return 0; } -char* -_glusterd_quota_get_limit_usages (glusterd_volinfo_t *volinfo, - char *path, char **op_errstr) +int +glusterd_start_bricks (glusterd_volinfo_t *volinfo) { - int32_t ret = 0; - char *quota_limits = NULL; - char *ret_str = NULL; + int ret = -1; + glusterd_brickinfo_t *brickinfo = NULL; - if (volinfo == NULL) - return NULL; - - ret = glusterd_volinfo_get (volinfo, "features.limit-usage", - "a_limits); - if (ret) - return NULL; - if (quota_limits == NULL) { - ret_str = NULL; - *op_errstr = gf_strdup ("Limits not set any directory"); - } else if (path == NULL) - ret_str = gf_strdup (quota_limits); - else - ret_str = glusterd_quota_get_limit_value (quota_limits, path); - - return ret_str; -} - -int32_t -glusterd_quota_get_limit_usages (glusterd_conf_t *priv, - glusterd_volinfo_t *volinfo, - char *volname, - dict_t *dict, - char **op_errstr) -{ - int32_t i = 0; - int32_t ret = 0; - int32_t count = 0; - char *path = NULL; - dict_t *ctx = NULL; - char cmd_str [1024] = {0, }; - char *ret_str = NULL; - - ctx = glusterd_op_get_ctx (GD_OP_QUOTA); - if (ctx == NULL) - return -1; - - ret = dict_get_int32 (dict, "count", &count); - if (ret < 0) - goto out; - - if (count == 0) { - ret_str = _glusterd_quota_get_limit_usages (volinfo, NULL, op_errstr); - } else { - i = 0; - while (count--) { - snprintf (cmd_str, 1024, "path%d", i++); - - ret = dict_get_str (dict, cmd_str, &path); - if (ret < 0) - goto out; + GF_ASSERT (volinfo); - ret_str = _glusterd_quota_get_limit_usages (volinfo, path, op_errstr); + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + ret = glusterd_brick_start (volinfo, brickinfo, _gf_false); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed to start %s:%s for %s", + brickinfo->hostname, brickinfo->path, + volinfo->volname); + goto out; } } - if (ret_str) { - ret = dict_set_dynstr (ctx, "limit_list", ret_str); - } -out: - return ret; -} - -int32_t -glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, - gf_boolean_t *crawl) -{ - int32_t ret = -1; - char *status = NULL; - char *quota_status = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", crawl, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == 0) { - *op_errstr = gf_strdup ("quota translator " - "couldnot be enabled"); - goto out; - } - - quota_status = gf_strdup ("on"); - if (!quota_status) { - gf_log ("", GF_LOG_ERROR, "memory allocation failed"); - *op_errstr = gf_strdup ("quota enable failed"); - goto out; - } - - ret = dict_set_dynstr (volinfo->dict, "features.quota", quota_status); - if (ret) { - gf_log ("", GF_LOG_ERROR, "dict set failed"); - *op_errstr = gf_strdup ("quota enable failed"); - goto out; - } - - *op_errstr = gf_strdup ("quota translator is enabled"); - - status = gf_strdup ("on"); - if (status == NULL) { - ret = -1; - goto out; - } - - *crawl = _gf_true; - ret = 0; out: return ret; } -int32_t -glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr) -{ - int32_t ret = -1; - char *quota_status = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - - quota_status = gf_strdup ("off"); - if (!quota_status) { - gf_log ("", GF_LOG_ERROR, "memory allocation failed"); - *op_errstr = gf_strdup ("quota disable failed"); +static int +glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict) +{ + char *key = NULL; + char *key_fixed = NULL; + char *value = NULL; + char *dup_value = NULL; + int ret = -1; + glusterd_conf_t *conf = NULL; + dict_t *dup_opt = NULL; + char *next_version = NULL; + gf_boolean_t quorum_action = _gf_false; + + conf = this->private; + ret = dict_get_str (dict, "key1", &key); + if (ret) goto out; - } - ret = dict_set_dynstr (volinfo->dict, "features.quota", quota_status); + ret = dict_get_str (dict, "value1", &value); if (ret) { - gf_log ("", GF_LOG_ERROR, "dict set failed"); - *op_errstr = gf_strdup ("quota disable failed"); + gf_log (this->name, GF_LOG_ERROR, + "invalid key,value pair in 'volume set'"); goto out; } - - *op_errstr = gf_strdup ("quota disabled"); - - dict_del (volinfo->dict, "features.limit-usage"); - - quota_status = gf_strdup ("off"); - if (quota_status == NULL) { + ret = glusterd_check_option_exists (key, &key_fixed); + if (ret <= 0) { + gf_log (this->name, GF_LOG_ERROR, "Invalid key %s", key); ret = -1; goto out; } -out: - return ret; -} - -int32_t -glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - char *path = NULL; - char *limit = NULL; - char *value = NULL; - char msg [1024] = {0,}; - char *quota_limits = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", dict, out); - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == -1) { - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - ret = glusterd_volinfo_get (volinfo, "features.limit-usage", - "a_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - ret = dict_get_str (dict, "limit", &limit); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - if (quota_limits) { - ret = _glusterd_quota_remove_limits ("a_limits, path); - if (ret == -1) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - } - - if (quota_limits == NULL) { - ret = gf_asprintf (&value, "%s:%s", path, limit); - if (ret == -1) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - } else { - ret = gf_asprintf (&value, "%s,%s:%s", - quota_limits, path, limit); - if (ret == -1) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - - GF_FREE (quota_limits); - } - - quota_limits = value; - - ret = dict_set_str (volinfo->dict, "features.limit-usage", - quota_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); - *op_errstr = gf_strdup ("failed to set limit"); - goto out; - } - snprintf (msg, 1024, "limit set on %s", path); - *op_errstr = gf_strdup (msg); - - ret = 0; -out: - return ret; -} - -int32_t -glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - char *quota_limits = NULL; - char *path = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", dict, out); - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + if (key_fixed) + key = key_fixed; - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == -1) + ret = -1; + dup_opt = dict_new (); + if (!dup_opt) goto out; - - ret = glusterd_volinfo_get (volinfo, "features.limit-usage", - "a_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); + dict_copy (conf->opts, dup_opt); + ret = dict_set_str (dup_opt, key, value); + if (ret) goto out; - } - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); + ret = glusterd_get_next_global_opt_version_str (conf->opts, + &next_version); + if (ret) goto out; - } - ret = _glusterd_quota_remove_limits ("a_limits, path); - if (ret == -1) + ret = dict_set_str (dup_opt, GLUSTERD_GLOBAL_OPT_VERSION, next_version); + if (ret) goto out; - if (quota_limits) { - ret = dict_set_str (volinfo->dict, "features.limit-usage", - quota_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); - goto out; - } - } else { - dict_del (volinfo->dict, "features.limit-usage"); - } - - ret = 0; - -out: - return ret; -} - - -int -glusterd_op_quota (dict_t *dict, char **op_errstr) -{ - glusterd_volinfo_t *volinfo = NULL; - int32_t ret = -1; - char *volname = NULL; - dict_t *ctx = NULL; - int type = -1; - gf_boolean_t start_crawl = _gf_false; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - - priv = THIS->private; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); + dup_value = gf_strdup (value); + if (!dup_value) goto out; - } - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + ret = glusterd_store_options (this, dup_opt); + if (ret) goto out; - } - - ret = dict_get_int32 (dict, "type", &type); - - if (type == GF_QUOTA_OPTION_TYPE_ENABLE) { - ret = glusterd_quota_enable (volinfo, op_errstr, &start_crawl); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_DISABLE) { - ret = glusterd_quota_disable (volinfo, op_errstr); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) { - ret = glusterd_quota_limit_usage (volinfo, dict, op_errstr); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_REMOVE) { - ret = glusterd_quota_remove_limits (volinfo, dict, op_errstr); - if (ret < 0) - goto out; - - goto create_vol; - } - - if (type == GF_QUOTA_OPTION_TYPE_LIST) { - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == -1) { - *op_errstr = gf_strdup ("cannot list the limits, " - "quota feature is disabled"); - goto out; - } - glusterd_quota_get_limit_usages (priv, volinfo, volname, dict, op_errstr); + if (glusterd_is_quorum_changed (conf->opts, key, value)) + quorum_action = _gf_true; + ret = dict_set_dynstr (conf->opts, GLUSTERD_GLOBAL_OPT_VERSION, + next_version); + if (ret) goto out; - } -create_vol: - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to re-create volfile for" - " 'quota'"); - ret = -1; - goto out; - } + else + next_version = NULL; - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + ret = dict_set_dynstr (conf->opts, key, dup_value); if (ret) goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - - ret = 0; - out: - if (start_crawl == _gf_true) - glusterd_quota_initiate_fs_crawl (priv, volname); - - ctx = glusterd_op_get_ctx (GD_OP_QUOTA); - if (ctx && *op_errstr) { - ret = dict_set_dynstr (ctx, "errstr", *op_errstr); - if (ret) { - GF_FREE (*op_errstr); - gf_log ("", GF_LOG_DEBUG, - "failed to set error message in ctx"); - } - *op_errstr = NULL; - } - + GF_FREE (key_fixed); + if (dup_opt) + dict_unref (dup_opt); + + gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret); + if (quorum_action) + glusterd_do_quorum_action (); + GF_FREE (next_version); return ret; } -int -glusterd_stop_bricks (glusterd_volinfo_t *volinfo) -{ - glusterd_brickinfo_t *brickinfo = NULL; - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (glusterd_brick_stop (volinfo, brickinfo)) - return -1; - } - - return 0; -} - -int -glusterd_start_bricks (glusterd_volinfo_t *volinfo) -{ - glusterd_brickinfo_t *brickinfo = NULL; - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (glusterd_brick_start (volinfo, brickinfo)) - return -1; - } - - return 0; -} - -static int -glusterd_restart_brick_servers (glusterd_volinfo_t *volinfo) -{ - if (!volinfo) - return -1; - if (glusterd_stop_bricks (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Restart Failed: Unable to " - "stop brick servers"); - return -1; - } - usleep (500000); - if (glusterd_start_bricks (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Restart Failed: Unable to " - "start brick servers"); - return -1; - } - return 0; -} - static int glusterd_op_set_volume (dict_t *dict) { @@ -4682,13 +1657,18 @@ glusterd_op_set_volume (dict_t *dict) xlator_t *this = NULL; glusterd_conf_t *priv = NULL; int count = 1; - int restart_flag = 0; - char *key = NULL; - char *key_fixed = NULL; - char *value = NULL; - char str[50] = {0, }; + char *key = NULL; + char *key_fixed = NULL; + char *value = NULL; + char str[50] = {0, }; + char *op_errstr = NULL; gf_boolean_t global_opt = _gf_false; - glusterd_volinfo_t *voliter = NULL; + gf_boolean_t global_opts_set = _gf_false; + glusterd_volinfo_t *voliter = NULL; + int32_t dict_count = 0; + gf_boolean_t check_op_version = _gf_false; + uint32_t new_op_version = 0; + gf_boolean_t quorum_action = _gf_false; this = THIS; GF_ASSERT (this); @@ -4696,57 +1676,113 @@ glusterd_op_set_volume (dict_t *dict) priv = this->private; GF_ASSERT (priv); - ret = dict_get_str (dict, "volname", &volname); + ret = dict_get_int32 (dict, "count", &dict_count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Count(dict),not set in Volume-Set"); + goto out; + } + if (dict_count == 0) { + ret = glusterd_volset_help (NULL, &op_errstr); + if (ret) { + op_errstr = (op_errstr)? op_errstr: + "Volume set help internal error"; + gf_log (this->name, GF_LOG_ERROR, "%s", op_errstr); + } + goto out; + } + + ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name"); + goto out; + } + + if (strcasecmp (volname, "all") == 0) { + ret = glusterd_op_set_all_volume_options (this, dict); goto out; } ret = glusterd_volinfo_find (volname, &volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + gf_log (this->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS, + volname); goto out; } - for ( count = 1; ret != -1 ; count++ ) { + // TODO: Remove this once v3.3 compatability is not required + check_op_version = dict_get_str_boolean (dict, "check-op-version", + _gf_false); + + if (check_op_version) { + ret = dict_get_uint32 (dict, "new-op-version", &new_op_version); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to get new op-version from dict"); + goto out; + } + } + + for (count = 1; ret != -1 ; count++) { - global_opt = _gf_false; sprintf (str, "key%d", count); ret = dict_get_str (dict, str, &key); + if (ret) + break; + sprintf (str, "value%d", count); + ret = dict_get_str (dict, str, &value); if (ret) { - break; + gf_log (this->name, GF_LOG_ERROR, + "invalid key,value pair in 'volume set'"); + ret = -1; + goto out; } - if (!ret) { + if (strcmp (key, "config.memory-accounting") == 0) { + ret = gf_string2boolean (value, + &volinfo->memory_accounting); + } + + if (strcmp (key, "config.transport") == 0) { + gf_log (this->name, GF_LOG_INFO, + "changing transport-type for volume %s to %s", + volname, value); + ret = 0; + if (strcasecmp (value, "rdma") == 0) { + volinfo->transport_type = GF_TRANSPORT_RDMA; + } else if (strcasecmp (value, "tcp") == 0) { + volinfo->transport_type = GF_TRANSPORT_TCP; + } else if ((strcasecmp (value, "tcp,rdma") == 0) || + (strcasecmp (value, "rdma,tcp") == 0)) { + volinfo->transport_type = + GF_TRANSPORT_BOTH_TCP_RDMA; + } else { + ret = -1; + goto out; + } + } + + if (!is_key_glusterd_hooks_friendly (key)) { ret = glusterd_check_option_exists (key, &key_fixed); GF_ASSERT (ret); - if (ret == -1) { + if (ret <= 0) { key_fixed = NULL; goto out; } - ret = 0; } - ret = glusterd_check_globaloption (key); - if (ret) + global_opt = _gf_false; + if (glusterd_check_globaloption (key)) { global_opt = _gf_true; - - sprintf (str, "value%d", count); - ret = dict_get_str (dict, str, &value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "invalid key,value pair in 'volume set'"); - ret = -1; - goto out; + global_opts_set = _gf_true; } if (!global_opt) value = gf_strdup (value); if (!value) { - gf_log ("", GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "Unable to set the options in 'volume set'"); ret = -1; goto out; @@ -4755,6 +1791,9 @@ glusterd_op_set_volume (dict_t *dict) if (key_fixed) key = key_fixed; + if (glusterd_is_quorum_changed (volinfo->dict, key, value)) + quorum_action = _gf_true; + if (global_opt) { list_for_each_entry (voliter, &priv->volumes, vol_list) { value = gf_strdup (value); @@ -4762,8 +1801,7 @@ glusterd_op_set_volume (dict_t *dict) if (ret) goto out; } - } - else { + } else { ret = dict_set_dynstr (volinfo->dict, key, value); if (ret) goto out; @@ -4771,75 +1809,75 @@ glusterd_op_set_volume (dict_t *dict) if (key_fixed) { GF_FREE (key_fixed); - key_fixed = NULL; } } - - if ( count == 1 ) { - gf_log ("", GF_LOG_ERROR, "No options received "); + if (count == 1) { + gf_log (this->name, GF_LOG_ERROR, "No options received "); ret = -1; goto out; } - if (!global_opt) { + /* Update the cluster op-version before regenerating volfiles so that + * correct volfiles are generated + */ + if (new_op_version > priv->op_version) { + priv->op_version = new_op_version; + ret = glusterd_store_global_info (this); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to store op-version"); + goto out; + } + } + + if (!global_opts_set) { + gd_update_volume_op_versions (volinfo); ret = glusterd_create_volfiles_and_notify_services (volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" + gf_log (this->name, GF_LOG_ERROR, + "Unable to create volfile for" " 'volume set'"); ret = -1; goto out; } - if (restart_flag) { - if (glusterd_restart_brick_servers (volinfo)) { - ret = -1; - goto out; - } - } - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) goto out; if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_check_generate_start_nfs (); + ret = glusterd_nodesvcs_handle_reconfigure (volinfo); if (ret) { - gf_log ("", GF_LOG_WARNING, + gf_log (this->name, GF_LOG_WARNING, "Unable to restart NFS-Server"); goto out; } } - } - else { + } else { list_for_each_entry (voliter, &priv->volumes, vol_list) { volinfo = voliter; + gd_update_volume_op_versions (volinfo); ret = glusterd_create_volfiles_and_notify_services (volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" + gf_log (this->name, GF_LOG_ERROR, + "Unable to create volfile for" " 'volume set'"); ret = -1; goto out; } - if (restart_flag) { - if (glusterd_restart_brick_servers (volinfo)) { - ret = -1; - goto out; - } - } - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) goto out; if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_check_generate_start_nfs (); + ret = glusterd_nodesvcs_handle_reconfigure (volinfo); if (ret) { - gf_log ("", GF_LOG_WARNING, + gf_log (this->name, GF_LOG_WARNING, "Unable to restart NFS-Server"); goto out; } @@ -4847,434 +1885,16 @@ glusterd_op_set_volume (dict_t *dict) } } - - - ret = 0; - -out: - if (key_fixed) - GF_FREE (key_fixed); - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; -} - -static int -glusterd_op_remove_brick (dict_t *dict) -{ - int ret = -1; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - char *brick = NULL; - int32_t count = 0; - int32_t i = 1; - char key[256] = {0,}; - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } - - - while ( i <= count) { - snprintf (key, 256, "brick%d", i); - ret = dict_get_str (dict, key, &brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); - goto out; - } - - ret = glusterd_op_perform_remove_brick (volinfo, brick); - if (ret) - goto out; - i++; - } - - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) - goto out; - - volinfo->defrag_status = 0; - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - - if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); - -out: - return ret; -} - - -static int -glusterd_op_delete_volume (dict_t *dict) -{ - int ret = 0; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) - goto out; - - ret = glusterd_delete_volume (volinfo); -out: - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; -} - -static int -glusterd_op_start_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - int flags = 0; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - - ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); - if (ret) - goto out; - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) - goto out; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_brick_start (volinfo, brickinfo); - if (ret) - goto out; - } - - glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - ret = glusterd_check_generate_start_nfs (); - -out: - gf_log ("", GF_LOG_DEBUG, "returning %d ", ret); - return ret; -} - -static int -glusterd_op_log_filename (dict_t *dict) -{ - int ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - xlator_t *this = NULL; - char *volname = NULL; - char *brick = NULL; - char *path = NULL; - char logfile[PATH_MAX] = {0,}; - char exp_path[PATH_MAX] = {0,}; - struct stat stbuf = {0,}; - int valid_brick = 0; - glusterd_brickinfo_t *tmpbrkinfo = NULL; - char* new_logdir = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "volname not found"); - goto out; - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "path not found"); - goto out; - } - - ret = dict_get_str (dict, "brick", &brick); - if (ret) - goto out; - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) - goto out; - - if (!strchr (brick, ':')) { - brick = NULL; - ret = stat (path, &stbuf); - if (ret || !S_ISDIR (stbuf.st_mode)) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "not a directory"); - goto out; - } - new_logdir = gf_strdup (path); - if (!new_logdir) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "Out of memory"); - goto out; - } - if (volinfo->logdir) - GF_FREE (volinfo->logdir); - volinfo->logdir = new_logdir; - } else { - ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "cannot get brickinfo from brick"); - goto out; - } - } - - - ret = -1; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - - if (uuid_is_null (brickinfo->uuid)) { - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; - } - - /* check if the brickinfo belongs to the 'this' machine */ - if (uuid_compare (brickinfo->uuid, priv->uuid)) - continue; - - if (brick && strcmp (tmpbrkinfo->path,brickinfo->path)) - continue; - - valid_brick = 1; - - /* If there are more than one brick in 'this' server, its an - * extra check, but it doesn't harm functionality - */ - ret = stat (path, &stbuf); - if (ret || !S_ISDIR (stbuf.st_mode)) { - ret = -1; - gf_log ("", GF_LOG_ERROR, "not a directory"); - goto out; - } - - GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); - - snprintf (logfile, PATH_MAX, "%s/%s.log", path, exp_path); - - if (brickinfo->logfile) - GF_FREE (brickinfo->logfile); - brickinfo->logfile = gf_strdup (logfile); - ret = 0; - - /* If request was for brick, only one iteration is enough */ - if (brick) - break; - } - - if (ret && !valid_brick) - ret = 0; -out: - if (tmpbrkinfo) - glusterd_brickinfo_delete (tmpbrkinfo); - - return ret; -} - -static int -glusterd_op_log_rotate (dict_t *dict) -{ - int ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - xlator_t *this = NULL; - char *volname = NULL; - char *brick = NULL; - char path[PATH_MAX] = {0,}; - char logfile[PATH_MAX] = {0,}; - char pidfile[PATH_MAX] = {0,}; - FILE *file = NULL; - pid_t pid = 0; - uint64_t key = 0; - int valid_brick = 0; - glusterd_brickinfo_t *tmpbrkinfo = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "volname not found"); - goto out; - } - - ret = dict_get_uint64 (dict, "rotate-key", &key); - if (ret) { - gf_log ("", GF_LOG_ERROR, "rotate key not found"); - goto out; - } - - ret = dict_get_str (dict, "brick", &brick); - if (ret) - goto out; - - if (!strchr (brick, ':')) - brick = NULL; - else { - ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "cannot get brickinfo from brick"); - goto out; - } - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) - goto out; - - ret = -1; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (uuid_compare (brickinfo->uuid, priv->uuid)) - continue; - - if (brick && - (strcmp (tmpbrkinfo->hostname, brickinfo->hostname) || - strcmp (tmpbrkinfo->path,brickinfo->path))) - continue; - - valid_brick = 1; - - GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); - GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, - brickinfo->path); - - file = fopen (pidfile, "r+"); - if (!file) { - gf_log ("", GF_LOG_ERROR, "Unable to open pidfile: %s", - pidfile); - ret = -1; - goto out; - } - - ret = fscanf (file, "%d", &pid); - if (ret <= 0) { - gf_log ("", GF_LOG_ERROR, "Unable to read pidfile: %s", - pidfile); - ret = -1; - goto out; - } - fclose (file); - file = NULL; - - snprintf (logfile, PATH_MAX, "%s.%"PRIu64, - brickinfo->logfile, key); - - ret = rename (brickinfo->logfile, logfile); - if (ret) - gf_log ("", GF_LOG_WARNING, "rename failed"); - - ret = kill (pid, SIGHUP); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to SIGHUP to %d", pid); - goto out; - } - ret = 0; - - /* If request was for brick, only one iteration is enough */ - if (brick) - break; - } - - if (ret && !valid_brick) - ret = 0; - -out: - if (tmpbrkinfo) - glusterd_brickinfo_delete (tmpbrkinfo); - + out: + GF_FREE (key_fixed); + gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret); + if (quorum_action) + glusterd_do_quorum_action (); return ret; } static int -glusterd_op_stop_volume (dict_t *dict) -{ - int ret = 0; - int flags = 0; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - - ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); - if (ret) - goto out; - - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) - goto out; - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_brick_stop (volinfo, brickinfo); - if (ret) - goto out; - } - - glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STOPPED); - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - if (glusterd_are_all_volumes_stopped ()) { - if (glusterd_is_nfs_started ()) { - ret = glusterd_nfs_server_stop (); - if (ret) - goto out; - } - } else { - ret = glusterd_check_generate_start_nfs (); - } - -out: - return ret; -} - -static int glusterd_op_sync_volume (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { @@ -5301,7 +1921,7 @@ glusterd_op_sync_volume (dict_t *dict, char **op_errstr, goto out; } - if (glusterd_is_local_addr (hostname)) { + if (!gf_is_local_addr (hostname)) { ret = 0; goto out; } @@ -5354,8 +1974,8 @@ glusterd_add_profile_volume_options (glusterd_volinfo_t *volinfo) GF_ASSERT (volinfo); - latency_key = "diagnostics.latency-measurement"; - fd_stats_key = "diagnostics.dump-fd-stats"; + latency_key = VKEY_DIAG_LAT_MEASUREMENT; + fd_stats_key = VKEY_DIAG_CNT_FOP_HITS; ret = dict_set_str (volinfo->dict, latency_key, "on"); if (ret) { @@ -5385,8 +2005,8 @@ glusterd_remove_profile_volume_options (glusterd_volinfo_t *volinfo) GF_ASSERT (volinfo); - latency_key = "diagnostics.latency-measurement"; - fd_stats_key = "diagnostics.dump-fd-stats"; + latency_key = VKEY_DIAG_LAT_MEASUREMENT; + fd_stats_key = VKEY_DIAG_CNT_FOP_HITS; dict_del (volinfo->dict, latency_key); dict_del (volinfo->dict, fd_stats_key); } @@ -5446,13 +2066,13 @@ glusterd_op_stats_volume (dict_t *dict, char **op_errstr, goto out; break; } - ret = glusterd_create_volfiles_and_notify_services (volinfo); + ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { + if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" - " 'volume set'"); - ret = -1; - goto out; + " 'volume set'"); + ret = -1; + goto out; } ret = glusterd_store_volinfo (volinfo, @@ -5461,7 +2081,7 @@ glusterd_op_stats_volume (dict_t *dict, char **op_errstr, goto out; if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); + ret = glusterd_nodesvcs_handle_reconfigure (volinfo); ret = 0; @@ -5472,11 +2092,444 @@ out: } static int +_add_brick_name_to_dict (dict_t *dict, char *key, glusterd_brickinfo_t *brick) +{ + int ret = -1; + char tmp[1024] = {0,}; + char *brickname = NULL; + xlator_t *this = NULL; + + GF_ASSERT (dict); + GF_ASSERT (key); + GF_ASSERT (brick); + + this = THIS; + GF_ASSERT (this); + + snprintf (tmp, sizeof (tmp), "%s:%s", brick->hostname, brick->path); + brickname = gf_strdup (tmp); + if (!brickname) { + gf_log (this->name, GF_LOG_ERROR, "Failed to dup brick name"); + goto out; + } + + ret = dict_set_dynstr (dict, key, brickname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add brick name to dict"); + goto out; + } + brickname = NULL; +out: + if (brickname) + GF_FREE (brickname); + return ret; +} + +static int +_add_remove_bricks_to_dict (dict_t *dict, glusterd_volinfo_t *volinfo, + char *prefix) +{ + int ret = -1; + int count = 0; + int i = 0; + char brick_key[1024] = {0,}; + char dict_key[1024] ={0,}; + char *brick = NULL; + xlator_t *this = NULL; + + GF_ASSERT (dict); + GF_ASSERT (volinfo); + GF_ASSERT (prefix); + + this = THIS; + GF_ASSERT (this); + + ret = dict_get_int32 (volinfo->rebal.dict, "count", &count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to get brick count"); + goto out; + } + + snprintf (dict_key, sizeof (dict_key), "%s.count", prefix); + ret = dict_set_int32 (dict, dict_key, count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set brick count in dict"); + goto out; + } + + for (i = 1; i <= count; i++) { + memset (brick_key, 0, sizeof (brick_key)); + snprintf (brick_key, sizeof (brick_key), "brick%d", i); + + ret = dict_get_str (volinfo->rebal.dict, brick_key, &brick); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to get %s", brick_key); + goto out; + } + + memset (dict_key, 0, sizeof (dict_key)); + snprintf (dict_key, sizeof (dict_key), "%s.%s", prefix, + brick_key); + ret = dict_set_str (dict, dict_key, brick); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add brick to dict"); + goto out; + } + brick = NULL; + } + +out: + return ret; +} + +/* This adds the respective task-id and all available parameters of a task into + * a dictionary + */ +static int +_add_task_to_dict (dict_t *dict, glusterd_volinfo_t *volinfo, int op, int index) +{ + + int ret = -1; + char key[128] = {0,}; + char *uuid_str = NULL; + int status = 0; + xlator_t *this = NULL; + + GF_ASSERT (dict); + GF_ASSERT (volinfo); + + this = THIS; + GF_ASSERT (this); + + switch (op) { + case GD_OP_REMOVE_BRICK: + snprintf (key, sizeof (key), "task%d", index); + ret = _add_remove_bricks_to_dict (dict, volinfo, key); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add remove bricks to dict"); + goto out; + } + case GD_OP_REBALANCE: + uuid_str = gf_strdup (uuid_utoa (volinfo->rebal.rebalance_id)); + status = volinfo->rebal.defrag_status; + break; + + case GD_OP_REPLACE_BRICK: + snprintf (key, sizeof (key), "task%d.src-brick", index); + ret = _add_brick_name_to_dict (dict, key, + volinfo->rep_brick.src_brick); + if (ret) + goto out; + memset (key, 0, sizeof (key)); + + snprintf (key, sizeof (key), "task%d.dst-brick", index); + ret = _add_brick_name_to_dict (dict, key, + volinfo->rep_brick.dst_brick); + if (ret) + goto out; + memset (key, 0, sizeof (key)); + + uuid_str = gf_strdup (uuid_utoa (volinfo->rep_brick.rb_id)); + status = volinfo->rep_brick.rb_status; + break; + + default: + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "%s operation doesn't have a" + " task_id", gd_op_list[op]); + goto out; + } + + snprintf (key, sizeof (key), "task%d.type", index); + ret = dict_set_str (dict, key, (char *)gd_op_list[op]); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting task type in dict"); + goto out; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "task%d.id", index); + + if (!uuid_str) + goto out; + ret = dict_set_dynstr (dict, key, uuid_str); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting task id in dict"); + goto out; + } + uuid_str = NULL; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "task%d.status", index); + ret = dict_set_int32 (dict, key, status); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting task status in dict"); + goto out; + } + +out: + if (uuid_str) + GF_FREE (uuid_str); + return ret; +} + +static int +glusterd_aggregate_task_status (dict_t *rsp_dict, glusterd_volinfo_t *volinfo) +{ + int ret = -1; + int tasks = 0; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + if (!uuid_is_null (volinfo->rebal.rebalance_id)) { + ret = _add_task_to_dict (rsp_dict, volinfo, volinfo->rebal.op, + tasks); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add task details to dict"); + goto out; + } + tasks++; + } + + if (!uuid_is_null (volinfo->rep_brick.rb_id)) { + ret = _add_task_to_dict (rsp_dict, volinfo, GD_OP_REPLACE_BRICK, + tasks); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add task details to dict"); + goto out; + } + tasks++; + } + + ret = dict_set_int32 (rsp_dict, "tasks", tasks); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting tasks count in dict"); + goto out; + } + ret = 0; + +out: + return ret; +} + +static int +glusterd_op_status_volume (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + int ret = -1; + int node_count = 0; + int brick_index = -1; + int other_count = 0; + int other_index = 0; + uint32_t cmd = 0; + char *volname = NULL; + char *brick = NULL; + xlator_t *this = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_conf_t *priv = NULL; + dict_t *vol_opts = NULL; + gf_boolean_t nfs_disabled = _gf_false; + gf_boolean_t shd_enabled = _gf_true; + gf_boolean_t origin_glusterd = _gf_false; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + + GF_ASSERT (priv); + + GF_ASSERT (dict); + + origin_glusterd = is_origin_glusterd (dict); + + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; + + if (origin_glusterd) { + ret = 0; + if ((cmd & GF_CLI_STATUS_ALL)) { + ret = glusterd_get_all_volnames (rsp_dict); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "failed to get all volume " + "names for status"); + } + } + + ret = dict_set_uint32 (rsp_dict, "cmd", cmd); + if (ret) + goto out; + + if (cmd & GF_CLI_STATUS_ALL) + goto out; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Volume with name: %s " + "does not exist", volname); + goto out; + } + vol_opts = volinfo->dict; + + if ((cmd & GF_CLI_STATUS_NFS) != 0) { + ret = glusterd_add_node_to_dict ("nfs", rsp_dict, 0, vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + + } else if ((cmd & GF_CLI_STATUS_SHD) != 0) { + ret = glusterd_add_node_to_dict ("glustershd", rsp_dict, 0, + vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + + } else if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + + ret = glusterd_volume_brickinfo_get_by_brick (brick, + volinfo, + &brickinfo); + if (ret) + goto out; + + if (uuid_compare (brickinfo->uuid, MY_UUID)) + goto out; + + glusterd_add_brick_to_dict (volinfo, brickinfo, rsp_dict, + ++brick_index); + if (cmd & GF_CLI_STATUS_DETAIL) + glusterd_add_brick_detail_to_dict (volinfo, brickinfo, + rsp_dict, + brick_index); + node_count++; + + } else if ((cmd & GF_CLI_STATUS_TASKS) != 0) { + ret = glusterd_aggregate_task_status (rsp_dict, volinfo); + goto out; + + } else { + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + brick_index++; + if (uuid_compare (brickinfo->uuid, MY_UUID)) + continue; + + glusterd_add_brick_to_dict (volinfo, brickinfo, + rsp_dict, brick_index); + + if (cmd & GF_CLI_STATUS_DETAIL) { + glusterd_add_brick_detail_to_dict (volinfo, + brickinfo, + rsp_dict, + brick_index); + } + node_count++; + } + + if ((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE) { + other_index = brick_index + 1; + + nfs_disabled = dict_get_str_boolean (vol_opts, + "nfs.disable", + _gf_false); + if (!nfs_disabled) { + ret = glusterd_add_node_to_dict ("nfs", + rsp_dict, + other_index, + vol_opts); + if (ret) + goto out; + other_index++; + other_count++; + node_count++; + } + + shd_enabled = dict_get_str_boolean + (vol_opts, "cluster.self-heal-daemon", + _gf_true); + if (glusterd_is_volume_replicate (volinfo) + && shd_enabled) { + ret = glusterd_add_node_to_dict ("glustershd", + rsp_dict, + other_index, + vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + } + } + } + + ret = dict_set_int32 (rsp_dict, "brick-index-max", brick_index); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting brick-index-max to dict"); + goto out; + } + ret = dict_set_int32 (rsp_dict, "other-count", other_count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting other-count to dict"); + goto out; + } + ret = dict_set_int32 (rsp_dict, "count", node_count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting node count to dict"); + goto out; + } + + /* Active tasks */ + /* Tasks are added only for normal volume status request for either a + * single volume or all volumes, and only by the origin glusterd + */ + if (((cmd & GF_CLI_STATUS_MASK) != GF_CLI_STATUS_NONE) || + !(cmd & (GF_CLI_STATUS_VOL | GF_CLI_STATUS_ALL)) || + !origin_glusterd) + goto out; + + ret = glusterd_aggregate_task_status (rsp_dict, volinfo); + if (ret) + goto out; + ret = 0; + +out: + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +static int glusterd_op_ac_none (glusterd_op_sm_event_t *event, void *ctx) { int ret = 0; - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } @@ -5490,6 +2543,7 @@ glusterd_op_ac_send_lock (glusterd_op_sm_event_t *event, void *ctx) xlator_t *this = NULL; glusterd_peerinfo_t *peerinfo = NULL; uint32_t pending_count = 0; + dict_t *dict = NULL; this = THIS; priv = this->private; @@ -5498,27 +2552,66 @@ glusterd_op_ac_send_lock (glusterd_op_sm_event_t *event, void *ctx) list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (!peerinfo->connected) + if (!peerinfo->connected || !peerinfo->mgmt) continue; if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) continue; - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_LOCK]; - if (proc->fn) { - ret = proc->fn (NULL, this, peerinfo); - if (ret) - continue; - pending_count++; + /* Based on the op_version, acquire a cluster or mgmt_v3 lock */ + if (priv->op_version < 3) { + proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_LOCK]; + if (proc->fn) { + ret = proc->fn (NULL, this, peerinfo); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Failed to send lock request " + "for operation 'Volume %s' to " + "peer %s", + gd_op_list[opinfo.op], + peerinfo->hostname); + continue; + } + pending_count++; + } + } else { + dict = glusterd_op_get_ctx (); + dict_ref (dict); + + proc = &peerinfo->mgmt_v3->proctable + [GLUSTERD_MGMT_V3_LOCK]; + if (proc->fn) { + ret = dict_set_static_ptr (dict, "peerinfo", + peerinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to set peerinfo"); + dict_unref (dict); + goto out; + } + + ret = proc->fn (NULL, this, dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Failed to send mgmt_v3 lock " + "request for operation " + "'Volume %s' to peer %s", + gd_op_list[opinfo.op], + peerinfo->hostname); + dict_unref (dict); + continue; + } + pending_count++; + } } } opinfo.pending_count = pending_count; if (!opinfo.pending_count) - ret = glusterd_op_sm_inject_all_acc (); - - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + ret = glusterd_op_sm_inject_all_acc (&event->txn_id); +out: + gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } @@ -5531,87 +2624,213 @@ glusterd_op_ac_send_unlock (glusterd_op_sm_event_t *event, void *ctx) xlator_t *this = NULL; glusterd_peerinfo_t *peerinfo = NULL; uint32_t pending_count = 0; + dict_t *dict = NULL; this = THIS; priv = this->private; GF_ASSERT (priv); - /*ret = glusterd_unlock (priv->uuid); - - if (ret) - goto out; - */ - list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (!peerinfo->connected) + if (!peerinfo->connected || !peerinfo->mgmt) continue; if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) continue; - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_UNLOCK]; - if (proc->fn) { - ret = proc->fn (NULL, this, peerinfo); - if (ret) - continue; - pending_count++; + /* Based on the op_version, release the * + * cluster or mgmt_v3 lock */ + if (priv->op_version < 3) { + proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_UNLOCK]; + if (proc->fn) { + ret = proc->fn (NULL, this, peerinfo); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Failed to send unlock request " + "for operation 'Volume %s' to " + "peer %s", + gd_op_list[opinfo.op], + peerinfo->hostname); + continue; + } + pending_count++; + } + } else { + dict = glusterd_op_get_ctx (); + dict_ref (dict); + + proc = &peerinfo->mgmt_v3->proctable + [GLUSTERD_MGMT_V3_UNLOCK]; + if (proc->fn) { + ret = dict_set_static_ptr (dict, "peerinfo", + peerinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "failed to set peerinfo"); + dict_unref (dict); + goto out; + } + + ret = proc->fn (NULL, this, dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Failed to send mgmt_v3 unlock " + "request for operation " + "'Volume %s' to peer %s", + gd_op_list[opinfo.op], + peerinfo->hostname); + dict_unref (dict); + continue; + } + pending_count++; + } } } opinfo.pending_count = pending_count; if (!opinfo.pending_count) - ret = glusterd_op_sm_inject_all_acc (); + ret = glusterd_op_sm_inject_all_acc (&event->txn_id); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); +out: + gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +static int +glusterd_op_ac_ack_drain (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + + if (opinfo.pending_count > 0) + opinfo.pending_count--; + + if (!opinfo.pending_count) + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, + &event->txn_id, NULL); + + gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; +} +static int +glusterd_op_ac_send_unlock_drain (glusterd_op_sm_event_t *event, void *ctx) +{ + return glusterd_op_ac_ack_drain (event, ctx); } static int glusterd_op_ac_lock (glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - glusterd_op_lock_ctx_t *lock_ctx = NULL; - int32_t status = 0; - + int32_t ret = 0; + char *volname = NULL; + glusterd_op_lock_ctx_t *lock_ctx = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; GF_ASSERT (event); GF_ASSERT (ctx); - lock_ctx = (glusterd_op_lock_ctx_t *)ctx; + this = THIS; + priv = this->private; - status = glusterd_lock (lock_ctx->uuid); + lock_ctx = (glusterd_op_lock_ctx_t *)ctx; - gf_log ("", GF_LOG_DEBUG, "Lock Returned %d", status); + /* If the req came from a node running on older op_version + * the dict won't be present. Based on it acquiring a cluster + * or mgmt_v3 lock */ + if (lock_ctx->dict == NULL) { + ret = glusterd_lock (lock_ctx->uuid); + glusterd_op_lock_send_resp (lock_ctx->req, ret); + } else { + ret = dict_get_str (lock_ctx->dict, "volname", &volname); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to acquire volname"); + else { + ret = glusterd_mgmt_v3_lock (volname, lock_ctx->uuid, + "vol"); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to acquire lock for %s", + volname); + } - ret = glusterd_op_lock_send_resp (lock_ctx->req, status); + glusterd_op_mgmt_v3_lock_send_resp (lock_ctx->req, + &event->txn_id, ret); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + dict_unref (lock_ctx->dict); + } + gf_log (THIS->name, GF_LOG_DEBUG, "Lock Returned %d", ret); return ret; } static int glusterd_op_ac_unlock (glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - glusterd_op_lock_ctx_t *lock_ctx = NULL; + int32_t ret = 0; + char *volname = NULL; + glusterd_op_lock_ctx_t *lock_ctx = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + GF_ASSERT (event); GF_ASSERT (ctx); + this = THIS; + priv = this->private; + lock_ctx = (glusterd_op_lock_ctx_t *)ctx; - ret = glusterd_unlock (lock_ctx->uuid); + /* If the req came from a node running on older op_version + * the dict won't be present. Based on it releasing the cluster + * or mgmt_v3 lock */ + if (lock_ctx->dict == NULL) { + ret = glusterd_unlock (lock_ctx->uuid); + glusterd_op_unlock_send_resp (lock_ctx->req, ret); + } else { + ret = dict_get_str (lock_ctx->dict, "volname", &volname); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to acquire volname"); + else { + ret = glusterd_mgmt_v3_unlock (volname, lock_ctx->uuid, + "vol"); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to release lock for %s", volname); + } - gf_log ("", GF_LOG_DEBUG, "Unlock Returned %d", ret); + glusterd_op_mgmt_v3_unlock_send_resp (lock_ctx->req, + &event->txn_id, ret); - ret = glusterd_op_unlock_send_resp (lock_ctx->req, ret); + dict_unref (lock_ctx->dict); + } - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Unlock Returned %d", ret); + + if (priv->pending_quorum_action) + glusterd_do_quorum_action (); + return ret; +} + +static int +glusterd_op_ac_local_unlock (glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + uuid_t *originator = NULL; + + GF_ASSERT (event); + GF_ASSERT (ctx); + + originator = (uuid_t *) ctx; + + ret = glusterd_unlock (*originator); + + gf_log (THIS->name, GF_LOG_DEBUG, "Unlock Returned %d", ret); return ret; } @@ -5629,78 +2848,243 @@ glusterd_op_ac_rcvd_lock_acc (glusterd_op_sm_event_t *event, void *ctx) if (opinfo.pending_count > 0) goto out; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, + &event->txn_id, NULL); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + +out: + return ret; +} + +static int +glusterd_dict_set_volid (dict_t *dict, char *volname, char **op_errstr) +{ + int ret = -1; + glusterd_volinfo_t *volinfo = NULL; + char *volid = NULL; + char msg[1024] = {0,}; + xlator_t *this = NULL; + this = THIS; + GF_ASSERT (this); + + if (!dict || !volname) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, volname); + goto out; + } + volid = gf_strdup (uuid_utoa (volinfo->volume_id)); + if (!volid) { + ret = -1; + goto out; + } + ret = dict_set_dynstr (dict, "vol-id", volid); + if (ret) { + snprintf (msg, sizeof (msg), "Failed to set volume id of volume" + " %s", volname); + goto out; + } out: + if (msg[0] != '\0') { + gf_log (this->name, GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + } return ret; } int -glusterd_op_build_payload (glusterd_op_t op, dict_t **req) +glusterd_op_build_payload (dict_t **req, char **op_errstr, dict_t *op_ctx) { int ret = -1; void *ctx = NULL; + dict_t *dict = NULL; dict_t *req_dict = NULL; + glusterd_op_t op = GD_OP_NONE; + char *volname = NULL; + uint32_t status_cmd = GF_CLI_STATUS_NONE; + char *errstr = NULL; + xlator_t *this = NULL; - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); GF_ASSERT (req); + this = THIS; + GF_ASSERT (this); + req_dict = dict_new (); if (!req_dict) goto out; - ctx = (void*)glusterd_op_get_ctx (op); - if (!ctx) { - gf_log ("", GF_LOG_ERROR, "Null Context for " - "op %d", op); - ret = -1; - goto out; + if (!op_ctx) { + op = glusterd_op_get_op (); + ctx = (void*)glusterd_op_get_ctx (); + if (!ctx) { + gf_log (this->name, GF_LOG_ERROR, "Null Context for " + "op %d", op); + ret = -1; + goto out; + } + + } else { +#define GD_SYNC_OPCODE_KEY "sync-mgmt-operation" + ret = dict_get_int32 (op_ctx, GD_SYNC_OPCODE_KEY, (int32_t*)&op); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get volume" + " operation"); + goto out; + } + ctx = op_ctx; +#undef GD_SYNC_OPCODE_KEY } + dict = ctx; switch (op) { case GD_OP_CREATE_VOLUME: { - dict_t *dict = ctx; ++glusterfs_port; - ret = dict_set_int32 (dict, "port", glusterfs_port); - if (ret) + ret = dict_set_int32 (dict, "port", + glusterfs_port); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set port in " + "dictionary"); goto out; + } dict_copy (dict, req_dict); } break; - case GD_OP_DELETE_VOLUME: + case GD_OP_GSYNC_CREATE: + case GD_OP_GSYNC_SET: + { + ret = glusterd_op_gsync_args_get (dict, + &errstr, + &volname, + NULL, NULL); + if (ret == 0) { + ret = glusterd_dict_set_volid + (dict, volname, op_errstr); + if (ret) + goto out; + } + dict_copy (dict, req_dict); + } + break; + + case GD_OP_SET_VOLUME: + { + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_CRITICAL, + "volname is not present in " + "operation ctx"); + goto out; + } + if (strcmp (volname, "help") && + strcmp (volname, "help-xml") && + strcasecmp (volname, "all")) { + ret = glusterd_dict_set_volid + (dict, volname, op_errstr); + if (ret) + goto out; + } + dict_destroy (req_dict); + req_dict = dict_ref (dict); + } + break; + + case GD_OP_SYNC_VOLUME: + { + dict_copy (dict, req_dict); + break; + } + + case GD_OP_REMOVE_BRICK: { - glusterd_op_delete_volume_ctx_t *ctx1 = ctx; - ret = dict_set_str (req_dict, "volname", - ctx1->volume_name); + dict_t *dict = ctx; + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_CRITICAL, + "volname is not present in " + "operation ctx"); + goto out; + } + + ret = glusterd_dict_set_volid (dict, volname, + op_errstr); if (ret) goto out; + + dict_destroy (req_dict); + req_dict = dict_ref (dict); } break; + case GD_OP_STATUS_VOLUME: + { + ret = dict_get_uint32 (dict, "cmd", + &status_cmd); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Status command not present " + "in op ctx"); + goto out; + } + if (GF_CLI_STATUS_ALL & status_cmd) { + dict_copy (dict, req_dict); + break; + } + } + /*fall-through*/ + case GD_OP_DELETE_VOLUME: case GD_OP_START_VOLUME: case GD_OP_STOP_VOLUME: case GD_OP_ADD_BRICK: case GD_OP_REPLACE_BRICK: - case GD_OP_SET_VOLUME: case GD_OP_RESET_VOLUME: - case GD_OP_REMOVE_BRICK: - case GD_OP_LOG_FILENAME: case GD_OP_LOG_ROTATE: - case GD_OP_SYNC_VOLUME: case GD_OP_QUOTA: - case GD_OP_GSYNC_SET: case GD_OP_PROFILE_VOLUME: + case GD_OP_REBALANCE: + case GD_OP_HEAL_VOLUME: + case GD_OP_STATEDUMP_VOLUME: + case GD_OP_CLEARLOCKS_VOLUME: + case GD_OP_DEFRAG_BRICK_VOLUME: { - dict_t *dict = ctx; + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_CRITICAL, + "volname is not present in " + "operation ctx"); + goto out; + } + + if (strcasecmp (volname, "all")) { + ret = glusterd_dict_set_volid (dict, + volname, + op_errstr); + if (ret) + goto out; + } dict_copy (dict, req_dict); } break; + case GD_OP_COPY_FILE: + { + dict_copy (dict, req_dict); + break; + } + + case GD_OP_SYS_EXEC: + { + dict_copy (dict, req_dict); + break; + } + default: break; } @@ -5712,6 +3096,105 @@ out: return ret; } +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_op_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; +} + +static int +glusterd_op_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_op_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; + } + + if (does_gd_meet_server_quorum (this)) { + 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; +} + static int glusterd_op_ac_send_stage_op (glusterd_op_sm_event_t *event, void *ctx) { @@ -5722,7 +3205,7 @@ glusterd_op_ac_send_stage_op (glusterd_op_sm_event_t *event, void *ctx) glusterd_peerinfo_t *peerinfo = NULL; dict_t *dict = NULL; char *op_errstr = NULL; - int i = 0; + glusterd_op_t op = GD_OP_NONE; uint32_t pending_count = 0; this = THIS; @@ -5730,29 +3213,34 @@ glusterd_op_ac_send_stage_op (glusterd_op_sm_event_t *event, void *ctx) priv = this->private; GF_ASSERT (priv); - for ( i = GD_OP_NONE; i < GD_OP_MAX; i++) { - if (opinfo.pending_op[i]) - break; - } - - if (GD_OP_MAX == i) { - //No pending ops, inject stage_acc - ret = glusterd_op_sm_inject_event - (GD_OP_EVENT_STAGE_ACC, NULL); + op = glusterd_op_get_op (); - return ret; + ret = glusterd_op_build_payload (&dict, &op_errstr, NULL); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, LOGSTR_BUILD_PAYLOAD, + gd_op_list[op]); + if (op_errstr == NULL) + gf_asprintf (&op_errstr, OPERRSTR_BUILD_PAYLOAD); + opinfo.op_errstr = op_errstr; + goto out; } - glusterd_op_clear_pending_op (i); - - ret = glusterd_op_build_payload (i, &dict); - if (ret) + ret = glusterd_op_validate_quorum (this, op, dict, &op_errstr); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "%s", op_errstr); + opinfo.op_errstr = op_errstr; goto out; + } /* rsp_dict NULL from source */ - ret = glusterd_op_stage_validate (i, dict, &op_errstr, NULL); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Staging failed"); + ret = glusterd_op_stage_validate (op, dict, &op_errstr, NULL); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, LOGSTR_STAGE_FAIL, + gd_op_list[op], "localhost", + (op_errstr) ? ":" : " ", (op_errstr) ? op_errstr : " "); + if (op_errstr == NULL) + gf_asprintf (&op_errstr, OPERRSTR_STAGE_FAIL, + "localhost"); opinfo.op_errstr = op_errstr; goto out; } @@ -5760,7 +3248,7 @@ glusterd_op_ac_send_stage_op (glusterd_op_sm_event_t *event, void *ctx) list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (!peerinfo->connected) + if (!peerinfo->connected || !peerinfo->mgmt) continue; if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) @@ -5771,13 +3259,19 @@ glusterd_op_ac_send_stage_op (glusterd_op_sm_event_t *event, void *ctx) if (proc->fn) { ret = dict_set_static_ptr (dict, "peerinfo", peerinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to set peerinfo"); + gf_log (this->name, GF_LOG_ERROR, "failed to " + "set peerinfo"); goto out; } ret = proc->fn (NULL, this, dict); - if (ret) + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to " + "send stage request for operation " + "'Volume %s' to peer %s", + gd_op_list[op], peerinfo->hostname); continue; + } pending_count++; } } @@ -5787,29 +3281,32 @@ out: if (dict) dict_unref (dict); if (ret) { - glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); + glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, + &event->txn_id, NULL); opinfo.op_ret = ret; } - gf_log ("glusterd", GF_LOG_NORMAL, "Sent op req to %d peers", + gf_log (this->name, GF_LOG_DEBUG, "Sent stage op request for " + "'Volume %s' to %d peers", gd_op_list[op], opinfo.pending_count); if (!opinfo.pending_count) - ret = glusterd_op_sm_inject_all_acc (); + ret = glusterd_op_sm_inject_all_acc (&event->txn_id); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } static int32_t -glusterd_op_start_rb_timer (dict_t *dict) +glusterd_op_start_rb_timer (dict_t *dict, uuid_t *txn_id) { int32_t op = 0; - struct timeval timeout = {0, }; + struct timespec timeout = {0, }; glusterd_conf_t *priv = NULL; int32_t ret = -1; + dict_t *rb_ctx = NULL; GF_ASSERT (dict); priv = THIS->private; @@ -5821,18 +3318,36 @@ glusterd_op_start_rb_timer (dict_t *dict) goto out; } - if (op == GF_REPLACE_OP_START || - op == GF_REPLACE_OP_ABORT) - timeout.tv_sec = 5; - else - timeout.tv_sec = 1; + if (op != GF_REPLACE_OP_START) { + ret = glusterd_op_sm_inject_all_acc (txn_id); + goto out; + } - timeout.tv_usec = 0; + timeout.tv_sec = 5; + timeout.tv_nsec = 0; + rb_ctx = dict_copy (dict, rb_ctx); + if (!rb_ctx) { + gf_log (THIS->name, GF_LOG_ERROR, "Couldn't copy " + "replace brick context. Can't start replace brick"); + ret = -1; + goto out; + } + + ret = dict_set_bin (rb_ctx, "transaction_id", + txn_id, sizeof(*txn_id)); + if (ret) { + gf_log ("", GF_LOG_ERROR, + "Failed to set transaction id."); + goto out; + } else + gf_log ("", GF_LOG_DEBUG, + "transaction_id = %s", uuid_utoa (*txn_id)); + priv->timer = gf_timer_call_after (THIS->ctx, timeout, glusterd_do_replace_brick, - (void *) dict); + (void *) rb_ctx); ret = 0; @@ -5840,6 +3355,360 @@ out: return ret; } +/* This function takes a dict and converts the uuid values of key specified + * into hostnames + */ +static int +glusterd_op_volume_dict_uuid_to_hostname (dict_t *dict, const char *key_fmt, + int idx_min, int idx_max) +{ + int ret = -1; + int i = 0; + char key[1024]; + char *uuid_str = NULL; + uuid_t uuid = {0,}; + char *hostname = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + GF_ASSERT (dict); + GF_ASSERT (key_fmt); + + for (i = idx_min; i < idx_max; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), key_fmt, i); + ret = dict_get_str (dict, key, &uuid_str); + if (ret) + continue; + + gf_log (this->name, GF_LOG_DEBUG, "Got uuid %s", + uuid_str); + + ret = uuid_parse (uuid_str, uuid); + /* if parsing fails don't error out + * let the original value be retained + */ + if (ret) + continue; + + hostname = glusterd_uuid_to_hostname (uuid); + if (hostname) { + gf_log (this->name, GF_LOG_DEBUG, "%s -> %s", + uuid_str, hostname); + ret = dict_set_dynstr (dict, key, hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Error setting hostname %s to dict", + hostname); + GF_FREE (hostname); + goto out; + } + } + } + +out: + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +reassign_defrag_status (dict_t *dict, char *key, gf_defrag_status_t *status) +{ + int ret = 0; + + if (!*status) + return ret; + + switch (*status) { + case GF_DEFRAG_STATUS_STARTED: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_STARTED; + break; + + case GF_DEFRAG_STATUS_STOPPED: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_STOPPED; + break; + + case GF_DEFRAG_STATUS_COMPLETE: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_COMPLETE; + break; + + case GF_DEFRAG_STATUS_FAILED: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_FAILED; + break; + default: + break; + } + + ret = dict_set_int32(dict, key, *status); + if (ret) + gf_log (THIS->name, GF_LOG_WARNING, + "failed to reset defrag %s in dict", key); + + return ret; +} + +/* Check and reassign the defrag_status enum got from the rebalance process + * of all peers so that the rebalance-status CLI command can display if a + * full-rebalance or just a fix-layout was carried out. + */ +static int +glusterd_op_check_peer_defrag_status (dict_t *dict, int count) +{ + glusterd_volinfo_t *volinfo = NULL; + gf_defrag_status_t status = GF_DEFRAG_STATUS_NOT_STARTED; + char key[256] = {0,}; + char *volname = NULL; + int ret = -1; + int i = 1; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, FMTSTR_CHECK_VOL_EXISTS, + volname); + goto out; + } + + if (volinfo->rebal.defrag_cmd != GF_DEFRAG_CMD_START_LAYOUT_FIX) { + /* Fix layout was not issued; we don't need to reassign + the status */ + ret = 0; + goto out; + } + + do { + memset (key, 0, 256); + snprintf (key, 256, "status-%d", i); + ret = dict_get_int32 (dict, key, (int32_t *)&status); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, + "failed to get defrag %s", key); + goto out; + } + ret = reassign_defrag_status (dict, key, &status); + if (ret) + goto out; + i++; + } while (i <= count); + + ret = 0; +out: + return ret; + +} + +/* This function is used to modify the op_ctx dict before sending it back + * to cli. This is useful in situations like changing the peer uuids to + * hostnames etc. + */ +void +glusterd_op_modify_op_ctx (glusterd_op_t op, void *ctx) +{ + int ret = -1; + dict_t *op_ctx = NULL; + int brick_index_max = -1; + int other_count = 0; + int count = 0; + uint32_t cmd = GF_CLI_STATUS_NONE; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + if (ctx) + op_ctx = ctx; + else + op_ctx = glusterd_op_get_ctx(); + + if (!op_ctx) { + gf_log (this->name, GF_LOG_CRITICAL, + "Operation context is not present."); + goto out; + } + + switch (op) { + case GD_OP_STATUS_VOLUME: + ret = dict_get_uint32 (op_ctx, "cmd", &cmd); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "Failed to get status cmd"); + goto out; + } + if (!(cmd & GF_CLI_STATUS_NFS || cmd & GF_CLI_STATUS_SHD || + (cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE)) { + gf_log (this->name, GF_LOG_DEBUG, + "op_ctx modification not required for status " + "operation being performed"); + goto out; + } + + ret = dict_get_int32 (op_ctx, "brick-index-max", + &brick_index_max); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "Failed to get brick-index-max"); + goto out; + } + + ret = dict_get_int32 (op_ctx, "other-count", &other_count); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "Failed to get other-count"); + goto out; + } + + count = brick_index_max + other_count + 1; + + ret = glusterd_op_volume_dict_uuid_to_hostname (op_ctx, + "brick%d.path", + 0, count); + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "Failed uuid to hostname conversion"); + + break; + + case GD_OP_PROFILE_VOLUME: + ret = dict_get_str_boolean (op_ctx, "nfs", _gf_false); + if (!ret) + goto out; + + ret = dict_get_int32 (op_ctx, "count", &count); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "Failed to get brick count"); + goto out; + } + + ret = glusterd_op_volume_dict_uuid_to_hostname (op_ctx, + "%d-brick", + 1, (count + 1)); + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "Failed uuid to hostname conversion"); + + break; + + /* For both rebalance and remove-brick status, the glusterd op is the + * same + */ + case GD_OP_DEFRAG_BRICK_VOLUME: + ret = dict_get_int32 (op_ctx, "count", &count); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "Failed to get count"); + goto out; + } + + /* add 'node-name-%d' into op_ctx with value uuid_str. + this will be used to convert to hostname later */ + { + char key[1024]; + char *uuid_str = NULL; + int i; + + for (i = 1; i <= count; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "node-uuid-%d", i); + ret = dict_get_str (op_ctx, key, &uuid_str); + if (!ret) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), + "node-name-%d", i); + ret = dict_set_str (op_ctx, key, + uuid_str); + } + } + } + + ret = glusterd_op_volume_dict_uuid_to_hostname (op_ctx, + "node-name-%d", + 1, (count + 1)); + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "Failed uuid to hostname conversion"); + + ret = glusterd_op_check_peer_defrag_status (op_ctx, count); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Failed to reset defrag status for fix-layout"); + break; + + default: + ret = 0; + gf_log (this->name, GF_LOG_DEBUG, + "op_ctx modification not required"); + break; + + } + +out: + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "op_ctx modification failed"); + return; +} + +static int +glusterd_op_commit_hook (glusterd_op_t op, dict_t *op_ctx, + glusterd_commit_hook_type_t type) +{ + glusterd_conf_t *priv = NULL; + char hookdir[PATH_MAX] = {0, }; + char scriptdir[PATH_MAX] = {0, }; + char type_subdir[256] = {0, }; + char *cmd_subdir = NULL; + int ret = -1; + + priv = THIS->private; + switch (type) { + case GD_COMMIT_HOOK_NONE: + case GD_COMMIT_HOOK_MAX: + /*Won't be called*/ + break; + + case GD_COMMIT_HOOK_PRE: + strcpy (type_subdir, "pre"); + break; + case GD_COMMIT_HOOK_POST: + strcpy (type_subdir, "post"); + break; + } + + cmd_subdir = glusterd_hooks_get_hooks_cmd_subdir (op); + if (strlen (cmd_subdir) == 0) + return -1; + + GLUSTERD_GET_HOOKS_DIR (hookdir, GLUSTERD_HOOK_VER, priv); + snprintf (scriptdir, sizeof (scriptdir), "%s/%s/%s", + hookdir, cmd_subdir, type_subdir); + + switch (type) { + case GD_COMMIT_HOOK_NONE: + case GD_COMMIT_HOOK_MAX: + /*Won't be called*/ + break; + + case GD_COMMIT_HOOK_PRE: + ret = glusterd_hooks_run_hooks (scriptdir, op, op_ctx, + type); + break; + case GD_COMMIT_HOOK_POST: + ret = glusterd_hooks_post_stub_enqueue (scriptdir, op, + op_ctx); + break; + } + + return ret; +} + static int glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx) { @@ -5851,42 +3720,44 @@ glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx) dict_t *op_dict = NULL; glusterd_peerinfo_t *peerinfo = NULL; char *op_errstr = NULL; - int i = 0; - uint32_t pending_count = 0; + glusterd_op_t op = GD_OP_NONE; + uint32_t pending_count = 0; this = THIS; GF_ASSERT (this); priv = this->private; GF_ASSERT (priv); - for ( i = GD_OP_NONE; i < GD_OP_MAX; i++) { - if (opinfo.commit_op[i]) - break; - } - - if (GD_OP_MAX == i) { - //No pending ops, return - return 0; - } + op = glusterd_op_get_op (); + op_dict = glusterd_op_get_ctx (); - glusterd_op_clear_commit_op (i); - - ret = glusterd_op_build_payload (i, &dict); - - if (ret) + ret = glusterd_op_build_payload (&dict, &op_errstr, NULL); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, LOGSTR_BUILD_PAYLOAD, + gd_op_list[op]); + if (op_errstr == NULL) + gf_asprintf (&op_errstr, OPERRSTR_BUILD_PAYLOAD); + opinfo.op_errstr = op_errstr; goto out; + } - ret = glusterd_op_commit_perform (i, dict, &op_errstr, NULL); //rsp_dict invalid for source + ret = glusterd_op_commit_perform (op, dict, &op_errstr, NULL); //rsp_dict invalid for source if (ret) { - gf_log ("", GF_LOG_ERROR, "Commit failed"); + gf_log (this->name, GF_LOG_ERROR, LOGSTR_COMMIT_FAIL, + gd_op_list[op], "localhost", (op_errstr) ? ":" : " ", + (op_errstr) ? op_errstr : " "); + if (op_errstr == NULL) + gf_asprintf (&op_errstr, OPERRSTR_COMMIT_FAIL, + "localhost"); opinfo.op_errstr = op_errstr; goto out; } + list_for_each_entry (peerinfo, &priv->peers, uuid_list) { GF_ASSERT (peerinfo); - if (!peerinfo->connected) + if (!peerinfo->connected || !peerinfo->mgmt) continue; if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) @@ -5897,40 +3768,48 @@ glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx) if (proc->fn) { ret = dict_set_static_ptr (dict, "peerinfo", peerinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to set peerinfo"); + gf_log (this->name, GF_LOG_ERROR, + "failed to set peerinfo"); goto out; } ret = proc->fn (NULL, this, dict); - if (ret) + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to " + "send commit request for operation " + "'Volume %s' to peer %s", + gd_op_list[op], peerinfo->hostname); continue; + } pending_count++; } } opinfo.pending_count = pending_count; - gf_log ("glusterd", GF_LOG_NORMAL, "Sent op req to %d peers", - opinfo.pending_count); + gf_log (this->name, GF_LOG_DEBUG, "Sent commit op req for 'Volume %s' " + "to %d peers", gd_op_list[op], opinfo.pending_count); out: if (dict) dict_unref (dict); if (ret) { - glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); + glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, + &event->txn_id, NULL); opinfo.op_ret = ret; } if (!opinfo.pending_count) { - op_dict = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (!op_dict) { - ret = glusterd_op_sm_inject_all_acc (); - goto err; - } + if (op == GD_OP_REPLACE_BRICK) { + ret = glusterd_op_start_rb_timer (op_dict, + &event->txn_id); - op_dict = dict_ref (op_dict); - ret = glusterd_op_start_rb_timer (op_dict); + } else { + glusterd_op_modify_op_ctx (op, NULL); + ret = glusterd_op_sm_inject_all_acc (&event->txn_id); + } + goto err; } err: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; @@ -5949,10 +3828,11 @@ glusterd_op_ac_rcvd_stage_op_acc (glusterd_op_sm_event_t *event, void *ctx) if (opinfo.pending_count > 0) goto out; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_STAGE_ACC, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_STAGE_ACC, + &event->txn_id, NULL); out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -5970,10 +3850,11 @@ glusterd_op_ac_stage_op_failed (glusterd_op_sm_event_t *event, void *ctx) if (opinfo.pending_count > 0) goto out; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, + &event->txn_id, NULL); out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -5991,10 +3872,11 @@ glusterd_op_ac_commit_op_failed (glusterd_op_sm_event_t *event, void *ctx) if (opinfo.pending_count > 0) goto out; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, + &event->txn_id, NULL); out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -6004,19 +3886,19 @@ glusterd_op_ac_brick_op_failed (glusterd_op_sm_event_t *event, void *ctx) { int ret = 0; glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; - glusterd_brickinfo_t *brickinfo = NULL; gf_boolean_t free_errstr = _gf_false; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); GF_ASSERT (event); GF_ASSERT (ctx); ev_ctx = ctx; - brickinfo = ev_ctx->brickinfo; - GF_ASSERT (brickinfo); - ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, brickinfo); + ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, ev_ctx->pending_node->node); if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "unknown response received " - "from %s:%s", brickinfo->hostname, brickinfo->path); + gf_log (this->name, GF_LOG_ERROR, "unknown response received "); ret = -1; free_errstr = _gf_true; goto out; @@ -6034,7 +3916,8 @@ glusterd_op_ac_brick_op_failed (glusterd_op_sm_event_t *event, void *ctx) if (opinfo.brick_pending_count > 0) goto out; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, ev_ctx->commit_ctx); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, + &event->txn_id, ev_ctx->commit_ctx); out: if (ev_ctx->rsp_dict) @@ -6042,182 +3925,23 @@ out: if (free_errstr && ev_ctx->op_errstr) GF_FREE (ev_ctx->op_errstr); GF_FREE (ctx); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } -void -glusterd_op_brick_disconnect (void *data) -{ - glusterd_brickinfo_t *brickinfo = NULL; - glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; - - ev_ctx = data; - GF_ASSERT (ev_ctx); - brickinfo = ev_ctx->brickinfo; - GF_ASSERT (brickinfo); - - if (brickinfo->timer) { - gf_timer_call_cancel (THIS->ctx, brickinfo->timer); - brickinfo->timer = NULL; - gf_log ("", GF_LOG_DEBUG, - "Cancelled timer thread"); - } - - glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_ACC, ev_ctx); - glusterd_op_sm (); -} - -void -glusterd_do_replace_brick (void *data) -{ - glusterd_volinfo_t *volinfo = NULL; - int32_t op = 0; - int32_t src_port = 0; - int32_t dst_port = 0; - dict_t *dict = NULL; - char *src_brick = NULL; - char *dst_brick = NULL; - char *volname = NULL; - glusterd_brickinfo_t *src_brickinfo = NULL; - glusterd_brickinfo_t *dst_brickinfo = NULL; - glusterd_conf_t *priv = NULL; - - int ret = 0; - - dict = data; - - GF_ASSERT (THIS); - - priv = THIS->private; - - if (priv->timer) { - gf_timer_call_cancel (THIS->ctx, priv->timer); - priv->timer = NULL; - gf_log ("", GF_LOG_DEBUG, - "Cancelled timer thread"); - } - - gf_log ("", GF_LOG_DEBUG, - "Replace brick operation detected"); - - ret = dict_get_int32 (dict, "operation", &op); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "dict_get on operation failed"); - goto out; - } - ret = dict_get_str (dict, "src-brick", &src_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "src brick=%s", src_brick); - - ret = dict_get_str (dict, "dst-brick", &dst_brick); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "dst brick=%s", dst_brick); - - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } - - ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); - goto out; - } - - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); - if (!dst_brickinfo) { - gf_log ("", GF_LOG_DEBUG, "Unable to get dst-brickinfo"); - goto out; - } - - ret = glusterd_resolve_brick (dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); - goto out; - } - - ret = dict_get_int32 (dict, "src-brick-port", &src_port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src-brick port"); - goto out; - } - - ret = dict_get_int32 (dict, "dst-brick-port", &dst_port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dst-brick port"); - } - - dst_brickinfo->port = dst_port; - src_brickinfo->port = src_port; - - switch (op) { - case GF_REPLACE_OP_START: - if (!dst_port) { - ret = -1; - goto out; - } - - ret = rb_do_operation_start (volinfo, src_brickinfo, dst_brickinfo); - if (ret) { - glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); - goto out; - } - break; - case GF_REPLACE_OP_PAUSE: - case GF_REPLACE_OP_ABORT: - case GF_REPLACE_OP_COMMIT: - case GF_REPLACE_OP_COMMIT_FORCE: - case GF_REPLACE_OP_STATUS: - break; - default: - ret = -1; - goto out; - } - -out: - if (ret) - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); - else - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, NULL); - -// if (dict) -// dict_unref (dict); - - glusterd_op_sm (); -} - - - static int glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) { - glusterd_conf_t *priv = NULL; - dict_t *dict = NULL; + dict_t *op_ctx = NULL; int ret = 0; - gf_boolean_t commit_ack_inject = _gf_false; + gf_boolean_t commit_ack_inject = _gf_true; + glusterd_op_t op = GD_OP_NONE; + xlator_t *this = NULL; - priv = THIS->private; + this = THIS; + GF_ASSERT (this); + op = glusterd_op_get_op (); GF_ASSERT (event); if (opinfo.pending_count > 0) @@ -6226,22 +3950,38 @@ glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) if (opinfo.pending_count > 0) goto out; - dict = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (dict) { - ret = glusterd_op_start_rb_timer (dict); - if (ret) + if (op == GD_OP_REPLACE_BRICK) { + op_ctx = glusterd_op_get_ctx (); + if (!op_ctx) { + gf_log (this->name, GF_LOG_CRITICAL, "Operation " + "context is not present."); + ret = -1; goto out; + } + + ret = glusterd_op_start_rb_timer (op_ctx, &event->txn_id); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Couldn't start " + "replace-brick operation."); + goto out; + } + commit_ack_inject = _gf_false; - goto out; + goto out; } - commit_ack_inject = _gf_true; + out: if (commit_ack_inject) { if (ret) - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); - else - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, + &event->txn_id, NULL); + else if (!opinfo.pending_count) { + glusterd_op_modify_op_ctx (op, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, + &event->txn_id, NULL); + } + /*else do nothing*/ } return ret; @@ -6260,15 +4000,15 @@ glusterd_op_ac_rcvd_unlock_acc (glusterd_op_sm_event_t *event, void *ctx) if (opinfo.pending_count > 0) goto out; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, + &event->txn_id, NULL); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); out: return ret; } - int32_t glusterd_op_clear_errstr() { opinfo.op_errstr = NULL; @@ -6276,145 +4016,120 @@ glusterd_op_clear_errstr() { } int32_t -glusterd_op_set_ctx (glusterd_op_t op, void *ctx) +glusterd_op_set_ctx (void *ctx) { - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - opinfo.op_ctx[op] = ctx; + opinfo.op_ctx = ctx; return 0; } int32_t -glusterd_op_reset_ctx (glusterd_op_t op) +glusterd_op_reset_ctx () { - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - glusterd_op_set_ctx (op, NULL); + glusterd_op_set_ctx (NULL); return 0; } int32_t -glusterd_op_txn_complete () +glusterd_op_txn_complete (uuid_t *txn_id) { int32_t ret = -1; glusterd_conf_t *priv = NULL; int32_t op = -1; int32_t op_ret = 0; int32_t op_errno = 0; - int32_t cli_op = 0; rpcsvc_request_t *req = NULL; void *ctx = NULL; - gf_boolean_t ctx_free = _gf_false; char *op_errstr = NULL; + char *volname = NULL; + xlator_t *this = NULL; + this = THIS; + GF_ASSERT (this); - priv = THIS->private; + priv = this->private; GF_ASSERT (priv); - ret = glusterd_unlock (priv->uuid); - - if (ret) { - gf_log ("glusterd", GF_LOG_CRITICAL, - "Unable to clear local lock, ret: %d", ret); - goto out; - } - - gf_log ("glusterd", GF_LOG_NORMAL, "Cleared local lock"); - + op = glusterd_op_get_op (); + ctx = glusterd_op_get_ctx (); op_ret = opinfo.op_ret; op_errno = opinfo.op_errno; - cli_op = opinfo.cli_op; req = opinfo.req; if (opinfo.op_errstr) op_errstr = opinfo.op_errstr; - opinfo.op_ret = 0; opinfo.op_errno = 0; + glusterd_op_clear_op (); + glusterd_op_reset_ctx (); + glusterd_op_clear_errstr (); + + /* Based on the op-version, we release the cluster or mgmt_v3 lock */ + if (priv->op_version < 3) { + ret = glusterd_unlock (MY_UUID); + /* unlock cant/shouldnt fail here!! */ + if (ret) + gf_log (this->name, GF_LOG_CRITICAL, + "Unable to clear local lock, ret: %d", ret); + else + gf_log (this->name, GF_LOG_DEBUG, "Cleared local lock"); + } else { + ret = dict_get_str (ctx, "volname", &volname); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to acquire volname"); - op = glusterd_op_get_op (); - - if (op != -1) { - glusterd_op_clear_pending_op (op); - glusterd_op_clear_commit_op (op); - glusterd_op_clear_op (op); - ctx = glusterd_op_get_ctx (op); - ctx_free = glusterd_op_get_ctx_free (op); - glusterd_op_reset_ctx (op); - glusterd_op_clear_ctx_free (op); - glusterd_op_clear_errstr (); + if (volname) { + ret = glusterd_mgmt_v3_unlock (volname, MY_UUID, + "vol"); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to release lock for %s", + volname); + } } -out: - pthread_mutex_unlock (&opinfo.lock); - ret = glusterd_op_send_cli_response (cli_op, op_ret, + ret = glusterd_op_send_cli_response (op, op_ret, op_errno, req, ctx, op_errstr); if (ret) { - gf_log ("", GF_LOG_ERROR, "Responding to cli failed, ret: %d", - ret); + gf_log (this->name, GF_LOG_ERROR, "Responding to cli failed, " + "ret: %d", ret); //Ignore this error, else state machine blocks ret = 0; } - if (ctx_free && ctx && (op != -1)) - glusterd_op_free_ctx (op, ctx, ctx_free); if (op_errstr && (strcmp (op_errstr, ""))) GF_FREE (op_errstr); - gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} -static int -glusterd_op_ac_unlocked_all (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; + if (priv->pending_quorum_action) + glusterd_do_quorum_action (); - GF_ASSERT (event); - - ret = glusterd_op_txn_complete (); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + /* Clearing the transaction opinfo */ + ret = glusterd_clear_txn_opinfo (txn_id); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to clear transaction's opinfo"); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } static int -glusterd_op_stage_quota (dict_t *dict, char **op_errstr) +glusterd_op_ac_unlocked_all (glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - - GF_ASSERT (dict); - GF_ASSERT (op_errstr); + int ret = 0; - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } + GF_ASSERT (event); - exists = glusterd_check_volume_exists (volname); - if (!exists) { - gf_log ("", GF_LOG_ERROR, "Volume with name: %s " - "does not exist", - volname); - *op_errstr = gf_strdup ("Invalid volume name"); - ret = -1; - goto out; - } + ret = glusterd_op_txn_complete (&event->txn_id); -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -6428,7 +4143,11 @@ glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) dict_t *rsp_dict = NULL; char *op_errstr = NULL; dict_t *dict = NULL; + xlator_t *this = NULL; + uuid_t *txn_id = NULL; + this = THIS; + GF_ASSERT (this); GF_ASSERT (ctx); req_ctx = ctx; @@ -6437,8 +4156,8 @@ glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) rsp_dict = dict_new (); if (!rsp_dict) { - gf_log ("", GF_LOG_DEBUG, - "Out of memory"); + gf_log (this->name, GF_LOG_ERROR, + "Failed to get new dictionary"); return -1; } @@ -6446,16 +4165,31 @@ glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) rsp_dict); if (status) { - gf_log ("", GF_LOG_ERROR, "Validate failed: %d", status); + gf_log (this->name, GF_LOG_ERROR, "Stage failed on operation" + " 'Volume %s', Status : %d", gd_op_list[req_ctx->op], + status); } + txn_id = GF_CALLOC (1, sizeof(uuid_t), gf_common_mt_uuid_t); + + if (txn_id) + uuid_copy (*txn_id, event->txn_id); + else + gf_log (this->name, GF_LOG_ERROR, "Out of Memory"); + + ret = dict_set_bin (rsp_dict, "transaction_id", + txn_id, sizeof(*txn_id)); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Failed to set transaction id."); + ret = glusterd_op_stage_send_resp (req_ctx->req, req_ctx->op, status, op_errstr, rsp_dict); if (op_errstr && (strcmp (op_errstr, ""))) GF_FREE (op_errstr); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); if (rsp_dict) dict_unref (rsp_dict); @@ -6463,38 +4197,109 @@ glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) return ret; } +static gf_boolean_t +glusterd_need_brick_op (glusterd_op_t op) +{ + gf_boolean_t ret = _gf_false; + + GF_ASSERT (GD_OP_NONE < op && op < GD_OP_MAX); + + switch (op) { + case GD_OP_PROFILE_VOLUME: + case GD_OP_STATUS_VOLUME: + case GD_OP_DEFRAG_BRICK_VOLUME: + case GD_OP_HEAL_VOLUME: + ret = _gf_true; + break; + default: + ret = _gf_false; + } + + return ret; +} + +dict_t* +glusterd_op_init_commit_rsp_dict (glusterd_op_t op) +{ + dict_t *rsp_dict = NULL; + dict_t *op_ctx = NULL; + + GF_ASSERT (GD_OP_NONE < op && op < GD_OP_MAX); + + if (glusterd_need_brick_op (op)) { + op_ctx = glusterd_op_get_ctx (); + GF_ASSERT (op_ctx); + rsp_dict = dict_ref (op_ctx); + } else { + rsp_dict = dict_new (); + } + + return rsp_dict; +} + static int glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) { int ret = 0; - glusterd_req_ctx_t *req_ctx = NULL; + glusterd_req_ctx_t *req_ctx = NULL; int32_t status = 0; char *op_errstr = NULL; - dict_t *op_ctx = NULL; dict_t *dict = NULL; + dict_t *rsp_dict = NULL; + xlator_t *this = NULL; + uuid_t *txn_id = NULL; + this = THIS; + GF_ASSERT (this); GF_ASSERT (ctx); req_ctx = ctx; dict = req_ctx->dict; - op_ctx = glusterd_op_get_ctx (req_ctx->op); - status = glusterd_op_commit_perform (req_ctx->op, dict, &op_errstr, - op_ctx); + rsp_dict = glusterd_op_init_commit_rsp_dict (req_ctx->op); + if (NULL == rsp_dict) + return -1; - if (status) { - gf_log ("", GF_LOG_ERROR, "Commit failed: %d", status); + + if (GD_OP_CLEARLOCKS_VOLUME == req_ctx->op) { + /*clear locks should be run only on + * originator glusterd*/ + status = 0; + + } else { + status = glusterd_op_commit_perform (req_ctx->op, dict, + &op_errstr, rsp_dict); } + if (status) + gf_log (this->name, GF_LOG_ERROR, "Commit of operation " + "'Volume %s' failed: %d", gd_op_list[req_ctx->op], + status); + + txn_id = GF_CALLOC (1, sizeof(uuid_t), gf_common_mt_uuid_t); + + if (txn_id) + uuid_copy (*txn_id, event->txn_id); + else + gf_log (this->name, GF_LOG_ERROR, "Out of Memory"); + + ret = dict_set_bin (rsp_dict, "transaction_id", + txn_id, sizeof(*txn_id)); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Failed to set transaction id."); + ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, - status, op_errstr, op_ctx); + status, op_errstr, rsp_dict); - glusterd_op_fini_ctx (req_ctx->op); if (op_errstr && (strcmp (op_errstr, ""))) GF_FREE (op_errstr); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + if (rsp_dict) + dict_unref (rsp_dict); + + gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } @@ -6510,19 +4315,18 @@ glusterd_op_ac_send_commit_failed (glusterd_op_sm_event_t *event, void *ctx) req_ctx = ctx; - op_ctx = glusterd_op_get_ctx (req_ctx->op); + op_ctx = glusterd_op_get_ctx (); ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, opinfo.op_ret, opinfo.op_errstr, op_ctx); - glusterd_op_fini_ctx (req_ctx->op); if (opinfo.op_errstr && (strcmp (opinfo.op_errstr, ""))) { GF_FREE (opinfo.op_errstr); opinfo.op_errstr = NULL; } - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } @@ -6553,6 +4357,7 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, dict_t *rsp_dict) { int ret = -1; + xlator_t *this = THIS; switch (op) { case GD_OP_CREATE_VOLUME: @@ -6589,11 +4394,7 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, break; case GD_OP_REMOVE_BRICK: - ret = glusterd_op_stage_remove_brick (dict); - break; - - case GD_OP_LOG_FILENAME: - ret = glusterd_op_stage_log_filename (dict, op_errstr); + ret = glusterd_op_stage_remove_brick (dict, op_errstr); break; case GD_OP_LOG_ROTATE: @@ -6604,6 +4405,10 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_stage_sync_volume (dict, op_errstr); break; + case GD_OP_GSYNC_CREATE: + ret = glusterd_op_stage_gsync_create (dict, op_errstr); + break; + case GD_OP_GSYNC_SET: ret = glusterd_op_stage_gsync_set (dict, op_errstr); break; @@ -6616,13 +4421,42 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_stage_quota (dict, op_errstr); break; + case GD_OP_STATUS_VOLUME: + ret = glusterd_op_stage_status_volume (dict, op_errstr); + break; + + case GD_OP_REBALANCE: + case GD_OP_DEFRAG_BRICK_VOLUME: + ret = glusterd_op_stage_rebalance (dict, op_errstr); + break; + + case GD_OP_HEAL_VOLUME: + ret = glusterd_op_stage_heal_volume (dict, op_errstr); + break; + + case GD_OP_STATEDUMP_VOLUME: + ret = glusterd_op_stage_statedump_volume (dict, + op_errstr); + break; + case GD_OP_CLEARLOCKS_VOLUME: + ret = glusterd_op_stage_clearlocks_volume (dict, + op_errstr); + break; + + case GD_OP_COPY_FILE: + ret = glusterd_op_stage_copy_file (dict, op_errstr); + break; + + case GD_OP_SYS_EXEC: + ret = glusterd_op_stage_sys_exec (dict, op_errstr); + break; + default: - gf_log ("", GF_LOG_ERROR, "Unknown op %d", - op); + gf_log (this->name, GF_LOG_ERROR, "Unknown op %s", + gd_op_list[op]); } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - + gf_log (this->name, GF_LOG_DEBUG, "OP = %d. Returning %d", op, ret); return ret; } @@ -6632,7 +4466,9 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, dict_t *rsp_dict) { int ret = -1; + xlator_t *this = THIS; + glusterd_op_commit_hook (op, dict, GD_COMMIT_HOOK_PRE); switch (op) { case GD_OP_CREATE_VOLUME: ret = glusterd_op_create_volume (dict, op_errstr); @@ -6663,15 +4499,11 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, break; case GD_OP_RESET_VOLUME: - ret = glusterd_op_reset_volume (dict); + ret = glusterd_op_reset_volume (dict, op_errstr); break; case GD_OP_REMOVE_BRICK: - ret = glusterd_op_remove_brick (dict); - break; - - case GD_OP_LOG_FILENAME: - ret = glusterd_op_log_filename (dict); + ret = glusterd_op_remove_brick (dict, op_errstr); break; case GD_OP_LOG_ROTATE: @@ -6682,8 +4514,13 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, ret = glusterd_op_sync_volume (dict, op_errstr, rsp_dict); break; + case GD_OP_GSYNC_CREATE: + ret = glusterd_op_gsync_create (dict, op_errstr, + rsp_dict); + break; + case GD_OP_GSYNC_SET: - ret = glusterd_op_gsync_set (dict); + ret = glusterd_op_gsync_set (dict, op_errstr, rsp_dict); break; case GD_OP_PROFILE_VOLUME: @@ -6692,98 +4529,56 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, break; case GD_OP_QUOTA: - ret = glusterd_op_quota (dict, op_errstr); + ret = glusterd_op_quota (dict, op_errstr, rsp_dict); break; - default: - gf_log ("", GF_LOG_ERROR, "Unknown op %d", - op); + case GD_OP_STATUS_VOLUME: + ret = glusterd_op_status_volume (dict, op_errstr, rsp_dict); break; - } - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -void -_profile_volume_add_brick_rsp (dict_t *this, char *key, data_t *value, - void *data) -{ - char new_key[256] = {0}; - glusterd_pr_brick_rsp_conv_t *rsp_ctx = NULL; - data_t *new_value = NULL; - - rsp_ctx = data; - new_value = data_copy (value); - GF_ASSERT (new_value); - snprintf (new_key, sizeof (new_key), "%d-%s", rsp_ctx->count, key); - dict_set (rsp_ctx->dict, new_key, new_value); -} + case GD_OP_REBALANCE: + case GD_OP_DEFRAG_BRICK_VOLUME: + ret = glusterd_op_rebalance (dict, op_errstr, rsp_dict); + break; -int -glusterd_profile_volume_brick_rsp (glusterd_brickinfo_t *brickinfo, - dict_t *rsp_dict, dict_t *op_ctx, - char **op_errstr) -{ - int ret = 0; - glusterd_pr_brick_rsp_conv_t rsp_ctx = {0}; - int32_t count = 0; - char brick[PATH_MAX+1024] = {0}; - char key[256] = {0}; - char *full_brick = NULL; - - GF_ASSERT (rsp_dict); - GF_ASSERT (op_ctx); - GF_ASSERT (op_errstr); - GF_ASSERT (brickinfo); + case GD_OP_HEAL_VOLUME: + ret = glusterd_op_heal_volume (dict, op_errstr); + break; - ret = dict_get_int32 (op_ctx, "count", &count); - if (ret) { - count = 1; - } else { - count++; - } - snprintf (key, sizeof (key), "%d-brick", count); - snprintf (brick, sizeof (brick), "%s:%s", brickinfo->hostname, - brickinfo->path); - full_brick = gf_strdup (brick); - GF_ASSERT (full_brick); - ret = dict_set_dynstr (op_ctx, key, full_brick); - - rsp_ctx.count = count; - rsp_ctx.dict = op_ctx; - dict_foreach (rsp_dict, _profile_volume_add_brick_rsp, &rsp_ctx); - dict_del (op_ctx, "count"); - ret = dict_set_int32 (op_ctx, "count", count); - return ret; -} + case GD_OP_STATEDUMP_VOLUME: + ret = glusterd_op_statedump_volume (dict, op_errstr); + break; -int32_t -glusterd_handle_brick_rsp (glusterd_brickinfo_t *brickinfo, - glusterd_op_t op, dict_t *rsp_dict, dict_t *op_ctx, - char **op_errstr) -{ - int ret = 0; + case GD_OP_CLEARLOCKS_VOLUME: + ret = glusterd_op_clearlocks_volume (dict, op_errstr, + rsp_dict); + break; - GF_ASSERT (op_errstr); + case GD_OP_COPY_FILE: + ret = glusterd_op_copy_file (dict, op_errstr); + break; - switch (op) { - case GD_OP_PROFILE_VOLUME: - ret = glusterd_profile_volume_brick_rsp (brickinfo, rsp_dict, - op_ctx, op_errstr); - break; + case GD_OP_SYS_EXEC: + ret = glusterd_op_sys_exec (dict, op_errstr, rsp_dict); + break; - default: - break; + default: + gf_log (this->name, GF_LOG_ERROR, "Unknown op %s", + gd_op_list[op]); + break; } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + if (ret == 0) + glusterd_op_commit_hook (op, dict, GD_COMMIT_HOOK_POST); + + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } + static int -glusterd_bricks_select_stop_volume (dict_t *dict, char **op_errstr) +glusterd_bricks_select_stop_volume (dict_t *dict, char **op_errstr, + struct list_head *selected) { int ret = 0; int flags = 0; @@ -6792,15 +4587,17 @@ glusterd_bricks_select_stop_volume (dict_t *dict, char **op_errstr) glusterd_brickinfo_t *brickinfo = NULL; glusterd_pending_node_t *pending_node = NULL; - ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); if (ret) goto out; ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS, + volname); + gf_asprintf (op_errstr, FMTSTR_CHECK_VOL_EXISTS, volname); goto out; + } list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { if (glusterd_is_brick_started (brickinfo)) { @@ -6811,7 +4608,8 @@ glusterd_bricks_select_stop_volume (dict_t *dict, char **op_errstr) goto out; } else { pending_node->node = brickinfo; - list_add_tail (&pending_node->list, &opinfo.pending_bricks); + pending_node->type = GD_NODE_BRICK; + list_add_tail (&pending_node->list, selected); pending_node = NULL; } } @@ -6822,7 +4620,8 @@ out: } static int -glusterd_bricks_select_remove_brick (dict_t *dict, char **op_errstr) +glusterd_bricks_select_remove_brick (dict_t *dict, char **op_errstr, + struct list_head *selected) { int ret = -1; char *volname = NULL; @@ -6833,6 +4632,9 @@ glusterd_bricks_select_remove_brick (dict_t *dict, char **op_errstr) int32_t i = 1; char key[256] = {0,}; glusterd_pending_node_t *pending_node = NULL; + int32_t force = 0; + + ret = dict_get_str (dict, "volname", &volname); @@ -6854,6 +4656,12 @@ glusterd_bricks_select_remove_brick (dict_t *dict, char **op_errstr) goto out; } + ret = dict_get_int32 (dict, "force", &force); + if (ret) { + gf_log (THIS->name, GF_LOG_INFO, "force flag is not set"); + ret = 0; + goto out; + } while ( i <= count) { snprintf (key, 256, "brick%d", i); @@ -6875,7 +4683,8 @@ glusterd_bricks_select_remove_brick (dict_t *dict, char **op_errstr) goto out; } else { pending_node->node = brickinfo; - list_add_tail (&pending_node->list, &opinfo.pending_bricks); + pending_node->type = GD_NODE_BRICK; + list_add_tail (&pending_node->list, selected); pending_node = NULL; } } @@ -6887,7 +4696,8 @@ out: } static int -glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) +glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr, + struct list_head *selected) { int ret = -1; char *volname = NULL; @@ -6900,11 +4710,14 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) glusterd_pending_node_t *pending_node = NULL; char *brick = NULL; + + this = THIS; GF_ASSERT (this); priv = this->private; GF_ASSERT (priv); + ret = dict_get_str (dict, "volname", &volname); if (ret) { gf_log ("glusterd", GF_LOG_ERROR, "volume name get failed"); @@ -6933,6 +4746,29 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) goto out; break; case GF_CLI_STATS_INFO: + ret = dict_get_str_boolean (dict, "nfs", _gf_false); + if (ret) { + if (!glusterd_is_nodesvc_online ("nfs")) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "NFS server" + " is not running"); + goto out; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = priv->nfs; + pending_node->type = GD_NODE_NFS; + list_add_tail (&pending_node->list, selected); + pending_node = NULL; + + ret = 0; + goto out; + + } list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { if (glusterd_is_brick_started (brickinfo)) { pending_node = GF_CALLOC (1, sizeof (*pending_node), @@ -6942,8 +4778,9 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) goto out; } else { pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; list_add_tail (&pending_node->list, - &opinfo.pending_bricks); + selected); pending_node = NULL; } } @@ -6951,13 +4788,39 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) break; case GF_CLI_STATS_TOP: + ret = dict_get_str_boolean (dict, "nfs", _gf_false); + if (ret) { + if (!glusterd_is_nodesvc_online ("nfs")) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, "NFS server" + " is not running"); + goto out; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = priv->nfs; + pending_node->type = GD_NODE_NFS; + list_add_tail (&pending_node->list, selected); + pending_node = NULL; + + ret = 0; + goto out; + + } ret = dict_get_str (dict, "brick", &brick); if (!ret) { - ret = glusterd_volume_brickinfo_get_by_brick (brick, - volinfo, &brickinfo); + ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, + &brickinfo); if (ret) goto out; + if (!glusterd_is_brick_started (brickinfo)) + goto out; + pending_node = GF_CALLOC (1, sizeof (*pending_node), gf_gld_mt_pending_node_t); if (!pending_node) { @@ -6965,8 +4828,9 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) goto out; } else { pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; list_add_tail (&pending_node->list, - &opinfo.pending_bricks); + selected); pending_node = NULL; goto out; } @@ -6981,8 +4845,9 @@ glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) goto out; } else { pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; list_add_tail (&pending_node->list, - &opinfo.pending_bricks); + selected); pending_node = NULL; } } @@ -7006,6 +4871,631 @@ out: } static int +_add_rxlator_to_dict (dict_t *dict, char *volname, int index, int count) +{ + int ret = -1; + char key[128] = {0,}; + char *xname = NULL; + + snprintf (key, sizeof (key), "xl-%d", count); + ret = gf_asprintf (&xname, "%s-replicate-%d", volname, index); + if (ret == -1) + goto out; + + ret = dict_set_dynstr (dict, key, xname); + if (ret) + goto out; + + ret = dict_set_int32 (dict, xname, index); +out: + return ret; +} + +int +get_replica_index_for_per_replica_cmd (glusterd_volinfo_t *volinfo, + dict_t *dict) { + int ret = 0; + char *hostname = NULL; + char *path = NULL; + int index = 0; + glusterd_brickinfo_t *brickinfo = NULL; + int cmd_replica_index = -1; + int replica_count = -1; + + + if (!dict) { + ret = -1; + goto out; + } + + ret = dict_get_str (dict, "per-replica-cmd-hostname", &hostname); + if (ret) + goto out; + ret = dict_get_str (dict, "per-replica-cmd-path", &path); + if (ret) + goto out; + + replica_count = volinfo->replica_count; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_is_null (brickinfo->uuid)) + (void)glusterd_resolve_brick (brickinfo); + if (!strcmp (brickinfo->path, path) && + !strcmp (brickinfo->hostname, hostname)) { + cmd_replica_index = index/(replica_count); + goto out; + } + index++; + } + + +out: + if (ret) + cmd_replica_index = -1; + + return cmd_replica_index; +} + +int +_select_rxlators_with_local_bricks (xlator_t *this, glusterd_volinfo_t *volinfo, + dict_t *dict, cli_cmd_type type) +{ + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_conf_t *priv = NULL; + int index = 0; + int rxlator_count = 0; + int replica_count = 0; + gf_boolean_t add = _gf_false; + int ret = 0; + int cmd_replica_index = -1; + + priv = this->private; + replica_count = volinfo->replica_count; + + if (type == PER_REPLICA) { + + cmd_replica_index = get_replica_index_for_per_replica_cmd + (volinfo, dict); + if (cmd_replica_index == -1) { + ret = -1; + goto err; + } + } + + index = 1; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_is_null (brickinfo->uuid)) + (void)glusterd_resolve_brick (brickinfo); + + switch (type) { + case ALL_REPLICA: + if (!uuid_compare (MY_UUID, brickinfo->uuid)) + add = _gf_true; + break; + case PER_REPLICA: + if (!uuid_compare (MY_UUID, brickinfo->uuid) && + ((index-1)/replica_count == cmd_replica_index)) + + add = _gf_true; + break; + } + + if (index % replica_count == 0) { + if (add) { + _add_rxlator_to_dict (dict, volinfo->volname, + (index-1)/replica_count, + rxlator_count); + rxlator_count++; + } + add = _gf_false; + } + + index++; + } +err: + if (ret) + rxlator_count = -1; + + return rxlator_count; +} + +int +_select_rxlators_for_full_self_heal (xlator_t *this, + glusterd_volinfo_t *volinfo, + dict_t *dict) +{ + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_conf_t *priv = NULL; + int index = 1; + int rxlator_count = 0; + int replica_count = 0; + uuid_t candidate = {0}; + + priv = this->private; + replica_count = volinfo->replica_count; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_is_null (brickinfo->uuid)) + (void)glusterd_resolve_brick (brickinfo); + + if (uuid_compare (brickinfo->uuid, candidate) > 0) + uuid_copy (candidate, brickinfo->uuid); + + if (index % replica_count == 0) { + if (!uuid_compare (MY_UUID, candidate)) { + _add_rxlator_to_dict (dict, volinfo->volname, + (index-1)/replica_count, + rxlator_count); + rxlator_count++; + } + uuid_clear (candidate); + } + + index++; + } + return rxlator_count; +} + + +static int +glusterd_bricks_select_snap (dict_t *dict, char **op_errstr, + struct list_head *selected) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + glusterd_pending_node_t *pending_node = NULL; + glusterd_volinfo_t *volinfo = NULL; + char *volname = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + int brick_index = -1; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to get" + " volname"); + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) + goto out; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + brick_index++; + if (uuid_compare (brickinfo->uuid, MY_UUID) || + !glusterd_is_brick_started (brickinfo)) { + continue; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + pending_node->index = brick_index; + list_add_tail (&pending_node->list, + selected); + pending_node = NULL; + } + + ret = 0; + +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning ret %d", ret); + return ret; +} + +static int +fill_shd_status_for_local_bricks (dict_t *dict, glusterd_volinfo_t *volinfo, + cli_cmd_type type, dict_t *req_dict) +{ + glusterd_brickinfo_t *brickinfo = NULL; + char msg[1024] = {0,}; + char key[1024] = {0,}; + char value[1024] = {0,}; + int index = 0; + int ret = 0; + xlator_t *this = NULL; + int cmd_replica_index = -1; + + this = THIS; + snprintf (msg, sizeof (msg), "self-heal-daemon is not running on"); + + if (type == PER_REPLICA) { + cmd_replica_index = get_replica_index_for_per_replica_cmd + (volinfo, req_dict); + if (cmd_replica_index == -1) { + gf_log (THIS->name, GF_LOG_ERROR, "Could not find the " + "replica index for per replica type command"); + ret = -1; + goto out; + } + } + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_is_null (brickinfo->uuid)) + (void)glusterd_resolve_brick (brickinfo); + + if (uuid_compare (MY_UUID, brickinfo->uuid)) { + index++; + continue; + } + + if (type == PER_REPLICA) { + if (cmd_replica_index != (index/volinfo->replica_count)) { + index++; + continue; + } + + } + snprintf (key, sizeof (key), "%d-status",index); + snprintf (value, sizeof (value), "%s %s",msg, + uuid_utoa(MY_UUID)); + ret = dict_set_dynstr (dict, key, gf_strdup(value)); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to" + "set the dictionary for shd status msg"); + goto out; + } + snprintf (key, sizeof (key), "%d-shd-status",index); + ret = dict_set_str (dict, key, "off"); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to" + " set dictionary for shd status msg"); + goto out; + } + + index++; + } + +out: + return ret; + +} + + +static int +glusterd_bricks_select_heal_volume (dict_t *dict, char **op_errstr, + struct list_head *selected, + dict_t *rsp_dict) +{ + int ret = -1; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + char msg[2048] = {0,}; + glusterd_pending_node_t *pending_node = NULL; + gf_xl_afr_op_t heal_op = GF_AFR_OP_INVALID; + int rxlator_count = 0; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume name get failed"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof (msg), "Volume %s does not exist", + volname); + + *op_errstr = gf_strdup (msg); + gf_log ("", GF_LOG_ERROR, "%s", msg); + goto out; + } + + ret = dict_get_int32 (dict, "heal-op", (int32_t*)&heal_op); + if (ret || (heal_op == GF_AFR_OP_INVALID)) { + gf_log ("glusterd", GF_LOG_ERROR, "heal op invalid"); + goto out; + } + + switch (heal_op) { + case GF_AFR_OP_INDEX_SUMMARY: + case GF_AFR_OP_STATISTICS_HEAL_COUNT: + if (!glusterd_is_nodesvc_online ("glustershd")) { + if (!rsp_dict) { + gf_log (this->name, GF_LOG_ERROR, "Received " + "empty ctx."); + goto out; + } + + ret = fill_shd_status_for_local_bricks (rsp_dict, + volinfo, + ALL_REPLICA, + dict); + if (ret) + gf_log (this->name, GF_LOG_ERROR, "Unable to " + "fill the shd status for the local " + "bricks"); + goto out; + + } + break; + case GF_AFR_OP_STATISTICS_HEAL_COUNT_PER_REPLICA: + if (!glusterd_is_nodesvc_online ("glustershd")) { + if (!rsp_dict) { + gf_log (this->name, GF_LOG_ERROR, "Received " + "empty ctx."); + goto out; + } + ret = fill_shd_status_for_local_bricks (rsp_dict, + volinfo, + PER_REPLICA, + dict); + if (ret) + gf_log (this->name, GF_LOG_ERROR, "Unable to " + "fill the shd status for the local" + " bricks."); + goto out; + + } + break; + default: + break; + } + + + switch (heal_op) { + case GF_AFR_OP_HEAL_FULL: + rxlator_count = _select_rxlators_for_full_self_heal (this, + volinfo, + dict); + break; + case GF_AFR_OP_STATISTICS_HEAL_COUNT_PER_REPLICA: + rxlator_count = _select_rxlators_with_local_bricks (this, + volinfo, + dict, + PER_REPLICA); + break; + default: + rxlator_count = _select_rxlators_with_local_bricks (this, + volinfo, + dict, + ALL_REPLICA); + break; + } + if (!rxlator_count) + goto out; + if (rxlator_count == -1){ + gf_log (this->name, GF_LOG_ERROR, "Could not determine the" + "translator count"); + ret = -1; + goto out; + } + + ret = dict_set_int32 (dict, "count", rxlator_count); + if (ret) + goto out; + + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } else { + pending_node->node = priv->shd; + pending_node->type = GD_NODE_SHD; + list_add_tail (&pending_node->list, selected); + pending_node = NULL; + } + +out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning ret %d", ret); + return ret; + +} + +static int +glusterd_bricks_select_rebalance_volume (dict_t *dict, char **op_errstr, + struct list_head *selected) +{ + int ret = -1; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + char msg[2048] = {0,}; + glusterd_pending_node_t *pending_node = NULL; + + this = THIS; + GF_ASSERT (this); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "volume name get failed"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (msg, sizeof (msg), "Volume %s does not exist", + volname); + + *op_errstr = gf_strdup (msg); + gf_log ("", GF_LOG_ERROR, "%s", msg); + goto out; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } else { + pending_node->node = volinfo; + pending_node->type = GD_NODE_REBALANCE; + list_add_tail (&pending_node->list, + &opinfo.pending_bricks); + pending_node = NULL; + } + +out: + return ret; +} + + + + +static int +glusterd_bricks_select_status_volume (dict_t *dict, char **op_errstr, + struct list_head *selected) +{ + int ret = -1; + int cmd = 0; + int brick_index = -1; + char *volname = NULL; + char *brickname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_pending_node_t *pending_node = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (dict); + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + ret = dict_get_int32 (dict, "cmd", &cmd); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to get status type"); + goto out; + } + + if (cmd & GF_CLI_STATUS_ALL) + goto out; + + switch (cmd & GF_CLI_STATUS_MASK) { + case GF_CLI_STATUS_MEM: + case GF_CLI_STATUS_CLIENTS: + case GF_CLI_STATUS_INODE: + case GF_CLI_STATUS_FD: + case GF_CLI_STATUS_CALLPOOL: + case GF_CLI_STATUS_NFS: + case GF_CLI_STATUS_SHD: + break; + default: + goto out; + } + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to get volname"); + goto out; + } + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + goto out; + } + + if ( (cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brickname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to get brick"); + goto out; + } + ret = glusterd_volume_brickinfo_get_by_brick (brickname, + volinfo, + &brickinfo); + if (ret) + goto out; + + if (uuid_compare (brickinfo->uuid, MY_UUID)|| + !glusterd_is_brick_started (brickinfo)) + goto out; + + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + pending_node->index = 0; + list_add_tail (&pending_node->list, selected); + + ret = 0; + } else if ((cmd & GF_CLI_STATUS_NFS) != 0) { + if (!glusterd_is_nodesvc_online ("nfs")) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "NFS server is not running"); + goto out; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = priv->nfs; + pending_node->type = GD_NODE_NFS; + pending_node->index = 0; + list_add_tail (&pending_node->list, selected); + + ret = 0; + } else if ((cmd & GF_CLI_STATUS_SHD) != 0) { + if (!glusterd_is_nodesvc_online ("glustershd")) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "Self-heal daemon is not running"); + goto out; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + goto out; + } + pending_node->node = priv->shd; + pending_node->type = GD_NODE_SHD; + pending_node->index = 0; + list_add_tail (&pending_node->list, selected); + + ret = 0; + } else { + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + brick_index++; + if (uuid_compare (brickinfo->uuid, MY_UUID) || + !glusterd_is_brick_started (brickinfo)) { + continue; + } + pending_node = GF_CALLOC (1, sizeof (*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + ret = -1; + gf_log (THIS->name ,GF_LOG_ERROR, + "Unable to allocate memory"); + goto out; + } + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + pending_node->index = brick_index; + list_add_tail (&pending_node->list, selected); + pending_node = NULL; + } + } +out: + return ret; +} + +static int glusterd_op_ac_send_brick_op (glusterd_op_sm_event_t *event, void *ctx) { int ret = 0; @@ -7014,6 +5504,7 @@ glusterd_op_ac_send_brick_op (glusterd_op_sm_event_t *event, void *ctx) xlator_t *this = NULL; glusterd_op_t op = GD_OP_NONE; glusterd_req_ctx_t *req_ctx = NULL; + char *op_errstr = NULL; this = THIS; priv = this->private; @@ -7025,13 +5516,21 @@ glusterd_op_ac_send_brick_op (glusterd_op_sm_event_t *event, void *ctx) gf_gld_mt_op_allack_ctx_t); op = glusterd_op_get_op (); req_ctx->op = op; - uuid_copy (req_ctx->uuid, priv->uuid); - ret = glusterd_op_build_payload (op, &req_ctx->dict); - if (ret)//TODO:what to do?? + uuid_copy (req_ctx->uuid, MY_UUID); + ret = glusterd_op_build_payload (&req_ctx->dict, &op_errstr, + NULL); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, LOGSTR_BUILD_PAYLOAD, + gd_op_list[op]); + if (op_errstr == NULL) + gf_asprintf (&op_errstr, + OPERRSTR_BUILD_PAYLOAD); + opinfo.op_errstr = op_errstr; goto out; + } } - proc = &priv->gfs_mgmt->proctable[GD_MGMT_BRICK_OP]; + proc = &priv->gfs_mgmt->proctable[GLUSTERD_BRICK_OP]; if (proc->fn) { ret = proc->fn (NULL, this, req_ctx); if (ret) @@ -7040,11 +5539,12 @@ glusterd_op_ac_send_brick_op (glusterd_op_sm_event_t *event, void *ctx) if (!opinfo.pending_count && !opinfo.brick_pending_count) { glusterd_clear_pending_nodes (&opinfo.pending_bricks); - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, req_ctx); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, + &event->txn_id, req_ctx); } out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } @@ -7055,13 +5555,16 @@ glusterd_op_ac_rcvd_brick_op_acc (glusterd_op_sm_event_t *event, void *ctx) { int ret = 0; glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; - glusterd_brickinfo_t *brickinfo = NULL; char *op_errstr = NULL; glusterd_op_t op = GD_OP_NONE; + gd_node_type type = GD_NODE_NONE; dict_t *op_ctx = NULL; - gf_boolean_t free_errstr = _gf_true; glusterd_req_ctx_t *req_ctx = NULL; + void *pending_entry = NULL; + xlator_t *this = NULL; + this = THIS; + GF_ASSERT (this); GF_ASSERT (event); GF_ASSERT (ctx); ev_ctx = ctx; @@ -7069,41 +5572,43 @@ glusterd_op_ac_rcvd_brick_op_acc (glusterd_op_sm_event_t *event, void *ctx) req_ctx = ev_ctx->commit_ctx; GF_ASSERT (req_ctx); - brickinfo = ev_ctx->brickinfo; - GF_ASSERT (brickinfo); + op = req_ctx->op; + op_ctx = glusterd_op_get_ctx (); + pending_entry = ev_ctx->pending_node->node; + type = ev_ctx->pending_node->type; - ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, brickinfo); + ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, + pending_entry); if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "unknown response received " - "from %s:%s", brickinfo->hostname, brickinfo->path); + gf_log (this->name, GF_LOG_ERROR, "unknown response received "); ret = -1; - free_errstr = _gf_true; goto out; } if (opinfo.brick_pending_count > 0) opinfo.brick_pending_count--; - op = req_ctx->op; - op_ctx = glusterd_op_get_ctx (op); - glusterd_handle_brick_rsp (brickinfo, op, ev_ctx->rsp_dict, - op_ctx, &op_errstr); + glusterd_handle_node_rsp (req_ctx->dict, pending_entry, op, ev_ctx->rsp_dict, + op_ctx, &op_errstr, type); + if (opinfo.brick_pending_count > 0) goto out; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, ev_ctx->commit_ctx); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, &event->txn_id, + ev_ctx->commit_ctx); out: if (ev_ctx->rsp_dict) dict_unref (ev_ctx->rsp_dict); GF_FREE (ev_ctx); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } int32_t -glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr) +glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr, + struct list_head *selected, dict_t *rsp_dict) { int ret = 0; @@ -7114,22 +5619,42 @@ glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr) switch (op) { case GD_OP_STOP_VOLUME: - ret = glusterd_bricks_select_stop_volume (dict, op_errstr); + ret = glusterd_bricks_select_stop_volume (dict, op_errstr, + selected); break; case GD_OP_REMOVE_BRICK: - ret = glusterd_bricks_select_remove_brick (dict, op_errstr); + ret = glusterd_bricks_select_remove_brick (dict, op_errstr, + selected); break; case GD_OP_PROFILE_VOLUME: - ret = glusterd_bricks_select_profile_volume (dict, op_errstr); + ret = glusterd_bricks_select_profile_volume (dict, op_errstr, + selected); + break; + + case GD_OP_HEAL_VOLUME: + ret = glusterd_bricks_select_heal_volume (dict, op_errstr, + selected, rsp_dict); break; + case GD_OP_STATUS_VOLUME: + ret = glusterd_bricks_select_status_volume (dict, op_errstr, + selected); + break; + + case GD_OP_DEFRAG_BRICK_VOLUME: + ret = glusterd_bricks_select_rebalance_volume (dict, op_errstr, + selected); + break; + case GD_OP_SNAP: + ret = glusterd_bricks_select_snap (dict, op_errstr, selected); + break; default: break; } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -7148,30 +5673,32 @@ glusterd_op_sm_t glusterd_op_state_default [] = { {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_lock_sent [] = { {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_rcvd_lock_acc}, //EVENT_RCVD_ACC {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_send_stage_op}, //EVENT_ALL_ACC {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_RCVD_RJT + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_send_unlock_drain}, //EVENT_RCVD_RJT {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_locked [] = { {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_LOCKED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_LOCKED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_RCVD_ACC {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7182,30 +5709,32 @@ glusterd_op_sm_t glusterd_op_state_locked [] = { {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_local_unlock}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_stage_op_sent [] = { {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_rcvd_stage_op_acc}, //EVENT_RCVD_ACC - {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_send_brick_op}, //EVENT_ALL_ACC + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_send_brick_op}, //EVENT_ALL_ACC {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_send_brick_op}, //EVENT_STAGE_ACC {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_stage_op_failed}, //EVENT_RCVD_RJT {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_stage_op_failed [] = { {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_stage_op_failed}, //EVENT_RCVD_ACC {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7214,15 +5743,16 @@ glusterd_op_sm_t glusterd_op_state_stage_op_failed [] = { {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK + {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_STAGE_OP_FAILED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_staged [] = { {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_STAGED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_STAGED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_RCVD_ACC {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7233,13 +5763,14 @@ glusterd_op_sm_t glusterd_op_state_staged [] = { {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_local_unlock}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_brick_op_sent [] = { {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_rcvd_brick_op_acc}, //EVENT_RCVD_ACC {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7248,15 +5779,16 @@ glusterd_op_sm_t glusterd_op_state_brick_op_sent [] = { {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_BRICK_OP {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_send_commit_op}, //EVENT_ALL_ACK + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_brick_op_failed [] = { {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_ACC {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7265,15 +5797,16 @@ glusterd_op_sm_t glusterd_op_state_brick_op_failed [] = { {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_BRICK_OP {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_brick_committed [] = { {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_rcvd_brick_op_acc}, //EVENT_RCVD_ACC {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7284,13 +5817,14 @@ glusterd_op_sm_t glusterd_op_state_brick_committed [] = { {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_COMMITED, glusterd_op_ac_commit_op}, //EVENT_ALL_ACK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_local_unlock}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_brick_commit_failed [] = { {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_ACC {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7301,13 +5835,14 @@ glusterd_op_sm_t glusterd_op_state_brick_commit_failed [] = { {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_send_commit_failed}, //EVENT_ALL_ACK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_local_unlock}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_commit_op_failed [] = { {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_commit_op_failed}, //EVENT_RCVD_ACC {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7316,15 +5851,16 @@ glusterd_op_sm_t glusterd_op_state_commit_op_failed [] = { {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_commit_op_sent [] = { {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_rcvd_commit_op_acc}, //EVENT_RCVD_ACC {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACC {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7333,15 +5869,16 @@ glusterd_op_sm_t glusterd_op_state_commit_op_sent [] = { {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_START_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_committed [] = { {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_COMMITED, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_COMMITED, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_RCVD_ACC {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_ALL_ACC {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_STAGE_ACC @@ -7352,26 +5889,45 @@ glusterd_op_sm_t glusterd_op_state_committed [] = { {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_local_unlock}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_MAX }; glusterd_op_sm_t glusterd_op_state_unlock_sent [] = { {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_NONE {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none},//EVENT_START_LOCK - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_LOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_lock}, //EVENT_LOCK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_rcvd_unlock_acc}, //EVENT_RCVD_ACC {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlocked_all}, //EVENT_ALL_ACC {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_ACC {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_RCVD_RJT + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_rcvd_unlock_acc}, //EVENT_RCVD_RJT {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_STAGE_OP {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_MAX }; +glusterd_op_sm_t glusterd_op_state_ack_drain [] = { + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_NONE + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none},//EVENT_START_LOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_lock}, //EVENT_LOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_send_unlock_drain}, //EVENT_RCVD_ACC + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_ALL_ACC + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_STAGE_ACC + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_COMMIT_ACC + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_send_unlock_drain}, //EVENT_RCVD_RJT + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_STAGE_OP + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_COMMIT_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_unlock}, //EVENT_UNLOCK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_START_UNLOCK + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_LOCAL_UNLOCK_NO_RESP + {GD_OP_STATE_ACK_DRAIN, glusterd_op_ac_none}, //EVENT_MAX +}; glusterd_op_sm_t *glusterd_op_state_table [] = { glusterd_op_state_default, @@ -7387,7 +5943,8 @@ glusterd_op_sm_t *glusterd_op_state_table [] = { glusterd_op_state_brick_op_sent, glusterd_op_state_brick_op_failed, glusterd_op_state_brick_committed, - glusterd_op_state_brick_commit_failed + glusterd_op_state_brick_commit_failed, + glusterd_op_state_ack_drain }; int @@ -7414,7 +5971,7 @@ glusterd_op_sm_new_event (glusterd_op_sm_event_type_t event_type, int glusterd_op_sm_inject_event (glusterd_op_sm_event_type_t event_type, - void *ctx) + uuid_t *txn_id, void *ctx) { int32_t ret = -1; glusterd_op_sm_event_t *event = NULL; @@ -7429,7 +5986,10 @@ glusterd_op_sm_inject_event (glusterd_op_sm_event_type_t event_type, event->ctx = ctx; - gf_log ("glusterd", GF_LOG_DEBUG, "Enqueuing event: '%s'", + if (txn_id) + uuid_copy (event->txn_id, *txn_id); + + gf_log (THIS->name, GF_LOG_DEBUG, "Enqueue event: '%s'", glusterd_op_sm_event_name_get (event->event)); list_add_tail (&event->list, &gd_op_sm_queue); @@ -7448,6 +6008,14 @@ glusterd_destroy_req_ctx (glusterd_req_ctx_t *ctx) } void +glusterd_destroy_local_unlock_ctx (uuid_t *ctx) +{ + if (!ctx) + return; + GF_FREE (ctx); +} + +void glusterd_destroy_op_event_ctx (glusterd_op_sm_event_t *event) { if (!event) @@ -7462,6 +6030,9 @@ glusterd_destroy_op_event_ctx (glusterd_op_sm_event_t *event) case GD_OP_EVENT_ALL_ACK: glusterd_destroy_req_ctx (event->ctx); break; + case GD_OP_EVENT_LOCAL_UNLOCK_NO_RESP: + glusterd_destroy_local_unlock_ctx (event->ctx); + break; default: break; } @@ -7473,11 +6044,21 @@ glusterd_op_sm () glusterd_op_sm_event_t *event = NULL; glusterd_op_sm_event_t *tmp = NULL; int ret = -1; + int lock_err = 0; glusterd_op_sm_ac_fn handler = NULL; glusterd_op_sm_t *state = NULL; glusterd_op_sm_event_type_t event_type = GD_OP_EVENT_NONE; + xlator_t *this = NULL; + glusterd_op_info_t txn_op_info; - (void ) pthread_mutex_lock (&gd_op_sm_lock); + this = THIS; + GF_ASSERT (this); + + if ((lock_err = pthread_mutex_trylock (&gd_op_sm_lock))) { + gf_log (this->name, GF_LOG_ERROR, "lock failed due to %s", + strerror (lock_err)); + goto lock_failed; + } while (!list_empty (&gd_op_sm_queue)) { @@ -7485,9 +6066,24 @@ glusterd_op_sm () list_del_init (&event->list); event_type = event->event; - gf_log ("", GF_LOG_DEBUG, "Dequeued event of type: '%s'", + gf_log (this->name, GF_LOG_DEBUG, "Dequeued event of " + "type: '%s'", glusterd_op_sm_event_name_get(event_type)); + gf_log ("", GF_LOG_DEBUG, "transaction ID = %s", + uuid_utoa (event->txn_id)); + + ret = glusterd_get_txn_opinfo (&event->txn_id, + &txn_op_info); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to get transaction's opinfo"); + glusterd_destroy_op_event_ctx (event); + GF_FREE (event); + continue; + } else + opinfo = txn_op_info; + state = glusterd_op_state_table[opinfo.state.state]; GF_ASSERT (state); @@ -7498,7 +6094,7 @@ glusterd_op_sm () ret = handler (event, event->ctx); if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "handler returned: %d", ret); glusterd_destroy_op_event_ctx (event); GF_FREE (event); @@ -7509,7 +6105,7 @@ glusterd_op_sm () event_type); if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "Unable to transition" "state from '%s' to '%s'", glusterd_op_sm_state_name_get(opinfo.state.state), @@ -7518,8 +6114,27 @@ glusterd_op_sm () return ret; } + if ((state[event_type].next_state == + GD_OP_STATE_DEFAULT) && + (event_type == GD_OP_EVENT_UNLOCK)) { + /* Clearing the transaction opinfo */ + ret = glusterd_clear_txn_opinfo(&event->txn_id); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to clear " + "transaction's opinfo"); + } else { + ret = glusterd_set_txn_opinfo (&event->txn_id, + &opinfo); + if (ret) + gf_log (this->name, GF_LOG_ERROR, + "Unable to set " + "transaction's opinfo"); + } + glusterd_destroy_op_event_ctx (event); GF_FREE (event); + } } @@ -7527,6 +6142,8 @@ glusterd_op_sm () (void ) pthread_mutex_unlock (&gd_op_sm_lock); ret = 0; +lock_failed: + return ret; } @@ -7537,9 +6154,7 @@ glusterd_op_set_op (glusterd_op_t op) GF_ASSERT (op < GD_OP_MAX); GF_ASSERT (op > GD_OP_NONE); - opinfo.op[op] = 1; - opinfo.pending_op[op] = 1; - opinfo.commit_op[op] = 1; + opinfo.op = op; return 0; @@ -7549,40 +6164,8 @@ int32_t glusterd_op_get_op () { - int i = 0; - int32_t ret = 0; - - for ( i = 0; i < GD_OP_MAX; i++) { - if (opinfo.op[i]) - break; - } - - if ( i == GD_OP_MAX) - ret = -1; - else - ret = i; - - return ret; - -} - - -int32_t -glusterd_op_set_cli_op (glusterd_op_t op) -{ - - int32_t ret = 0; - - ret = pthread_mutex_trylock (&opinfo.lock); + return opinfo.op; - if (ret) - goto out; - - opinfo.cli_op = op; - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; } int32_t @@ -7595,103 +6178,27 @@ glusterd_op_set_req (rpcsvc_request_t *req) } int32_t -glusterd_op_clear_pending_op (glusterd_op_t op) -{ - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - opinfo.pending_op[op] = 0; - - return 0; - -} - -int32_t -glusterd_op_clear_commit_op (glusterd_op_t op) -{ - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - opinfo.commit_op[op] = 0; - - return 0; - -} - -int32_t glusterd_op_clear_op (glusterd_op_t op) { - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - opinfo.op[op] = 0; + opinfo.op = GD_OP_NONE; return 0; } int32_t -glusterd_op_init_ctx (glusterd_op_t op) -{ - int ret = 0; - dict_t *dict = NULL; - - if (GD_OP_PROFILE_VOLUME != op) { - gf_log ("", GF_LOG_DEBUG, "Received op: %d, returning", op); - goto out; - } - dict = dict_new (); - if (dict == NULL) { - ret = -1; - goto out; - } - ret = glusterd_op_set_ctx (op, dict); - if (ret) - goto out; - ret = glusterd_op_set_ctx_free (op, _gf_true); - if (ret) - goto out; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - - - -int32_t -glusterd_op_fini_ctx (glusterd_op_t op) +glusterd_op_free_ctx (glusterd_op_t op, void *ctx) { - dict_t *dict = NULL; - if (glusterd_op_get_ctx_free (op)) { - dict = glusterd_op_get_ctx (op); - if (dict) - dict_unref (dict); - } - glusterd_op_reset_ctx (op); - return 0; -} - - - -int32_t -glusterd_op_free_ctx (glusterd_op_t op, void *ctx, gf_boolean_t ctx_free) -{ - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - if (ctx && ctx_free) { + if (ctx) { switch (op) { case GD_OP_CREATE_VOLUME: + case GD_OP_DELETE_VOLUME: case GD_OP_STOP_VOLUME: case GD_OP_ADD_BRICK: case GD_OP_REMOVE_BRICK: case GD_OP_REPLACE_BRICK: - case GD_OP_LOG_FILENAME: case GD_OP_LOG_ROTATE: case GD_OP_SYNC_VOLUME: case GD_OP_SET_VOLUME: @@ -7700,63 +6207,30 @@ glusterd_op_free_ctx (glusterd_op_t op, void *ctx, gf_boolean_t ctx_free) case GD_OP_GSYNC_SET: case GD_OP_QUOTA: case GD_OP_PROFILE_VOLUME: + case GD_OP_STATUS_VOLUME: + case GD_OP_REBALANCE: + case GD_OP_HEAL_VOLUME: + case GD_OP_STATEDUMP_VOLUME: + case GD_OP_CLEARLOCKS_VOLUME: + case GD_OP_DEFRAG_BRICK_VOLUME: dict_unref (ctx); break; - case GD_OP_DELETE_VOLUME: - GF_FREE (ctx); - break; default: GF_ASSERT (0); break; } } - return 0; - -} - -void * -glusterd_op_get_ctx (glusterd_op_t op) -{ - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - return opinfo.op_ctx[op]; - -} - -int32_t -glusterd_op_set_ctx_free (glusterd_op_t op, gf_boolean_t ctx_free) -{ - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - opinfo.ctx_free[op] = ctx_free; + glusterd_op_reset_ctx (); return 0; } -int32_t -glusterd_op_clear_ctx_free (glusterd_op_t op) -{ - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - opinfo.ctx_free[op] = _gf_false; - - return 0; - -} - -gf_boolean_t -glusterd_op_get_ctx_free (glusterd_op_t op) +void * +glusterd_op_get_ctx () { - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - return opinfo.ctx_free[op]; + return opinfo.op_ctx; } @@ -7767,165 +6241,3 @@ glusterd_op_sm_init () pthread_mutex_init (&gd_op_sm_lock, NULL); return 0; } - -int32_t -glusterd_opinfo_unlock(){ - return (pthread_mutex_unlock(&opinfo.lock)); -} -int32_t -glusterd_volume_stats_write_perf (char *brick_path, int32_t blk_size, - int32_t blk_count, double *throughput, double *time) -{ - int32_t fd = -1; - int32_t input_fd = -1; - char export_path[1024]; - char *buf = NULL; - int32_t iter = 0; - int32_t ret = -1; - int64_t total_blks = 0; - struct timeval begin, end = {0, }; - - - GF_VALIDATE_OR_GOTO ("stripe", brick_path, out); - - snprintf (export_path, sizeof(export_path), "%s/%s", - brick_path, ".gf_tmp_stats_perf"); - fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); - if (fd == -1) - return errno; - buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); - - if (!buf) - return ret; - - input_fd = open("/dev/zero", O_RDONLY); - if (input_fd == -1) - return errno; - gettimeofday (&begin, NULL); - for (iter = 0; iter < blk_count; iter++) { - ret = read (input_fd, buf, blk_size); - if (ret != blk_size) { - ret = -1; - goto out; - } - ret = write (fd, buf, blk_size); - if (ret != blk_size) { - ret = -1; - goto out; - } - total_blks += ret; - } - ret = 0; - if (total_blks != (blk_size * blk_count)) { - gf_log ("glusterd", GF_LOG_WARNING, "Errors in write"); - ret = -1; - goto out; - } - - gettimeofday (&end, NULL); - *time = (end.tv_sec - begin.tv_sec) * 1e6 - + (end.tv_usec - begin.tv_usec); - - *throughput = total_blks / *time; - gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f MBps time %.2f secs bytes " - "written %"PRId64, *throughput, *time / 1e6, total_blks); -out: - if (fd >= 0) - close (fd); - if (input_fd >= 0) - close (input_fd); - if (buf) - GF_FREE (buf); - unlink (export_path); - return ret; -} - -int32_t -glusterd_volume_stats_read_perf (char *brick_path, int32_t blk_size, - int32_t blk_count, double *throughput, double *time) -{ - int32_t fd = -1; - int32_t output_fd = -1; - int32_t input_fd = -1; - char export_path[1024]; - char *buf = NULL; - int32_t iter = 0; - int32_t ret = -1; - int64_t total_blks = 0; - struct timeval begin, end = {0, }; - - - GF_VALIDATE_OR_GOTO ("glusterd", brick_path, out); - - snprintf (export_path, sizeof(export_path), "%s/%s", - brick_path, ".gf_tmp_stats_perf"); - fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); - if (fd == -1) - return errno; - buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); - - if (!buf) - return ret; - - output_fd = open("/dev/null", O_RDWR); - if (output_fd == -1) - return errno; - input_fd = open("/dev/zero", O_RDONLY); - if (input_fd == -1) - return errno; - for (iter = 0; iter < blk_count; iter++) { - ret = read (input_fd, buf, blk_size); - if (ret != blk_size) { - ret = -1; - goto out; - } - ret = write (fd, buf, blk_size); - if (ret != blk_size) { - ret = -1; - goto out; - } - } - - - lseek (fd, 0L, 0); - gettimeofday (&begin, NULL); - for (iter = 0; iter < blk_count; iter++) { - ret = read (fd, buf, blk_size); - if (ret != blk_size) { - ret = -1; - goto out; - } - ret = write (output_fd, buf, blk_size); - if (ret != blk_size) { - ret = -1; - goto out; - } - total_blks += ret; - } - ret = 0; - if (total_blks != (blk_size * blk_count)) { - gf_log ("glusterd", GF_LOG_WARNING, "Errors in write"); - ret = -1; - goto out; - } - - gettimeofday (&end, NULL); - *time = (end.tv_sec - begin.tv_sec) * 1e6 - + (end.tv_usec - begin.tv_usec); - - *throughput = total_blks / *time; - gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f MBps time %.2f secs bytes " - "read %"PRId64, *throughput, *time / 1e6, total_blks); -out: - if (fd >= 0) - close (fd); - if (input_fd >= 0) - close (input_fd); - if (output_fd >= 0) - close (output_fd); - if (buf) - GF_FREE (buf); - unlink (export_path); - return ret; -} - |
