diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-op-sm.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 14840 |
1 files changed, 7045 insertions, 7795 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 831e6bbdc40..c537fc33a85 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1,8914 +1,8164 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU 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 -#include "config.h" -#endif #include <time.h> #include <sys/uio.h> #include <sys/resource.h> #include <sys/mount.h> #include <libgen.h> -#include "uuid.h" +#include <glusterfs/compat-uuid.h> #include "fnmatch.h" -#include "xlator.h" +#include <glusterfs/xlator.h> #include "protocol-common.h" #include "glusterd.h" -#include "call-stub.h" -#include "defaults.h" -#include "list.h" -#include "dict.h" -#include "compat.h" -#include "compat-errno.h" -#include "statedump.h" -#include "glusterd-sm.h" +#include <glusterfs/call-stub.h> +#include <glusterfs/list.h> +#include <glusterfs/dict.h> +#include <glusterfs/compat.h> +#include <glusterfs/compat-errno.h> +#include <glusterfs/statedump.h> #include "glusterd-op-sm.h" #include "glusterd-utils.h" #include "glusterd-store.h" -#include "glusterd-volgen.h" -#include "syscall.h" -#include "cli1.h" -#include "common-utils.h" -#include "run.h" - +#include "glusterd-locks.h" +#include "glusterd-quota.h" +#include <glusterfs/syscall.h> +#include "cli1-xdr.h" +#include "glusterd-snapshot-utils.h" +#include "glusterd-svc-mgmt.h" +#include "glusterd-svc-helper.h" +#include "glusterd-shd-svc-helper.h" +#include "glusterd-shd-svc.h" +#include "glusterd-quotad-svc.h" +#include "glusterd-server-quorum.h" #include <sys/types.h> #include <signal.h> #include <sys/wait.h> -#define glusterd_op_start_volume_args_get(dict, volname, flags) \ - glusterd_op_stop_volume_args_get (dict, volname, flags) +#include "glusterd-gfproxyd-svc-helper.h" -static struct list_head gd_op_sm_queue; -pthread_mutex_t gd_op_sm_lock; -glusterd_op_info_t opinfo = {{0},}; -static int glusterfs_port = GLUSTERD_DEFAULT_PORT; -static char *glusterd_op_sm_state_names[] = { - "Default", - "Lock sent", - "Locked", - "Stage op sent", - "Staged", - "Commit op sent", - "Committed", - "Unlock sent", - "Stage op failed", - "Commit op failed", - "Brick op sent", - "Brick op failed", - "Brick op Committed", - "Brick op Commit failed", - "Invalid", -}; +#define len_strcmp(key, len, str) \ + ((len == SLEN(str)) && (strcmp(key, str) == 0)) -static char *glusterd_op_sm_event_names[] = { - "GD_OP_EVENT_NONE", - "GD_OP_EVENT_START_LOCK", - "GD_OP_EVENT_LOCK", - "GD_OP_EVENT_RCVD_ACC", - "GD_OP_EVENT_ALL_ACC", - "GD_OP_EVENT_STAGE_ACC", - "GD_OP_EVENT_COMMIT_ACC", - "GD_OP_EVENT_RCVD_RJT", - "GD_OP_EVENT_STAGE_OP", - "GD_OP_EVENT_COMMIT_OP", - "GD_OP_EVENT_UNLOCK", - "GD_OP_EVENT_START_UNLOCK", - "GD_OP_EVENT_ALL_ACK", - "GD_OP_EVENT_INVALID" -}; +extern char local_node_hostname[PATH_MAX]; +static int +glusterd_set_shared_storage(dict_t *dict, char *key, char *value, + char **op_errstr); -static char *gsync_reserved_opts[] = { - "gluster-command", - "pid-file", - "state-file", - "session-owner", - NULL +/* + * Valid options for all volumes to be listed in the valid_all_vol_opts table. + * To add newer options to all volumes, we can just add more entries to this + * table. + * + * It's important that every value have a default, or have a special handler + * in glusterd_get_global_options_for_all_vols, or else we might crash there. + */ +const glusterd_all_vol_opts valid_all_vol_opts[] = { + {GLUSTERD_QUORUM_RATIO_KEY, "51"}, + {GLUSTERD_SHARED_STORAGE_KEY, "disable"}, + /* This one actually gets filled in dynamically. */ + {GLUSTERD_GLOBAL_OP_VERSION_KEY, "BUG_NO_OP_VERSION"}, + /* + * This one should be filled in dynamically, but it didn't used to be + * (before the defaults were added here) so the value is unclear. + * + * TBD: add a dynamic handler to set the appropriate value + */ + {GLUSTERD_MAX_OP_VERSION_KEY, "BUG_NO_MAX_OP_VERSION"}, + {GLUSTERD_BRICK_MULTIPLEX_KEY, "disable"}, + /* Set this value to 0 by default implying brick-multiplexing + * behaviour with no limit set on the number of brick instances that + * can be attached per process. + * TBD: Discuss the default value for this. Maybe this should be a + * dynamic value depending on the memory specifications per node */ + {GLUSTERD_BRICKMUX_LIMIT_KEY, GLUSTERD_BRICKMUX_LIMIT_DFLT_VALUE}, + {GLUSTERD_VOL_CNT_PER_THRD, GLUSTERD_VOL_CNT_PER_THRD_DEFAULT_VALUE}, + {GLUSTERD_LOCALTIME_LOGGING_KEY, "disable"}, + {GLUSTERD_DAEMON_LOG_LEVEL_KEY, "INFO"}, + {NULL}, }; -static int -glusterd_restart_brick_servers (glusterd_volinfo_t *); - +static struct cds_list_head gd_op_sm_queue; +synclock_t gd_op_sm_lock; +glusterd_op_info_t opinfo = { + {0}, +}; -char* -glusterd_op_sm_state_name_get (int state) +int32_t +glusterd_txn_opinfo_dict_init() { - if (state < 0 || state >= GD_OP_STATE_MAX) - return glusterd_op_sm_state_names[GD_OP_STATE_MAX]; - return glusterd_op_sm_state_names[state]; -} + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; -char* -glusterd_op_sm_event_name_get (int event) -{ - if (event < 0 || event >= GD_OP_EVENT_MAX) - return glusterd_op_sm_event_names[GD_OP_EVENT_MAX]; - return glusterd_op_sm_event_names[event]; -} + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); -void -glusterd_destroy_lock_ctx (glusterd_op_lock_ctx_t *ctx) -{ - if (!ctx) - return; - GF_FREE (ctx); -} + priv->glusterd_txn_opinfo = dict_new(); + if (!priv->glusterd_txn_opinfo) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_CREATE_FAIL, NULL); + ret = -1; + goto out; + } -void -glusterd_set_volume_status (glusterd_volinfo_t *volinfo, - glusterd_volume_status status) -{ - GF_ASSERT (volinfo); - volinfo->status = status; -} + memset(priv->global_txn_id, '\0', sizeof(uuid_t)); -gf_boolean_t -glusterd_is_volume_started (glusterd_volinfo_t *volinfo) -{ - GF_ASSERT (volinfo); - return (volinfo->status == GLUSTERD_STATUS_STARTED); + ret = 0; +out: + return ret; } -gf_boolean_t -glusterd_are_all_volumes_stopped () +void +glusterd_txn_opinfo_dict_fini() { - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - glusterd_volinfo_t *voliter = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = 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; + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + if (priv->glusterd_txn_opinfo) + dict_unref(priv->glusterd_txn_opinfo); } -static int -glusterd_op_sm_inject_all_acc () +void +glusterd_txn_opinfo_init(glusterd_op_info_t *opinfo, + glusterd_op_sm_state_info_t *state, int *op, + dict_t *op_ctx, rpcsvc_request_t *req) { - int32_t ret = -1; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} + glusterd_conf_t *conf = NULL; -int -glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickinfo, - gd1_mgmt_brick_op_req **req, dict_t *dict) -{ - 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; + GF_ASSERT(opinfo); - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - GF_ASSERT (req); + conf = THIS->private; + GF_ASSERT(conf); + if (state) + opinfo->state = *state; - switch (op) { - case GD_OP_REMOVE_BRICK: - 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"); - goto out; - } - brick_req->op = GF_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 (op) + opinfo->op = *op; - if (!brick_req) { - gf_log ("", GF_LOG_ERROR, "Out of Memory"); - goto out; - } + if (op_ctx) + opinfo->op_ctx = dict_ref(op_ctx); + else + opinfo->op_ctx = NULL; - brick_req->op = GF_BRICK_XLATOR_INFO; - brick_req->name = brickinfo->path; + if (req) + opinfo->req = req; - ret = dict_get_int32 (dict, "top-op", (int32_t*)&top_op); - if (ret) - goto cont; - if (top_op == GF_CLI_TOP_READ_PERF || - top_op == GF_CLI_TOP_WRITE_PERF) { + opinfo->txn_generation = conf->generation; + cmm_smp_rmb(); - 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; - - 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); - if (ret) - goto out; - *req = brick_req; - ret = 0; + return; +} +int32_t +glusterd_generate_txn_id(dict_t *dict, uuid_t **txn_id) +{ + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + GF_ASSERT(dict); + + *txn_id = GF_MALLOC(sizeof(uuid_t), gf_common_mt_uuid_t); + if (!*txn_id) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, NULL); + goto out; + } + + if (priv->op_version < GD_OP_VERSION_3_6_0) + gf_uuid_copy(**txn_id, priv->global_txn_id); + else + gf_uuid_generate(**txn_id); + + ret = dict_set_bin(dict, "transaction_id", *txn_id, sizeof(**txn_id)); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set transaction id."); + goto out; + } + + gf_msg_debug(this->name, 0, "Transaction_id = %s", uuid_utoa(**txn_id)); out: - if (ret && brick_req) - GF_FREE (brick_req); - gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + if (ret && *txn_id) { + GF_FREE(*txn_id); + *txn_id = NULL; + } + + return ret; } -static int -glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) +int32_t +glusterd_get_txn_opinfo(uuid_t *txn_id, glusterd_op_info_t *opinfo) { - 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}; - uuid_t volume_uuid; - char *volume_uuid_str; - - 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; - } + int32_t ret = -1; + glusterd_txn_opinfo_obj *opinfo_obj = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = 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 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, "volume-id", &volume_uuid_str); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume id"); - goto out; - } - ret = uuid_parse (volume_uuid_str, volume_uuid); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to parse volume id"); - goto out; - } - - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } - - 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; - } - } + if (!txn_id || !opinfo) { + gf_msg_callingfn(this->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_ID_GET_FAIL, + "Empty transaction id or opinfo received."); + ret = -1; + goto out; + } - while ( i < brick_count) { - i++; - brick= strtok_r (brick_list, " \n", &tmpptr); - brick_list = tmpptr; + ret = dict_get_bin(priv->glusterd_txn_opinfo, uuid_utoa(*txn_id), + (void **)&opinfo_obj); + if (ret) + goto out; - if (!glusterd_store_is_valid_brickpath (volname, brick) || - !glusterd_is_valid_volfpath (volname, brick)) { - snprintf (msg, sizeof (msg), "brick path %s is too " - "long.", brick); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); + (*opinfo) = opinfo_obj->opinfo; - ret = -1; - goto out; - } + gf_msg_debug(this->name, 0, + "Successfully got opinfo for transaction ID : %s", + uuid_utoa(*txn_id)); - 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); - goto out; - } - - if (!uuid_compare (brick_info->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brick_info->hostname, - brick_info->path, - volume_uuid, - 0777, op_errstr); - if (ret) - goto out; - brick_list = tmpptr; - } - glusterd_brickinfo_delete (brick_info); - brick_info = NULL; - } + ret = 0; 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; + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } -static int -glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, - int *flags) +int32_t +glusterd_set_txn_opinfo(uuid_t *txn_id, glusterd_op_info_t *opinfo) { - int ret = -1; + int32_t ret = -1; + glusterd_txn_opinfo_obj *opinfo_obj = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; - if (!dict || !volname || !flags) - goto out; + 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; - } + if (!txn_id) { + gf_msg_callingfn(this->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_ID_GET_FAIL, + "Empty transaction id received."); + ret = -1; + goto out; + } - ret = dict_get_int32 (dict, "flags", flags); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get flags"); - goto out; + ret = dict_get_bin(priv->glusterd_txn_opinfo, uuid_utoa(*txn_id), + (void **)&opinfo_obj); + if (ret) { + opinfo_obj = GF_CALLOC(1, sizeof(glusterd_txn_opinfo_obj), + gf_common_mt_txn_opinfo_obj_t); + if (!opinfo_obj) { + ret = -1; + goto out; } -out: - return ret; -} -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; - - priv = THIS->private; - if (!priv) { - gf_log ("glusterd", GF_LOG_ERROR, - "priv is NULL"); - ret = -1; - goto out; + ret = dict_set_bin(priv->glusterd_txn_opinfo, uuid_utoa(*txn_id), + opinfo_obj, sizeof(glusterd_txn_opinfo_obj)); + if (ret) { + gf_msg_callingfn(this->name, GF_LOG_ERROR, errno, + GD_MSG_DICT_SET_FAILED, + "Unable to set opinfo for transaction" + " ID : %s", + uuid_utoa(*txn_id)); + goto out; } + } - ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); - if (ret) - goto out; + opinfo_obj->opinfo = (*opinfo); - exists = glusterd_check_volume_exists (volname); + gf_msg_debug(this->name, 0, + "Successfully set opinfo for transaction ID : %s", + uuid_utoa(*txn_id)); + ret = 0; +out: + if (ret) + if (opinfo_obj) + GF_FREE(opinfo_obj); - 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; - } + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; +} - ret = glusterd_volinfo_find (volname, &volinfo); +int32_t +glusterd_clear_txn_opinfo(uuid_t *txn_id) +{ + int32_t ret = -1; + glusterd_op_info_t txn_op_info = { + {0}, + }; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + if (!txn_id) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_ID_GET_FAIL, + "Empty transaction id received."); + ret = -1; + goto out; + } - if (ret) - goto out; + ret = glusterd_get_txn_opinfo(txn_id, &txn_op_info); + if (ret) { + gf_msg_callingfn(this->name, GF_LOG_ERROR, 0, + GD_MSG_TRANS_OPINFO_GET_FAIL, + "Unable to get transaction opinfo " + "for transaction ID : %s", + uuid_utoa(*txn_id)); + 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 (txn_op_info.op_ctx) + dict_unref(txn_op_info.op_ctx); - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brickinfo->hostname, - brickinfo->path, - volinfo->volume_id, - 0777, op_errstr); - if (ret) - goto out; - } + dict_del(priv->glusterd_txn_opinfo, uuid_utoa(*txn_id)); - 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; - } - } - } + gf_msg_debug(this->name, 0, + "Successfully cleared opinfo for transaction ID : %s", + uuid_utoa(*txn_id)); - ret = 0; + ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } -static int -glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - int flags = 0; - gf_boolean_t exists = _gf_false; - gf_boolean_t is_run = _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); +static int glusterfs_port = GLUSTERD_DEFAULT_PORT; +static char *glusterd_op_sm_state_names[] = { + "Default", + "Lock sent", + "Locked", + "Stage op sent", + "Staged", + "Commit op sent", + "Committed", + "Unlock sent", + "Stage op failed", + "Commit op failed", + "Brick op sent", + "Brick op failed", + "Brick op Committed", + "Brick op Commit failed", + "Ack drain", + "Invalid", +}; - 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; - } +static char *glusterd_op_sm_event_names[] = { + "GD_OP_EVENT_NONE", "GD_OP_EVENT_START_LOCK", + "GD_OP_EVENT_LOCK", "GD_OP_EVENT_RCVD_ACC", + "GD_OP_EVENT_ALL_ACC", "GD_OP_EVENT_STAGE_ACC", + "GD_OP_EVENT_COMMIT_ACC", "GD_OP_EVENT_RCVD_RJT", + "GD_OP_EVENT_STAGE_OP", "GD_OP_EVENT_COMMIT_OP", + "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"}; - ret = glusterd_volinfo_find (volname, &volinfo); +char * +glusterd_op_sm_state_name_get(int state) +{ + if (state < 0 || state >= GD_OP_STATE_MAX) + return glusterd_op_sm_state_names[GD_OP_STATE_MAX]; + return glusterd_op_sm_state_names[state]; +} - if (ret) - goto out; +char * +glusterd_op_sm_event_name_get(int event) +{ + if (event < 0 || event >= GD_OP_EVENT_MAX) + return glusterd_op_sm_event_names[GD_OP_EVENT_MAX]; + return glusterd_op_sm_event_names[event]; +} - 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; - } - ret = glusterd_check_gsync_running (volinfo, &is_run); - if (ret && (is_run == _gf_false)) - gf_log ("", GF_LOG_WARNING, "Unable to get the status" - " of active "GEOREP" session"); - if (is_run) { - gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" - "for the volume %s ", volname); - snprintf (msg, sizeof(msg), GEOREP" sessions are active " - "for the volume '%s'.\nUse 'volume "GEOREP" " - "status' command for more info. Use 'force'" - "option to ignore and stop stop the volume", - volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } +static void +glusterd_destroy_lock_ctx(glusterd_op_lock_ctx_t *ctx) +{ + if (!ctx) + return; + GF_FREE(ctx); +} - } +void +glusterd_set_volume_status(glusterd_volinfo_t *volinfo, + glusterd_volume_status status) +{ + GF_ASSERT(volinfo); + volinfo->status = status; +} +static int +glusterd_op_sm_inject_all_acc(uuid_t *txn_id) +{ + int ret = -1; + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_ALL_ACC, txn_id, NULL); + gf_msg_debug("glusterd", 0, "Returning %d", ret); + return ret; +} +static int +glusterd_check_bitrot_cmd(char *key, const int keylen, char *errstr, + const size_t size) +{ + int ret = -1; + + if (len_strcmp(key, keylen, "bitrot") || + len_strcmp(key, keylen, "features.bitrot")) { + snprintf(errstr, size, + " 'gluster volume set <VOLNAME> %s' is invalid command." + " Use 'gluster volume bitrot <VOLNAME> {enable|disable}'" + " instead.", + key); + goto out; + } else if (len_strcmp(key, keylen, "scrub-freq") || + len_strcmp(key, keylen, "features.scrub-freq")) { + snprintf(errstr, size, + " 'gluster volume set <VOLNAME> %s' is invalid command." + " Use 'gluster volume bitrot <VOLNAME> scrub-frequency" + " {hourly|daily|weekly|biweekly|monthly}' instead.", + key); + goto out; + } else if (len_strcmp(key, keylen, "scrub") || + len_strcmp(key, keylen, "features.scrub")) { + snprintf(errstr, size, + " 'gluster volume set <VOLNAME> %s' is invalid command." + " Use 'gluster volume bitrot <VOLNAME> scrub {pause|resume}'" + " instead.", + key); + goto out; + } else if (len_strcmp(key, keylen, "scrub-throttle") || + len_strcmp(key, keylen, "features.scrub-throttle")) { + snprintf(errstr, size, + " 'gluster volume set <VOLNAME> %s' is invalid command." + " Use 'gluster volume bitrot <VOLNAME> scrub-throttle " + " {lazy|normal|aggressive}' instead.", + key); + goto out; + } + + ret = 0; out: - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; + return ret; } static int -glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr) +glusterd_check_quota_cmd(char *key, const int keylen, char *value, char *errstr, + size_t size) { - 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 = -1; + gf_boolean_t b = _gf_false; - 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; + if (len_strcmp(key, keylen, "quota") || + len_strcmp(key, keylen, "features.quota")) { + ret = gf_string2boolean(value, &b); + if (ret) + goto out; + ret = -1; + if (b) { + snprintf(errstr, size, + " 'gluster volume set <VOLNAME> %s %s' is deprecated." + " Use 'gluster volume quota <VOLNAME> enable' instead.", + key, value); } else { - ret = 0; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - + snprintf(errstr, size, + " 'gluster volume set <VOLNAME> %s %s' is deprecated." + " Use 'gluster volume quota <VOLNAME> disable' instead.", + key, value); + } + goto out; + } else if (len_strcmp(key, keylen, "inode-quota") || + len_strcmp(key, keylen, "features.inode-quota")) { + ret = gf_string2boolean(value, &b); if (ret) - goto out; + goto out; + ret = -1; + if (b) { + snprintf( + errstr, size, + " 'gluster volume set <VOLNAME> %s %s' is deprecated." + " Use 'gluster volume inode-quota <VOLNAME> enable' instead.", + key, value); + } else { + /* inode-quota disable not supported, + * use quota disable + */ + snprintf(errstr, size, + " 'gluster volume set <VOLNAME> %s %s' is deprecated." + " Use 'gluster volume quota <VOLNAME> disable' instead.", + key, value); + } + goto out; + } + + ret = 0; +out: + return ret; +} - 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; - } +int +glusterd_brick_op_build_payload(glusterd_op_t op, + glusterd_brickinfo_t *brickinfo, + gd1_mgmt_brick_op_req **req, dict_t *dict) +{ + int ret = -1; + gd1_mgmt_brick_op_req *brick_req = NULL; + char *volname = NULL; + char name[1024] = { + 0, + }; + gf_xl_afr_op_t heal_op = GF_SHD_OP_INVALID; + xlator_t *this = NULL; + glusterd_volinfo_t *volinfo = NULL; + + this = THIS; + GF_ASSERT(this); + + GF_ASSERT(op < GD_OP_MAX); + GF_ASSERT(op > GD_OP_NONE); + GF_ASSERT(req); + + switch (op) { + case GD_OP_REMOVE_BRICK: + case GD_OP_STOP_VOLUME: + brick_req = GF_CALLOC(1, sizeof(*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); + goto out; + } + brick_req->op = GLUSTERD_BRICK_TERMINATE; + brick_req->name = brickinfo->path; + glusterd_set_brick_status(brickinfo, GF_BRICK_STOPPING); + 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_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); + goto out; + } + + brick_req->op = GLUSTERD_BRICK_XLATOR_INFO; + brick_req->name = brickinfo->path; + + break; + case GD_OP_HEAL_VOLUME: { + brick_req = GF_CALLOC(1, sizeof(*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); + goto out; + } + + brick_req->op = GLUSTERD_BRICK_XLATOR_OP; + brick_req->name = ""; + ret = dict_get_int32n(dict, "heal-op", SLEN("heal-op"), + (int32_t *)&heal_op); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=heal-op", NULL); + goto out; + } + ret = dict_set_int32n(dict, "xl-op", SLEN("xl-op"), heal_op); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=xl-op", NULL); + goto out; + } + } break; + case GD_OP_STATUS_VOLUME: { + brick_req = GF_CALLOC(1, sizeof(*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); + goto out; + } + brick_req->op = GLUSTERD_BRICK_STATUS; + brick_req->name = ""; + ret = dict_set_strn(dict, "brick-name", SLEN("brick-name"), + brickinfo->path); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=brick-name", NULL); + goto out; + } + } 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) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); + goto out; + } + + brick_req->op = GLUSTERD_BRICK_XLATOR_DEFRAG; + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=volname", NULL); + goto out; + } + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, + GD_MSG_VOLINFO_GET_FAIL, "Volume=%s", volname, NULL); + goto out; + } + snprintf(name, sizeof(name), "%s-dht", volname); + brick_req->name = gf_strdup(name); + + break; + case GD_OP_SNAP: + case GD_OP_BARRIER: + brick_req = GF_CALLOC(1, sizeof(*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); + goto out; + } + brick_req->op = GLUSTERD_BRICK_BARRIER; + brick_req->name = brickinfo->path; + break; - ret = 0; + default: + goto out; + break; + } + + brick_req->dict.dict_len = 0; + brick_req->dict.dict_val = NULL; + ret = dict_allocate_and_serialize(dict, &brick_req->input.input_val, + &brick_req->input.input_len); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, + GD_MSG_DICT_ALLOC_AND_SERL_LENGTH_GET_FAIL, NULL); + goto out; + } + *req = brick_req; + ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; + if (ret && brick_req) + GF_FREE(brick_req); + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } -static int -glusterd_op_stage_add_brick (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; - 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; - - 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; - } + int ret = -1; + gd1_mgmt_brick_op_req *brick_req = NULL; + char *volname = NULL; - 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"); - goto out; - } + GF_ASSERT(op < GD_OP_MAX); + GF_ASSERT(op > GD_OP_NONE); + GF_ASSERT(req); + xlator_t *this = NULL; + this = THIS; + GF_ASSERT(this); - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); + 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) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); goto out; - } + } - if (bricks) { - brick_list = gf_strdup (bricks); - all_bricks = gf_strdup (bricks); - free_ptr = brick_list; - } + brick_req->op = GLUSTERD_NODE_PROFILE; + brick_req->name = ""; - /* Check whether any of the bricks given is the destination brick of the - replace brick running */ + break; - 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; + case GD_OP_STATUS_VOLUME: + brick_req = GF_CALLOC(1, sizeof(*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); goto out; - } + } - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); + brick_req->op = GLUSTERD_NODE_STATUS; + brick_req->name = ""; + break; - while ( i < count) { - if (!glusterd_store_is_valid_brickpath (volname, brick) || - !glusterd_is_valid_volfpath (volname, brick)) { - snprintf (msg, sizeof (msg), "brick path %s is too " - "long.", brick); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); + case GD_OP_SCRUB_STATUS: + case GD_OP_SCRUB_ONDEMAND: + brick_req = GF_CALLOC(1, sizeof(*brick_req), + gf_gld_mt_mop_brick_req_t); + if (!brick_req) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, + NULL); + goto out; + } - ret = -1; - goto out; + brick_req->op = GLUSTERD_NODE_BITROT; - } + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=volname", NULL); + goto out; + } - 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 (ret) { - gf_log ("", GF_LOG_ERROR, "Add-brick: Unable" - " to get brickinfo"); - goto out; - } - brick_alloc = _gf_true; - } + brick_req->name = gf_strdup(volname); + break; + default: + goto out; + } - 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; - } + brick_req->dict.dict_len = 0; + brick_req->dict.dict_val = NULL; + ret = dict_allocate_and_serialize(dict, &brick_req->input.input_val, + &brick_req->input.input_len); - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_brick_create_path (brickinfo->hostname, - brickinfo->path, - volinfo->volume_id, - 0777, op_errstr); - if (ret) - goto out; - } + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, + GD_MSG_DICT_ALLOC_AND_SERL_LENGTH_GET_FAIL, NULL); + goto out; + } - glusterd_brickinfo_delete (brickinfo); - brick_alloc = _gf_false; - brickinfo = NULL; - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } + *req = brick_req; + ret = 0; 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); + if (ret && brick_req) + GF_FREE(brick_req); + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; +} - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +static int +glusterd_validate_quorum_options(xlator_t *this, char *fullkey, char *value, + char **op_errstr) +{ + int ret = 0; + char *key = NULL; + volume_option_t *opt = NULL; - return ret; + if (!glusterd_is_quorum_option(fullkey)) + goto out; + key = strchr(fullkey, '.'); + if (key == NULL) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_STRCHR_FAIL, NULL); + ret = -1; + goto out; + } + key++; + opt = xlator_volume_option_get(this, key); + if (!opt) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_VOLINFO_GET_FAIL, NULL); + ret = -1; + goto out; + } + ret = xlator_option_validate(this, key, value, opt, op_errstr); +out: + return ret; } -char * -glusterd_check_brick_rb_part (char *bricks, int count, glusterd_volinfo_t *volinfo) +static int +glusterd_validate_brick_mx_options(xlator_t *this, char *fullkey, char *value, + char **op_errstr) { - 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; - goto out; - } + int ret = 0; - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); + // Placeholder function for now + return ret; +} - 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; - 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; - goto out; - } +static int +glusterd_validate_shared_storage(char *value, char *errstr) +{ + int32_t ret = -1; + int32_t count = -1; + char *op = NULL; + char hook_script[PATH_MAX] = ""; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + int32_t len = 0; + glusterd_volinfo_t *volinfo = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO("glusterd", this, out); + + conf = this->private; + GF_VALIDATE_OR_GOTO(this->name, conf, out); + + GF_VALIDATE_OR_GOTO(this->name, value, out); + GF_VALIDATE_OR_GOTO(this->name, errstr, out); + + if ((strcmp(value, "enable")) && (strcmp(value, "disable"))) { + snprintf(errstr, PATH_MAX, + "Invalid option(%s). Valid options " + "are 'enable' and 'disable'", + value); + gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY, "%s", + errstr); + ret = -1; + goto out; + } - glusterd_brickinfo_delete (brickinfo); - brickinfo = NULL; - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } + len = snprintf(hook_script, sizeof(hook_script), + "%s" GLUSTERD_SHRD_STRG_HOOK_SCRIPT, conf->workdir); + if ((len < 0) || (len >= sizeof(hook_script))) { + ret = -1; + goto out; + } + + ret = sys_access(hook_script, R_OK | X_OK); + if (ret) { + len = snprintf(errstr, PATH_MAX, + "The hook-script (%s) required " + "for this operation is not present. " + "Please install the hook-script " + "and retry", + hook_script); + if (len < 0) { + strncpy(errstr, "<error>", PATH_MAX); + } + gf_msg(this->name, GF_LOG_ERROR, ENOENT, GD_MSG_FILE_OP_FAILED, "%s", + errstr); + goto out; + } + + if (!strncmp(value, "disable", SLEN("disable"))) { + ret = dict_get_strn(conf->opts, GLUSTERD_SHARED_STORAGE_KEY, + SLEN(GLUSTERD_SHARED_STORAGE_KEY), &op); + if (ret || !strncmp(op, "disable", SLEN("disable"))) { + snprintf(errstr, PATH_MAX, + "Shared storage volume " + "does not exist. Please enable shared storage" + " for creating shared storage volume."); + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_SHARED_STORAGE_DOES_NOT_EXIST, "%s", errstr); + ret = -1; + goto out; + } + goto out; + } + + ret = glusterd_volinfo_find(GLUSTER_SHARED_STORAGE, &volinfo); + if (!ret) { + snprintf(errstr, PATH_MAX, + "Shared storage volume(" GLUSTER_SHARED_STORAGE + ") already exists."); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_ALREADY_EXIST, "%s", + errstr); + ret = -1; + goto out; + } + + ret = glusterd_count_connected_peers(&count); + if (ret) { + snprintf(errstr, PATH_MAX, + "Failed to calculate number of connected peers."); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_PEER_COUNT_GET_FAIL, "%s", + errstr); + goto out; + } + + if (count <= 1) { + snprintf(errstr, PATH_MAX, + "More than one node should " + "be up/present in the cluster to enable this option"); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INSUFFICIENT_UP_NODES, "%s", + errstr); + ret = -1; + goto out; + } out: - if (brick_list) - GF_FREE(brick_list); - if (brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (ret) - str = gf_strdup (msg); - return str; + return ret; } 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; +glusterd_validate_localtime_logging(char *value, char *errstr) +{ + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + int already_enabled = 0; + + this = THIS; + GF_VALIDATE_OR_GOTO("glusterd", this, out); + + conf = this->private; + GF_VALIDATE_OR_GOTO(this->name, conf, out); + GF_VALIDATE_OR_GOTO(this->name, value, out); + + already_enabled = gf_log_get_localtime(); + + ret = 0; + if (strcmp(value, "enable") == 0) { + gf_log_set_localtime(1); + if (!already_enabled) + gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_LOCALTIME_LOGGING_ENABLE, + "localtime logging enable"); + } else if (strcmp(value, "disable") == 0) { + gf_log_set_localtime(0); + if (already_enabled) + gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_LOCALTIME_LOGGING_DISABLE, + "localtime logging disable"); + } else { + ret = -1; + GF_VALIDATE_OR_GOTO(this->name, errstr, out); + snprintf(errstr, PATH_MAX, + "Invalid option(%s). Valid options " + "are 'enable' and 'disable'", + value); + gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY, "%s", + errstr); + } out: - return ret; + return ret; } static int -glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, - dict_t *rsp_dict) +glusterd_validate_daemon_log_level(char *value, char *errstr) { - 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; - gf_boolean_t is_run = _gf_false; - - 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"); - 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 = 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_store_is_valid_brickpath (volname, dst_brick) || - !glusterd_is_valid_volfpath (volname, dst_brick)) { - snprintf (msg, sizeof (msg), "brick path %s is too " - "long.", dst_brick); - gf_log ("", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - - ret = -1; - goto out; - } - - ret = glusterd_check_gsync_running (volinfo, &is_run); - if (ret && (is_run == _gf_false)) - gf_log ("", GF_LOG_WARNING, "Unable to get the status" - " of active "GEOREP" session"); - if (is_run) { - gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" - "for the volume %s ", volname); - snprintf (msg, sizeof(msg), GEOREP" sessions are active " - "for the volume %s.\nStop "GEOREP "sessions " - "involved in this volume. Use 'volume "GEOREP - " status' command for more info.", - volname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; - 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 "); - 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; - 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; - } + this = THIS; + GF_VALIDATE_OR_GOTO("glusterd", this, 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); - } + conf = this->private; + GF_VALIDATE_OR_GOTO(this->name, conf, out); - 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, - volinfo->volume_id, 0777, - op_errstr); - 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; - } + GF_VALIDATE_OR_GOTO(this->name, value, 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; - } + ret = 0; - 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; - } - } - ret = 0; + if ((strcmp(value, "INFO")) && (strcmp(value, "WARNING")) && + (strcmp(value, "DEBUG")) && (strcmp(value, "TRACE")) && + (strcmp(value, "ERROR"))) { + ret = -1; + GF_VALIDATE_OR_GOTO(this->name, errstr, out); + snprintf(errstr, PATH_MAX, + "Invalid option(%s). Valid options " + "are 'INFO' or 'WARNING' or 'ERROR' or 'DEBUG' or " + " 'TRACE'", + value); + gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY, "%s", + errstr); + } out: - if (dup_dstbrick) - GF_FREE (dup_dstbrick); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; + return ret; } static int -glusterd_op_stage_log_level (dict_t *dict, char **op_errstr) -{ - int ret = -1; - gf_boolean_t exists = _gf_false; - dict_t *val_dict = NULL; - char *volname = NULL; - char *xlator = NULL; - char *loglevel = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - char msg[2048] = {0,}; - - 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 ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } - - /* - * check for existence of the gieven volume - */ - 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 ("glusterd", GF_LOG_ERROR, "%s", msg); - - *op_errstr = gf_strdup(msg); +glusterd_op_stage_set_volume(dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + int exists = 0; + char *key = NULL; + char *key_fixed = NULL; + char *value = NULL; + char *val_dup = NULL; + char keystr[100] = { + 0, + }; + int keystr_len; + int keylen; + char *trash_path = NULL; + int trash_path_len = 0; + int count = 0; + int dict_count = 0; + char errstr[PATH_MAX] = { + 0, + }; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + dict_t *val_dict = NULL; + gf_boolean_t global_opt = _gf_false; + gf_boolean_t key_matched = _gf_false; /* if a key was processed or not*/ + glusterd_volinfo_t *voliter = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + uint32_t new_op_version = GD_OP_VERSION_MIN; + uint32_t local_new_op_version = GD_OP_VERSION_MIN; + uint32_t local_new_client_op_version = GD_OP_VERSION_MIN; + uint32_t key_op_version = GD_OP_VERSION_MIN; + uint32_t local_key_op_version = GD_OP_VERSION_MIN; + gf_boolean_t origin_glusterd = _gf_true; + gf_boolean_t check_op_version = _gf_true; + gf_boolean_t trash_enabled = _gf_false; + gf_boolean_t all_vol = _gf_false; + struct volopt_map_entry *vmep = NULL; + + GF_ASSERT(dict); + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + /* 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 (!origin_glusterd) { + /* Check for v3.3.x origin glusterd */ + 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_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Key=new-op-version", NULL); + goto out; + } + + if ((new_op_version > GD_OP_VERSION_MAX) || + (new_op_version < GD_OP_VERSION_MIN)) { ret = -1; - goto out; - } - - ret = dict_get_str (dict, "xlator", &xlator); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); - goto out; - } - - ret = dict_get_str (dict, "loglevel", &loglevel); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get loglevel"); - goto out; - } - - ret = 0; - - out: - if (val_dict) - dict_unref (val_dict); - - if (ret) { - if (!(*op_errstr)) { - *op_errstr = gf_strdup ("Error, Validation Failed"); - gf_log ("glusterd", GF_LOG_DEBUG, "Error, Cannot Validate option: %s", - *op_errstr); - } + snprintf(errstr, sizeof(errstr), + "Required op_version (%d) is not supported." + " Max supported op version is %d", + new_op_version, priv->op_version); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNSUPPORTED_VERSION, + "%s", errstr); + goto out; + } + } + } + + ret = dict_get_int32_sizen(dict, "count", &dict_count); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Count(dict),not set in Volume-Set"); + goto out; + } + + if (dict_count == 0) { + /*No options would be specified of volume set help */ + if (dict_get_sizen(dict, "help")) { + ret = 0; + goto out; + } + + if (dict_get_sizen(dict, "help-xml")) { +#if (HAVE_LIB_XML) + ret = 0; + goto out; +#else + ret = -1; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MODULE_NOT_INSTALLED, + "libxml not present in the system"); + *op_errstr = gf_strdup( + "Error: xml libraries not present to produce xml-output"); + goto out; +#endif } + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_NO_OPTIONS_GIVEN, + "No options received "); + *op_errstr = gf_strdup("Options not specified"); + ret = -1; + goto out; + } - gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); - return ret; -} + ret = dict_get_str_sizen(dict, "volname", &volname); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Key=volname", NULL); + goto out; + } -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; - - ret = dict_get_str (dict, "volname", &volname); + if (strcasecmp(volname, "all") != 0) { + ret = glusterd_volinfo_find(volname, &volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; + snprintf(errstr, sizeof(errstr), FMTSTR_CHECK_VOL_EXISTS, volname); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + FMTSTR_CHECK_VOL_EXISTS, volname); + 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 = glusterd_validate_volume_id(dict, volinfo); + if (ret) + goto out; + + local_new_op_version = volinfo->op_version; + local_new_client_op_version = volinfo->client_op_version; + + } else { + all_vol = _gf_true; + } + + val_dict = dict_new(); + if (!val_dict) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_CREATE_FAIL, NULL); + goto out; + } + + for (count = 1; ret != 1; count++) { + keystr_len = sprintf(keystr, "key%d", count); + ret = dict_get_strn(dict, keystr, keystr_len, &key); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=%s", keystr, NULL); + break; + } + + keystr_len = sprintf(keystr, "value%d", count); + ret = dict_get_strn(dict, keystr, keystr_len, &value); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "invalid key,value pair in 'volume set'"); + ret = -1; + goto out; + } + + key_matched = _gf_false; + keylen = strlen(key); + if (len_strcmp(key, keylen, "config.memory-accounting")) { + key_matched = _gf_true; + gf_msg_debug(this->name, 0, + "enabling memory accounting for volume %s", volname); + ret = 0; + } else if (len_strcmp(key, keylen, "config.transport")) { + key_matched = _gf_true; + gf_msg_debug(this->name, 0, "changing transport-type for volume %s", + volname); + ret = 0; + /* 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; + } + } else if (len_strcmp(key, keylen, "ganesha.enable")) { + key_matched = _gf_true; + if (!strcmp(value, "off") == 0) { + ret = ganesha_manage_export(dict, "off", _gf_true, op_errstr); + if (ret) + goto out; + } } - ret = dict_get_str (dict, "brick", &brick); - if (ret) + if (!key_matched) { + ret = glusterd_check_bitrot_cmd(key, keylen, errstr, + sizeof(errstr)); + 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; - } - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "path not found"); + ret = glusterd_check_quota_cmd(key, keylen, value, errstr, + sizeof(errstr)); + if (ret) 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; - } + if (is_key_glusterd_hooks_friendly(key)) + continue; - ret = glusterd_brick_create_path (hostname, path, volinfo->volume_id, - 0777, op_errstr); + ret = glusterd_volopt_validate(volinfo, dict, key, value, op_errstr); if (ret) - goto out; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} + goto out; -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_option_exists(key, &key_fixed); + if (exists == -1) { + ret = -1; + 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); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, + "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, sizeof(errstr) - ret, + "\nDid you mean %s?", key_fixed); + ret = -1; + goto out; + } + + if (key_fixed) { + key = key_fixed; + keylen = strlen(key_fixed); + } + + if (len_strcmp(key, keylen, "cluster.granular-entry-heal")) { + /* For granular entry-heal, if the set command was + * invoked through volume-set CLI, then allow the + * command only if the volume is still in 'Created' + * state + */ + if (volinfo && volinfo->status != GLUSTERD_STATUS_NONE && + (dict_get_sizen(dict, "is-special-key") == NULL)) { + snprintf(errstr, sizeof(errstr), + " 'gluster volume set <VOLNAME> %s {enable, disable}'" + " is not supported." + " Use 'gluster volume heal <VOLNAME> " + "granular-entry-heal {enable, disable}' instead.", + key); 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); + } + } else if (len_strcmp(key, keylen, GLUSTERD_GLOBAL_OP_VERSION_KEY)) { + /* Check if the key is cluster.op-version and set + * local_new_op_version to the value given if possible. + */ + if (!all_vol) { + ret = -1; + snprintf(errstr, sizeof(errstr), + "Option \"%s\" is not valid for a single volume", key); + goto out; + } + /* Check if cluster.op-version is the only option being + * set + */ + if (count != 1) { ret = -1; + snprintf(errstr, sizeof(errstr), + "Option \"%s\" cannot be set along with other options", + key); + goto out; + } + /* Just reusing the variable, but I'm using it for + * storing the op-version from value + */ + ret = gf_string2uint(value, &local_key_op_version); + if (ret) { + snprintf(errstr, sizeof(errstr), + "invalid number format \"%s\" in option \"%s\"", value, + key); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, "%s", + errstr); + goto out; + } + + if (local_key_op_version > GD_OP_VERSION_MAX || + local_key_op_version < GD_OP_VERSION_MIN) { + ret = -1; + snprintf(errstr, sizeof(errstr), + "Required op_version (%d) is not supported." + " Max supported op version is %d", + local_key_op_version, priv->op_version); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VERSION_UNSUPPORTED, + "%s", errstr); + goto out; + } + if (local_key_op_version > priv->op_version) { + local_new_op_version = local_key_op_version; + } else { + ret = -1; + snprintf(errstr, sizeof(errstr), + "Required op-version (%d) should" + " not be equal or lower than current" + " cluster op-version (%d).", + local_key_op_version, priv->op_version); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VERSION_UNSUPPORTED, + "%s", errstr); goto out; + } + + goto cont; } - ret = dict_get_str (dict, "brick", &brick); + ALL_VOLUME_OPTION_CHECK(volname, _gf_false, key, ret, op_errstr, out); + ret = glusterd_validate_quorum_options(this, key, value, op_errstr); if (ret) - goto out; + 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); + ret = glusterd_validate_brick_mx_options(this, key, value, op_errstr); + if (ret) + goto out; + + vmep = gd_get_vmep(key); + local_key_op_version = glusterd_get_op_version_from_vmep(vmep); + if (local_key_op_version > local_new_op_version) + local_new_op_version = local_key_op_version; + if (gd_is_client_option(vmep) && + (local_key_op_version > local_new_client_op_version)) + local_new_client_op_version = local_key_op_version; + + sprintf(keystr, "op-version%d", count); + if (origin_glusterd) { + ret = dict_set_uint32(dict, keystr, local_key_op_version); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set key-op-version in dict"); + goto out; + } + } else if (check_op_version) { + ret = dict_get_uint32(dict, keystr, &key_op_version); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "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_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_OP_VERSION_MISMATCH, + "%s, required op-version = %" PRIu32 + ", available op-version = %" PRIu32, + errstr, key_op_version, local_key_op_version); + goto out; + } + } + + global_opt = glusterd_check_globaloption(key); + + if (len_strcmp(key, keylen, GLUSTERD_SHARED_STORAGE_KEY)) { + ret = glusterd_validate_shared_storage(value, errstr); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_SHARED_STRG_VOL_OPT_VALIDATE_FAIL, + "Failed to validate shared storage volume options"); + goto out; + } + } else if (len_strcmp(key, keylen, GLUSTERD_LOCALTIME_LOGGING_KEY)) { + ret = glusterd_validate_localtime_logging(value, errstr); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_LOCALTIME_LOGGING_VOL_OPT_VALIDATE_FAIL, + "Failed to validate localtime logging volume options"); + goto out; + } + } else if (len_strcmp(key, keylen, GLUSTERD_DAEMON_LOG_LEVEL_KEY)) { + ret = glusterd_validate_daemon_log_level(value, errstr); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_DAEMON_LOG_LEVEL_VOL_OPT_VALIDATE_FAIL, + "Failed to validate daemon-log-level volume options"); + goto out; + } + } else if (len_strcmp(key, keylen, "features.trash-dir")) { + if (volinfo) { + ret = glusterd_volinfo_get(volinfo, VKEY_FEATURES_TRASH, + &val_dup); + if (!ret && val_dup) { + ret = gf_string2boolean(val_dup, &trash_enabled); + if (ret) goto out; } - } -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); + } + if (!trash_enabled) { + snprintf(errstr, sizeof(errstr), + "Trash translator is not enabled. " + "Use volume set %s trash on", + volname); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_SET_FAIL, + "Unable to set the options in 'volume set': %s", 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" )) { - ret = 0; - goto out; - } - - gf_log ("", GF_LOG_ERROR, "No options received "); - *op_errstr = gf_strdup ("Options not specified"); + } + if (strchr(value, '/')) { + snprintf(errstr, sizeof(errstr), + "Path is not allowed as option"); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_SET_FAIL, + "Unable to set the options in 'volume set': %s", errstr); 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 (ret) - break; - - 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, - "option : %s does not exist", - key); - if (key_fixed) - snprintf (errstr + ret, 2048 - 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'"); + } + + list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + /* Check for local brick */ + if (!gf_uuid_compare(brickinfo->uuid, MY_UUID)) { + trash_path_len = strlen(value) + strlen(brickinfo->path) + + 2; + trash_path = GF_MALLOC(trash_path_len, gf_common_mt_char); + snprintf(trash_path, trash_path_len, "%s/%s", + brickinfo->path, value); + + /* Checks whether a directory with + given option exists or not */ + if (!sys_access(trash_path, R_OK)) { + snprintf(errstr, sizeof(errstr), "Path %s exists", + value); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_SET_FAIL, + "Unable to set the options in 'volume set': %s", + errstr); ret = -1; goto out; - } - - if (key_fixed) - key = key_fixed; - - ret = glusterd_check_globaloption (key); - if (ret) - global_opt = _gf_true; - - ret = dict_set_str (val_dict, key, value); - - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set the options in 'volume set'"); + } else { + gf_msg_debug(this->name, 0, + "Directory with given name does not exist," + " continuing"); + } + + if (volinfo->status == GLUSTERD_STATUS_STARTED && + brickinfo->status != GF_BRICK_STARTED) { + /* If volume is in started state , checks + whether bricks are online */ + snprintf(errstr, sizeof(errstr), + "One or more bricks are down"); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_SET_FAIL, + "Unable to set the options in 'volume set': %s", + errstr); ret = -1; goto out; + } } - - *op_errstr = NULL; - if (!global_opt) - ret = glusterd_validate_reconfopts (volinfo, val_dict, op_errstr); - else { - voliter = NULL; - list_for_each_entry (voliter, &priv->volumes, vol_list) { - ret = glusterd_validate_globalopts (voliter, val_dict, op_errstr); - if (ret) - break; - } - } - - if (ret) { - gf_log ("glusterd", GF_LOG_DEBUG, "Could not create temp " - "volfile, some option failed: %s", *op_errstr); - goto out; - } - dict_del (val_dict, key); - - if (key_fixed) { - GF_FREE (key_fixed); - key_fixed = NULL; + if (trash_path) { + GF_FREE(trash_path); + trash_path = NULL; } + } } - - ret = 0; - -out: - if (val_dict) - dict_unref (val_dict); - - if (key_fixed) - GF_FREE (key_fixed); + ret = dict_set_strn(val_dict, key, keylen, value); if (ret) { - if (!(*op_errstr)) { - *op_errstr = gf_strdup ("Error, Validation Failed"); - gf_log ("glsuterd", GF_LOG_DEBUG, - "Error, Cannot Validate option :%s", - *op_errstr); - } else { - gf_log ("glsuterd", GF_LOG_DEBUG, - "Error, Cannot Validate option"); - } + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Unable to set the options in 'volume set'"); + ret = -1; + goto out; } - return ret; -} -static int -glusterd_op_stage_reset_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0}; - - ret = dict_get_str (dict, "volname", &volname); + *op_errstr = NULL; + if (!global_opt && !all_vol) + ret = glusterd_validate_reconfopts(volinfo, val_dict, op_errstr); + else if (!all_vol) { + voliter = NULL; + cds_list_for_each_entry(voliter, &priv->volumes, vol_list) + { + ret = glusterd_validate_globalopts(voliter, val_dict, + op_errstr); + if (ret) + break; + } + } if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOLFILE_CREATE_FAIL, + "Could not create temp volfile, some option failed: %s", + *op_errstr); + goto out; } + dict_deln(val_dict, key, keylen); - exists = glusterd_check_volume_exists (volname); + if (key_fixed) { + GF_FREE(key_fixed); + key_fixed = NULL; + } + } - 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; + /* Check if all the connected clients support the new client-op-version + */ + ret = glusterd_check_client_op_version_support( + volname, local_new_client_op_version, op_errstr); + if (ret) + goto out; +cont: + if (origin_glusterd) { + ret = dict_set_uint32(dict, "new-op-version", local_new_op_version); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "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_int32_sizen(dict, "check-op-version", 1); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set check-op-version in dict"); + goto out; } + } + ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + if (val_dict) + dict_unref(val_dict); - 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; + if (trash_path) + GF_FREE(trash_path); - ret = glusterd_resolve_brick (brickinfo); - if (ret) - goto out; + GF_FREE(key_fixed); + if (errstr[0] != '\0') + *op_errstr = gf_strdup(errstr); - 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; - } + if (ret) { + if (!(*op_errstr)) { + *op_errstr = gf_strdup("Error, Validation Failed"); + gf_msg_debug(this->name, 0, "Error, Cannot Validate option :%s", + *op_errstr); + } else { + gf_msg_debug(this->name, 0, "Error, Cannot Validate option"); } - glusterd_delete_brick (volinfo, brickinfo); -out: - if (dup_brick) - GF_FREE (dup_brick); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + } + return ret; } static int -glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo, - char *old_brick, char *new_brick) +glusterd_op_stage_reset_volume(dict_t *dict, char **op_errstr) { - glusterd_brickinfo_t *old_brickinfo = NULL; - glusterd_brickinfo_t *new_brickinfo = NULL; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; + int ret = 0; + char *volname = NULL; + int exists = 0; + char msg[2048] = {0}; + char *key = NULL; + char *key_fixed = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; - priv = THIS->private; + this = THIS; + GF_ASSERT(this); - GF_ASSERT (volinfo); + priv = this->private; + GF_ASSERT(priv); - 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; + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); - list_add_tail (&new_brickinfo->brick_list, - &old_brickinfo->brick_list); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get volume name"); + goto out; + } - volinfo->brick_count++; + if (strcasecmp(volname, "all") != 0) { + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + snprintf(msg, sizeof(msg), FMTSTR_CHECK_VOL_EXISTS, volname); + goto out; + } - ret = glusterd_op_perform_remove_brick (volinfo, old_brick); + ret = glusterd_validate_volume_id(dict, volinfo); if (ret) - goto out; + goto out; + } + + ret = dict_get_strn(dict, "key", SLEN("key"), &key); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get option key"); + goto out; + } + + /* * + * If key ganesha.enable is set, then volume should be unexported from + * ganesha server. Also it is a volume-level option, perform only when + * volume name not equal to "all"(in other words if volinfo != NULL) + */ + if (volinfo && (!strcmp(key, "all") || !strcmp(key, "ganesha.enable"))) { + if (glusterd_check_ganesha_export(volinfo)) { + ret = ganesha_manage_export(dict, "off", _gf_true, op_errstr); + if (ret) + gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_NFS_GNS_RESET_FAIL, + "Could not reset ganesha.enable key"); + } + } + + if (strcmp(key, "all")) { + exists = glusterd_check_option_exists(key, &key_fixed); + if (exists == -1) { + ret = -1; + goto out; + } - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) + 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; + + /* 'gluster volume set/reset <VOLNAME> + * features.quota/features.inode-quota' should + * not be allowed as it is deprecated. + * Setting and resetting quota/inode-quota features + * should be allowed only through 'gluster volume quota + * <VOLNAME> enable/disable'. + * But, 'gluster volume set features.quota-deem-statfs' + * can be turned on/off when quota is enabled. + */ + + if (strcmp(VKEY_FEATURES_INODE_QUOTA, key) == 0 || + strcmp(VKEY_FEATURES_QUOTA, key) == 0) { + snprintf(msg, sizeof(msg), + "'gluster volume " + "reset <VOLNAME> %s' is deprecated. " + "Use 'gluster volume quota <VOLNAME> " + "disable' instead.", + key); + ret = -1; goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_start (volinfo, new_brickinfo); - if (ret) - goto out; + } + ALL_VOLUME_OPTION_CHECK(volname, _gf_false, key, ret, op_errstr, + 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_FREE(key_fixed); - 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); - } + if (msg[0] != '\0') { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_OP_STAGE_RESET_VOL_FAIL, + "%s", msg); + *op_errstr = gf_strdup(msg); + } -out: - if (free_ptr1) - GF_FREE (free_ptr1); - if (free_ptr2) - GF_FREE (free_ptr2); + gf_msg_debug(this->name, 0, "Returning %d", ret); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return 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; - - 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); - 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) { - ret = -1; - goto out; - } - gf_log ("glusterd", GF_LOG_ERROR, "%s", errstr); - ret = dict_set_dynstr (ctx, "errstr", errstr); - if (ret) { - GF_FREE (errstr); - gf_log ("", GF_LOG_DEBUG, - "failed to set errstr ctx"); - goto out; - } - - ret = -1; - goto out; - } - - ret = dict_get_int32 (dict, "count", &brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get brick count"); - 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"); - 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"); - ret = -1; - goto 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; - } - - ret = -1; +glusterd_op_stage_sync_volume(dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + char *hostname = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + char msg[2048] = { + 0, + }; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + this = THIS; + GF_ASSERT(this); + + ret = dict_get_strn(dict, "hostname", SLEN("hostname"), &hostname); + if (ret) { + snprintf(msg, sizeof(msg), + "hostname couldn't be " + "retrieved from msg"); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=hostname", NULL); + *op_errstr = gf_strdup(msg); + goto out; + } + + if (gf_is_local_addr(hostname)) { + // volname is not present in case of sync all + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (!ret) { + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + snprintf(msg, sizeof(msg), + "Volume %s " + "does not exist", + volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_VOL_NOT_FOUND, + "Volume=%s", volname, NULL); + *op_errstr = gf_strdup(msg); goto out; - } + } + } + } else { + RCU_READ_LOCK; + + peerinfo = glusterd_peerinfo_find(NULL, hostname); + if (peerinfo == NULL) { + RCU_READ_UNLOCK; + ret = -1; + snprintf(msg, sizeof(msg), "%s, is not a friend", hostname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_PEER_NOT_FOUND, + "Peer_name=%s", hostname, NULL); + *op_errstr = gf_strdup(msg); + goto out; + + } else if (!peerinfo->connected) { + RCU_READ_UNLOCK; + ret = -1; + snprintf(msg, sizeof(msg), + "%s, is not connected at " + "the moment", + hostname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_PEER_DISCONNECTED, + "Peer_name=%s", hostname, NULL); + *op_errstr = gf_strdup(msg); + goto out; + } + + RCU_READ_UNLOCK; + } out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_msg_debug("glusterd", 0, "Returning %d", ret); - return ret; + return ret; } static int -glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - char *hostname = NULL; - gf_boolean_t exists = _gf_false; - glusterd_peerinfo_t *peerinfo = NULL; - char msg[2048] = {0,}; - - ret = dict_get_str (dict, "hostname", &hostname); - if (ret) { - snprintf (msg, sizeof (msg), "hostname couldn't be " - "retrieved from msg"); - *op_errstr = gf_strdup (msg); - goto out; - } +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; +#ifdef BUILD_GNFS + gf_boolean_t nfs_disabled = _gf_false; +#endif + gf_boolean_t shd_enabled = _gf_false; + + GF_ASSERT(dict); + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + ret = dict_get_uint32(dict, "cmd", &cmd); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=cmd", NULL); + goto out; + } + + if (cmd & GF_CLI_STATUS_ALL) + goto out; + + if ((cmd & GF_CLI_STATUS_QUOTAD) && + (priv->op_version == GD_OP_VERSION_MIN)) { + snprintf(msg, sizeof(msg), + "The cluster is operating at " + "version 1. Getting the status of quotad is not " + "allowed in this state."); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_QUOTA_GET_STAT_FAIL, + msg, NULL); + ret = -1; + goto out; + } + + if ((cmd & GF_CLI_STATUS_SNAPD) && + (priv->op_version < GD_OP_VERSION_3_6_0)) { + snprintf(msg, sizeof(msg), + "The cluster is operating at " + "version less than %d. Getting the " + "status of snapd is not allowed in this state.", + GD_OP_VERSION_3_6_0); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_SNAP_STATUS_FAIL, msg, + NULL); + ret = -1; + goto out; + } + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + snprintf(msg, sizeof(msg), FMTSTR_CHECK_VOL_EXISTS, volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_VOLINFO_GET_FAIL, + "Volume=%s", volname, NULL); + ret = -1; + goto out; + } + + ret = glusterd_validate_volume_id(dict, volinfo); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_VALIDATE_FAILED, NULL); + goto out; + } + + ret = glusterd_is_volume_started(volinfo); + if (!ret) { + snprintf(msg, sizeof(msg), "Volume %s is not started", volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_VOL_NOT_STARTED, + "Volume=%s", volname, NULL); + ret = -1; + goto out; + } - ret = glusterd_is_local_addr (hostname); - if (ret) { - ret = glusterd_friend_find (NULL, hostname, &peerinfo); - if (ret) { - snprintf (msg, sizeof (msg), "%s, is not a friend", - hostname); - *op_errstr = gf_strdup (msg); - goto out; - } + vol_opts = volinfo->dict; - if (!peerinfo->connected) { - snprintf (msg, sizeof (msg), "%s, is not connected at " - "the moment", hostname); - *op_errstr = gf_strdup (msg); - ret = -1; - goto out; - } + if ((cmd & GF_CLI_STATUS_SHD) != 0) { + if (glusterd_is_shd_compatible_volume(volinfo)) { + shd_enabled = gd_is_self_heal_enabled(volinfo, vol_opts); } 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; - } + ret = -1; + snprintf(msg, sizeof(msg), "Volume %s is not Self-heal compatible", + volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_VOL_SHD_NOT_COMP, + "Volume=%s", volname, NULL); + goto out; + } + if (!shd_enabled) { + ret = -1; + snprintf(msg, sizeof(msg), + "Self-heal Daemon is disabled for volume %s", volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_SELF_HEALD_DISABLED, + "Volume=%s", volname, NULL); + goto out; + } +#ifdef BUILD_GNFS + } else if ((cmd & GF_CLI_STATUS_NFS) != 0) { + nfs_disabled = dict_get_str_boolean(vol_opts, NFS_DISABLE_MAP_KEY, + _gf_false); + if (nfs_disabled) { + ret = -1; + snprintf(msg, sizeof(msg), "NFS server is disabled for volume %s", + volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, + GD_MSG_NFS_GANESHA_DISABLED, "Volume=%s", volname, NULL); + goto out; } +#endif + } else if ((cmd & GF_CLI_STATUS_QUOTAD) != 0) { + if (!glusterd_is_volume_quota_enabled(volinfo)) { + ret = -1; + snprintf(msg, sizeof(msg), + "Volume %s does not have " + "quota enabled", + volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_QUOTA_DISABLED, + "Volume=%s", volname, NULL); + goto out; + } + } else if ((cmd & GF_CLI_STATUS_BITD) != 0) { + if (!glusterd_is_bitrot_enabled(volinfo)) { + ret = -1; + snprintf(msg, sizeof(msg), + "Volume %s does not have " + "bitrot enabled", + volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_BITROT_NOT_ENABLED, + "Volume=%s", volname, NULL); + goto out; + } + } else if ((cmd & GF_CLI_STATUS_SCRUB) != 0) { + if (!glusterd_is_bitrot_enabled(volinfo)) { + ret = -1; + snprintf(msg, sizeof(msg), + "Volume %s does not have " + "bitrot enabled. Scrubber will be enabled " + "automatically if bitrot is enabled", + volname); + gf_smsg( + this->name, GF_LOG_ERROR, errno, GD_MSG_BITROT_NOT_ENABLED, + "Scrubber will be enabled automatically if bitrot is enabled", + "Volume=%s", volname, NULL); + goto out; + } + } else if ((cmd & GF_CLI_STATUS_SNAPD) != 0) { + if (!glusterd_is_snapd_enabled(volinfo)) { + ret = -1; + snprintf(msg, sizeof(msg), + "Volume %s does not have " + "uss enabled", + volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_SNAPD_NOT_RUNNING, + "Volume=%s", volname, NULL); + goto out; + } + } else if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_strn(dict, "brick", SLEN("brick"), &brick); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Key=brick", NULL); + goto out; + } + + ret = glusterd_volume_brickinfo_get_by_brick(brick, volinfo, &brickinfo, + _gf_false); + if (ret) { + snprintf(msg, sizeof(msg), + "No brick %s in" + " volume %s", + brick, volname); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_BRICK_NOT_FOUND, + "Brick=%s, Volume=%s", brick, volname, NULL); + ret = -1; + goto out; + } + } + + ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + if (ret) { + if (msg[0] != '\0') + *op_errstr = gf_strdup(msg); + else + *op_errstr = gf_strdup("Validation Failed for Status"); + } - return ret; + gf_msg_debug(this->name, 0, "Returning: %d", ret); + return ret; } - int -glusterd_query_extutil (char *resbuf, runner_t *runner) -{ - char *ptr = NULL; - int ret = 0; - - runner_redir (runner, STDOUT_FILENO, RUN_PIPE); - if (runner_start (runner) != 0) { - gf_log ("", GF_LOG_ERROR, "spawning child failed"); - - return -1; - } - - ptr = fgets(resbuf, PATH_MAX, runner_chio (runner, STDOUT_FILENO)); - if (ptr) - resbuf[strlen(resbuf)-1] = '\0'; //strip off \n - - ret = runner_end (runner); - if (ret) - gf_log ("", GF_LOG_ERROR, "reading data from child failed"); - - return ret ? -1 : 0; +glusterd_op_stage_stats_volume(dict_t *dict, char **op_errstr) +{ + int ret = -1; + char *volname = NULL; + char msg[2048] = { + 0, + }; + int32_t stats_op = GF_CLI_STATS_NONE; + glusterd_volinfo_t *volinfo = NULL; + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + snprintf(msg, sizeof(msg), "Volume name get failed"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + snprintf(msg, sizeof(msg), + "Volume %s, " + "doesn't exist", + volname); + goto out; + } + + ret = glusterd_validate_volume_id(dict, volinfo); + if (ret) + goto out; + + ret = dict_get_int32n(dict, "op", SLEN("op"), &stats_op); + if (ret) { + snprintf(msg, sizeof(msg), "Volume profile op get failed"); + goto out; + } + + if (GF_CLI_STATS_START == stats_op) { + if (_gf_true == glusterd_is_profile_on(volinfo)) { + snprintf(msg, sizeof(msg), + "Profile on Volume %s is" + " already started", + volinfo->volname); + ret = -1; + goto out; + } + } else if ((GF_CLI_STATS_STOP == stats_op) || + (GF_CLI_STATS_INFO == stats_op)) { + if (_gf_false == glusterd_is_profile_on(volinfo)) { + snprintf(msg, sizeof(msg), + "Profile on Volume %s is" + " not started", + volinfo->volname); + ret = -1; + + goto out; + } + } + if ((GF_CLI_STATS_TOP == stats_op) || (GF_CLI_STATS_INFO == stats_op)) { + if (_gf_false == glusterd_is_volume_started(volinfo)) { + snprintf(msg, sizeof(msg), "Volume %s is not started.", + volinfo->volname); + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_STARTED, "%s", + msg); + ret = -1; + goto out; + } + } + ret = 0; +out: + if (msg[0] != '\0') { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_OP_STAGE_STATS_VOL_FAIL, + "%s", msg); + *op_errstr = gf_strdup(msg); + } + gf_msg_debug("glusterd", 0, "Returning %d", ret); + return ret; } static int -glusterd_get_canon_url (char *cann, char *name, gf_boolean_t cann_esc) -{ - runner_t runner = {0,}; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - runinit (&runner); - runner_add_arg (&runner, GSYNCD_PREFIX"/gsyncd"); - runner_argprintf (&runner, "--canonicalize-%surl", - cann_esc ? "escape-" : ""); - runner_add_arg(&runner, name); - - return glusterd_query_extutil (cann, &runner); +_delete_reconfig_opt(dict_t *this, char *key, data_t *value, void *data) +{ + int32_t *is_force = 0; + + GF_ASSERT(data); + is_force = (int32_t *)data; + + /* Keys which has the flag VOLOPT_FLAG_NEVER_RESET + * should not be deleted + */ + + if (_gf_true == + glusterd_check_voloption_flags(key, VOLOPT_FLAG_NEVER_RESET)) { + if (*is_force != 1) + *is_force = *is_force | GD_OP_PROTECTED; + goto out; + } + + if (*is_force != 1) { + if (_gf_true == + glusterd_check_voloption_flags(key, VOLOPT_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; + } + } + + gf_msg_debug("glusterd", 0, "deleting dict with key=%s,value=%s", key, + value->data); + dict_del(this, key); + /**Delete scrubber (pause/resume) option from the dictionary if bitrot + * option is going to be reset + * */ + if (!strncmp(key, VKEY_FEATURES_BITROT, strlen(VKEY_FEATURES_BITROT))) { + dict_del_sizen(this, VKEY_FEATURES_SCRUB); + } +out: + return 0; } -int -glusterd_gsync_get_param_file (char *prmfile, const char *param, char *master, - char *slave, char *gl_workdir) +static int +_delete_reconfig_global_opt(dict_t *this, char *key, data_t *value, void *data) { - runner_t runner = {0,}; + GF_ASSERT(data); - runinit (&runner); - runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); - runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); - runner_argprintf (&runner, ":%s", master); - runner_add_args (&runner, slave, "--config-get", NULL); - runner_argprintf (&runner, "%s-file", param); + if (strcmp(GLUSTERD_GLOBAL_OPT_VERSION, key) == 0) + goto out; - return glusterd_query_extutil (prmfile, &runner); + _delete_reconfig_opt(this, key, value, data); +out: + return 0; } static int -gsyncd_getpidfile (char *master, char *slave, char *pidfile) -{ - int ret = -1; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; +glusterd_options_reset(glusterd_volinfo_t *volinfo, char *key, + int32_t *is_force) +{ + int ret = 0; + data_t *value = NULL; + char *key_fixed = NULL; + xlator_t *this = NULL; + glusterd_svc_t *svc = NULL; + + this = THIS; + GF_ASSERT(this); + GF_ASSERT(volinfo->dict); + GF_ASSERT(key); + + if (!strncmp(key, "all", 3)) { + dict_foreach(volinfo->dict, _delete_reconfig_opt, is_force); + ret = glusterd_enable_default_options(volinfo, NULL); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FAIL_DEFAULT_OPT_SET, + "Failed to set " + "default options on reset for volume %s", + volinfo->volname); + goto out; + } + } else { + value = dict_get(volinfo->dict, key); + if (!value) { + gf_msg_debug(this->name, 0, "no value set for option %s", key); + goto out; + } + _delete_reconfig_opt(volinfo->dict, key, value, is_force); + ret = glusterd_enable_default_options(volinfo, key); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FAIL_DEFAULT_OPT_SET, + "Failed to set " + "default value for option '%s' on reset for " + "volume %s", + key, volinfo->volname); + goto out; + } + } + + gd_update_volume_op_versions(volinfo); + if (!volinfo->is_snap_volume) { + svc = &(volinfo->snapd.svc); + ret = svc->manager(svc, volinfo, PROC_START_NO_WAIT); + if (ret) + goto out; + } + svc = &(volinfo->gfproxyd.svc); + ret = svc->reconfigure(volinfo); + if (ret) + goto out; + + svc = &(volinfo->shd.svc); + ret = svc->reconfigure(volinfo); + if (ret) + goto out; + + ret = glusterd_create_volfiles_and_notify_services(volinfo); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOLFILE_CREATE_FAIL, + "Unable to create volfile for" + " 'volume reset'"); + ret = -1; + goto out; + } - GF_VALIDATE_OR_GOTO ("gsync", master, out); - GF_VALIDATE_OR_GOTO ("gsync", slave, out); + ret = glusterd_store_volinfo(volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; - ret = glusterd_gsync_get_param_file (pidfile, "pid", master, - slave, priv->workdir); - if (ret == -1) { - ret = -2; - gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); - goto out; - } + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_svcs_reconfigure(volinfo); + if (ret) + goto out; + } - ret = open (pidfile, O_RDWR); + ret = 0; - out: - return ret; +out: + GF_FREE(key_fixed); + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } static int -gsync_status_byfd (int fd) -{ - GF_ASSERT (fd >= -1); - - if (lockf (fd, F_TEST, 0) == -1 && - (errno == EAGAIN || errno == EACCES)) - /* gsyncd keeps the pidfile locked */ - return 0; - - return -1; -} - -/* status: return 0 when gsync is running - * return -1 when not running - */ -int -gsync_status (char *master, char *slave, int *status) -{ - char pidfile[PATH_MAX] = {0,}; - int fd = -1; - - fd = gsyncd_getpidfile (master, slave, pidfile); - if (fd == -2) - return -1; - - *status = gsync_status_byfd (fd); +glusterd_op_reset_all_volume_options(xlator_t *this, dict_t *dict) +{ + 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; + + conf = this->private; + ret = dict_get_strn(dict, "key", SLEN("key"), &key); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Failed to get key"); + goto out; + } + + ret = dict_get_int32n(dict, "force", SLEN("force"), &is_force); + if (ret) + is_force = 0; + + if (strcmp(key, "all")) { + ret = glusterd_check_option_exists(key, &key_fixed); + if (ret <= 0) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, + "Option %s does not " + "exist", + key); + ret = -1; + goto out; + } + } else { + all = _gf_true; + } + + if (key_fixed) + key = key_fixed; + + ret = -1; + dup_opt = dict_new(); + if (!dup_opt) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_CREATE_FAIL, NULL); + goto out; + } + if (!all) { + dict_copy(conf->opts, dup_opt); + dict_del(dup_opt, key); + } + ret = glusterd_get_next_global_opt_version_str(conf->opts, &next_version); + if (ret) + goto out; + + ret = dict_set_strn(dup_opt, GLUSTERD_GLOBAL_OPT_VERSION, + SLEN(GLUSTERD_GLOBAL_OPT_VERSION), next_version); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=%s", GLUSTERD_GLOBAL_OPT_VERSION, NULL); + goto out; + } + + ret = glusterd_store_options(this, dup_opt); + if (ret) + goto out; + + if (glusterd_is_quorum_changed(conf->opts, key, NULL)) + quorum_action = _gf_true; + + ret = dict_set_dynstrn(conf->opts, GLUSTERD_GLOBAL_OPT_VERSION, + SLEN(GLUSTERD_GLOBAL_OPT_VERSION), next_version); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=%s", GLUSTERD_GLOBAL_OPT_VERSION, NULL); + goto out; + } else + next_version = NULL; + + if (!all) { + dict_del(conf->opts, key); + } else { + dict_foreach(conf->opts, _delete_reconfig_global_opt, &is_force); + } +out: + GF_FREE(key_fixed); + if (dup_opt) + dict_unref(dup_opt); - close (fd); - return 0; + gf_msg_debug(this->name, 0, "returning %d", ret); + if (quorum_action) + glusterd_do_quorum_action(); + GF_FREE(next_version); + return ret; } - -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"); - goto out; +static int +glusterd_op_reset_volume(dict_t *dict, char **op_rspstr) +{ + 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; + + this = THIS; + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get volume name"); + goto out; + } + + if (strcasecmp(volname, "all") == 0) { + ret = glusterd_op_reset_all_volume_options(this, dict); + goto out; + } + + ret = dict_get_int32n(dict, "force", SLEN("force"), &is_force); + if (ret) + is_force = 0; + + ret = dict_get_strn(dict, "key", SLEN("key"), &key); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get option key"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + FMTSTR_CHECK_VOL_EXISTS, volname); + goto out; + } + + if (strcmp(key, "all") && + glusterd_check_option_exists(key, &key_fixed) != 1) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, + "volinfo dict inconsistency: option %s not found", key); + ret = -1; + goto out; + } + if (key_fixed) + key = key_fixed; + + if (glusterd_is_quorum_changed(volinfo->dict, key, NULL)) + quorum_action = _gf_true; + + 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 { + ret = -1; + gf_asprintf(op_rspstr, + "'%s' is protected. To reset" + " use 'force'.", + key); } + } - ret = dict_set_dynstr (volinfo->dict, key, gsync_status); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set dict"); - goto out; + if (!strcmp(key, "ganesha.enable") || !strcmp(key, "all")) { + if (glusterd_check_ganesha_export(volinfo) && + is_origin_glusterd(dict)) { + ret = manage_export_config(volname, "off", op_rspstr); + if (ret) + gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_NFS_GNS_RESET_FAIL, + "Could not reset ganesha.enable key"); } + } - ret = 0; out: - return 0; + GF_FREE(key_fixed); + if (quorum_action) + glusterd_do_quorum_action(); + + gf_msg_debug(this->name, 0, "'volume reset' returning %d", ret); + return ret; } int -gsync_verify_config_options (dict_t *dict, char **op_errstr) +glusterd_stop_bricks(glusterd_volinfo_t *volinfo) { - char **resopt = NULL; - int i = 0; - char *subop = NULL; - char *slave = NULL; - char *op_name = NULL; - char *op_value = NULL; - gf_boolean_t banned = _gf_true; + glusterd_brickinfo_t *brickinfo = NULL; - if (dict_get_str (dict, "subop", &subop) != 0) { - gf_log ("", GF_LOG_WARNING, "missing subop"); - *op_errstr = gf_strdup ("Invalid config request"); - return -1; + cds_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)) { + gf_event(EVENT_BRICK_STOP_FAILED, "peer=%s;volume=%s;brick=%s", + brickinfo->hostname, volinfo->volname, brickinfo->path); + return -1; } + } - if (dict_get_str (dict, "slave", &slave) != 0) { - gf_log ("", GF_LOG_WARNING, GEOREP" CONFIG: no slave given"); - *op_errstr = gf_strdup ("Slave required"); - return -1; - } - - if (strcmp (subop, "get-all") == 0) - return 0; - - if (dict_get_str (dict, "op_name", &op_name) != 0) { - gf_log ("", GF_LOG_WARNING, "option name missing"); - *op_errstr = gf_strdup ("Option name missing"); - return -1; - } - - if (runcmd (GSYNCD_PREFIX"/gsyncd", "--config-check", op_name, NULL)) { - gf_log ("", GF_LOG_WARNING, "Invalid option %s", op_name); - *op_errstr = gf_strdup ("Invalid option"); - - return -1; - } - - if (strcmp (subop, "get") == 0) - return 0; - - if (strcmp (subop, "set") != 0 && strcmp (subop, "del") != 0) { - gf_log ("", GF_LOG_WARNING, "unknown subop %s", subop); - *op_errstr = gf_strdup ("Invalid config request"); - return -1; - } - - if (strcmp (subop, "set") == 0 && - dict_get_str (dict, "op_value", &op_value) != 0) { - gf_log ("", GF_LOG_WARNING, "missing value for set"); - *op_errstr = gf_strdup ("missing value"); - } - - /* match option name against reserved options, modulo -/_ - * difference - */ - for (resopt = gsync_reserved_opts; *resopt; resopt++) { - banned = _gf_true; - for (i = 0; (*resopt)[i] && op_name[i]; i++) { - if ((*resopt)[i] == op_name[i] || - ((*resopt)[i] == '-' && op_name[i] == '_')) - continue; - banned = _gf_false; - } - if (banned) { - gf_log ("", GF_LOG_WARNING, "Reserved option %s", op_name); - *op_errstr = gf_strdup ("Reserved option"); - - return -1; - break; - } - } - - return 0; + return 0; } -static void -_get_status_mst_slv (dict_t *this, char *key, data_t *value, void *data) -{ - glusterd_gsync_status_temp_t *param = NULL; - char *slave = NULL; - int ret = 0; - - param = (glusterd_gsync_status_temp_t *)data; - - GF_ASSERT (param); - GF_ASSERT (param->volinfo); - - slave = strchr(value->data, ':'); - if (slave) - slave ++; - else - return; - - ret = glusterd_get_gsync_status_mst_slv(param->volinfo, - slave, param->rsp_dict); - +int +glusterd_start_bricks(glusterd_volinfo_t *volinfo) + +{ + int ret = -1; + glusterd_brickinfo_t *brickinfo = NULL; + + GF_ASSERT(volinfo); + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (!brickinfo->start_triggered) { + pthread_mutex_lock(&brickinfo->restart_mutex); + { + /* coverity[SLEEP] */ + ret = glusterd_brick_start(volinfo, brickinfo, _gf_false, + _gf_false); + } + pthread_mutex_unlock(&brickinfo->restart_mutex); + if (ret) { + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_DISCONNECTED, + "Failed to start %s:%s for %s", brickinfo->hostname, + brickinfo->path, volinfo->volname); + gf_event(EVENT_BRICK_START_FAILED, "peer=%s;volume=%s;brick=%s", + brickinfo->hostname, volinfo->volname, + brickinfo->path); + goto out; + } + } + } + ret = 0; +out: + return ret; } -/* The return status indicates success (ret_status = 0) if the host uuid - * matches, status indicates failure (ret_status = -1) if the host uuid - * mismatches, status indicates not found if the slave is not found to be - * spawned for the given master */ -static void -_compare_host_uuid (dict_t *this, char *key, data_t *value, void *data) -{ - glusterd_gsync_slaves_t *status = NULL; - char *slave = NULL; - int uuid_len = 0; - - status = (glusterd_gsync_slaves_t *)data; - - if ((status->ret_status == -1) || (status->ret_status == 0)) - return; - slave = strchr(value->data, ':'); - if (slave) - slave ++; - - uuid_len = (slave - value->data - 1); - - if (strncmp (slave, status->slave, PATH_MAX) == 0) { - if (strncmp (value->data, status->host_uuid, uuid_len) == 0) { - status->ret_status = 0; - } else { - status->ret_status = -1; - strncpy (status->rmt_hostname, value->data, uuid_len); - status->rmt_hostname[uuid_len] = '\0'; +static int +glusterd_update_volumes_dict(glusterd_volinfo_t *volinfo) +{ + int ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + char *address_family_str = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO("glusterd", this, out); + + conf = this->private; + GF_VALIDATE_OR_GOTO(this->name, conf, out); + + /* 3.9.0 onwards gNFS will be disabled by default. In case of an upgrade + * from anything below than 3.9.0 to 3.9.x the volume's dictionary will + * not have 'nfs.disable' key set which means the same will not be set + * to on until explicitly done. setnfs.disable to 'on' at op-version + * bump up flow is the ideal way here. The same is also applicable for + * transport.address-family where if the transport type is set to tcp + * then transport.address-family is defaulted to 'inet'. + */ + if (conf->op_version >= GD_OP_VERSION_3_9_0) { + if (dict_get_str_boolean(volinfo->dict, NFS_DISABLE_MAP_KEY, 1)) { + ret = dict_set_dynstr_with_alloc(volinfo->dict, NFS_DISABLE_MAP_KEY, + "on"); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Failed to set " + "option ' NFS_DISABLE_MAP_KEY ' on " + "volume %s", + volinfo->volname); + goto out; + } + } + ret = dict_get_strn(volinfo->dict, "transport.address-family", + SLEN("transport.address-family"), + &address_family_str); + if (ret) { + if (volinfo->transport_type == GF_TRANSPORT_TCP) { + ret = dict_set_dynstr_with_alloc( + volinfo->dict, "transport.address-family", "inet"); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, errno, + GD_MSG_DICT_SET_FAILED, + "failed to set transport." + "address-family on %s", + volinfo->volname); + goto out; } + } } + } + ret = glusterd_store_volinfo(volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -} - -static void -_get_max_gsync_slave_num (dict_t *this, char *key, data_t *value, void *data) -{ - int tmp_slvnum = 0; - glusterd_gsync_slaves_t *status = NULL; - - status = (glusterd_gsync_slaves_t *)data; - - sscanf (key, "slave%d", &tmp_slvnum); - if (tmp_slvnum > status->ret_status) - status->ret_status = tmp_slvnum; -} - -static void -_remove_gsync_slave (dict_t *this, char *key, data_t *value, void *data) -{ - glusterd_gsync_slaves_t *status = NULL; - char *slave = NULL; - - - status = (glusterd_gsync_slaves_t *)data; - - slave = strchr(value->data, ':'); - if (slave) - slave ++; - - if (strncmp (slave, status->slave, PATH_MAX) == 0) - dict_del (this, key); - +out: + return ret; } static int -glusterd_remove_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, - char *host_uuid, char **op_errstr) +glusterd_set_brick_mx_opts(dict_t *dict, char *key, char *value, + char **op_errstr) { - int ret = 0; - glusterd_gsync_slaves_t status = {0, }; - char cann_slave[PATH_MAX] = {0, }; + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (host_uuid); + this = THIS; + GF_VALIDATE_OR_GOTO("glusterd", this, out); + GF_VALIDATE_OR_GOTO(this->name, dict, out); + GF_VALIDATE_OR_GOTO(this->name, key, out); + GF_VALIDATE_OR_GOTO(this->name, value, out); + GF_VALIDATE_OR_GOTO(this->name, op_errstr, out); - ret = glusterd_get_canon_url (cann_slave, slave, _gf_false); - if (ret) - goto out; - - status.slave = cann_slave; - status.host_uuid = host_uuid; - status.ret_status = 1; + ret = 0; - dict_foreach (volinfo->gsync_slaves, _remove_gsync_slave, &status); + priv = this->private; - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) { - *op_errstr = gf_strdup ("Failed to store the Volume" - "information"); - goto out; - } - out: - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; + if (!strcmp(key, GLUSTERD_BRICK_MULTIPLEX_KEY)) { + ret = dict_set_dynstrn(priv->opts, GLUSTERD_BRICK_MULTIPLEX_KEY, + SLEN(GLUSTERD_BRICK_MULTIPLEX_KEY), + gf_strdup(value)); + } +out: + return ret; } +/* This is a hack to prevent client-io-threads from being loaded in the graph + * when the cluster-op-version is bumped up from 3.8.x to 3.13.x. The key is + * deleted subsequently in glusterd_create_volfiles(). */ static int -glusterd_gsync_get_uuid (char *slave, glusterd_volinfo_t *vol, - uuid_t uuid) +glusterd_dict_set_skip_cliot_key(glusterd_volinfo_t *volinfo) { - - int ret = 0; - glusterd_gsync_slaves_t status = {0, }; - char cann_slave[PATH_MAX] = {0, }; - char host_uuid_str[64] = {0}; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (vol); - GF_ASSERT (slave); - - uuid_utoa_r (priv->uuid, host_uuid_str); - ret = glusterd_get_canon_url (cann_slave, slave, _gf_false); - if (ret) - goto out; - - status.slave = cann_slave; - status.host_uuid = host_uuid_str; - status.ret_status = 1; - dict_foreach (vol->gsync_slaves, _compare_host_uuid, &status); - if (status.ret_status == 0) { - uuid_copy (uuid, priv->uuid); - } else if (status.ret_status == -1) { - uuid_parse (status.rmt_hostname, uuid); - } else { - ret = -1; - goto out; - } - ret = 0; - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; - + return dict_set_int32n(volinfo->dict, "skip-CLIOT", SLEN("skip-CLIOT"), 1); } static int -glusterd_check_gsync_running_local (char *master, char *slave, - gf_boolean_t *is_run) +glusterd_op_set_all_volume_options(xlator_t *this, dict_t *dict, + char **op_errstr) { - int ret = -1; - int ret_status = 0; - - GF_ASSERT (master); - GF_ASSERT (slave); - GF_ASSERT (is_run); - - *is_run = _gf_false; - ret = gsync_status (master, slave, &ret_status); - if (ret == 0 && ret_status == 0) { - *is_run = _gf_true; - } else if (ret == -1) { - gf_log ("", GF_LOG_WARNING, GEOREP" validation " - " failed"); - goto out; - } + 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; + uint32_t op_version = 0; + glusterd_volinfo_t *volinfo = NULL; + glusterd_svc_t *svc = NULL; + gf_boolean_t svcs_reconfigure = _gf_false; + + conf = this->private; + ret = dict_get_strn(dict, "key1", SLEN("key1"), &key); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=key1", NULL); + goto out; + } + + ret = dict_get_strn(dict, "value1", SLEN("value1"), &value); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "invalid key,value pair in 'volume set'"); + goto out; + } + + ret = glusterd_check_option_exists(key, &key_fixed); + if (ret <= 0) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNKNOWN_KEY, + "Invalid key %s", key); + ret = -1; + goto out; + } + + if (key_fixed) + key = key_fixed; + + ret = glusterd_set_shared_storage(dict, key, value, op_errstr); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SHARED_STRG_SET_FAIL, + "Failed to set shared storage option"); + goto out; + } + + ret = glusterd_set_brick_mx_opts(dict, key, value, op_errstr); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_MX_SET_FAIL, + "Failed to set brick multiplexing option"); + goto out; + } + + /* If the key is cluster.op-version, set conf->op_version to the value + * if needed and save it. + */ + if (strcmp(key, GLUSTERD_GLOBAL_OP_VERSION_KEY) == 0) { ret = 0; - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; - -} - -static int -glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, - char *host_uuid, char **op_errstr) -{ - int ret = 0; - glusterd_gsync_slaves_t status = {0, }; - char cann_slave[PATH_MAX] = {0, }; - char *value = NULL; - char key[512] = {0, }; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (host_uuid); - - ret = glusterd_get_canon_url (cann_slave, slave, _gf_false); - if (ret) - goto out; - - status.slave = cann_slave; - status.host_uuid = host_uuid; - status.ret_status = 1; - dict_foreach (volinfo->gsync_slaves, _compare_host_uuid, &status); - - if (status.ret_status == -1) { - gf_log ("", GF_LOG_ERROR, GEOREP" has already been invoked for " - "the %s (master) and %s (slave)" - "from a different machine", - volinfo->volname, slave); - *op_errstr = gf_strdup (GEOREP" already running in an an" - "orhter machine"); - ret = -1; - goto out; - } - - memset (&status, 0, sizeof (status)); - - dict_foreach (volinfo->gsync_slaves, _get_max_gsync_slave_num, &status); - - gf_asprintf (&value, "%s:%s", host_uuid, cann_slave); - snprintf (key, 512, "slave%d", status.ret_status +1); - ret = dict_set_dynstr (volinfo->gsync_slaves, key, value); + ret = gf_string2uint(value, &op_version); if (ret) - goto out; - 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 = 0; - out: - return ret; -} - + goto out; + + if (op_version >= conf->op_version) { + conf->op_version = op_version; + + /* When a bump up happens, update the quota.conf file + * as well. This is because, till 3.7 we had a quota + * conf version v1.1 in quota.conf. When inode-quota + * feature is introduced, this needs to be changed to + * v1.2 in quota.conf and 16 bytes uuid in quota.conf + * needs to be changed to 17 bytes. Look + * glusterd_store_quota_config for more details. + */ + cds_list_for_each_entry(volinfo, &conf->volumes, vol_list) + { + ret = glusterd_store_quota_config( + volinfo, NULL, NULL, GF_QUOTA_OPTION_TYPE_UPGRADE, NULL); + if (ret) + goto out; + ret = glusterd_update_volumes_dict(volinfo); + if (ret) + goto out; -static int -glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo, - char *slave, char **op_errstr) -{ - int ret = -1; - gf_boolean_t is_running = _gf_false; - char msg[2048] = {0}; - uuid_t uuid = {0}; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; + if (glusterd_dict_set_skip_cliot_key(volinfo)) + goto out; - this = THIS; + if (!volinfo->is_snap_volume) { + svc = &(volinfo->snapd.svc); + ret = svc->manager(svc, volinfo, PROC_START_NO_WAIT); + if (ret) + goto out; + } - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (op_errstr); - GF_ASSERT (this && this->private); + svc = &(volinfo->gfproxyd.svc); + ret = svc->reconfigure(volinfo); + if (ret) + goto out; - priv = this->private; + svc = &(volinfo->shd.svc); + ret = svc->reconfigure(volinfo); + if (ret) + goto out; - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - snprintf (msg, sizeof (msg), "Volume %s needs to be started " - "before "GEOREP" start", volinfo->volname); - goto out; - } - /*Check if the gsync is already started in cmd. inited host - * If so initiate add it into the glusterd's priv*/ - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if ((ret == 0) && (uuid_compare (priv->uuid, uuid) == 0)) { - ret = glusterd_check_gsync_running_local (volinfo->volname, - slave, &is_running); + ret = glusterd_create_volfiles_and_notify_services(volinfo); if (ret) { - snprintf (msg, sizeof (msg), GEOREP" start option " - "validation failed "); - goto out; + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_VOLFILE_CREATE_FAIL, + "Unable to create volfile for" + " 'volume set'"); + goto out; } - if (_gf_true == is_running) { - snprintf (msg, sizeof (msg), GEOREP " session between" - " %s & %s already started", volinfo->volname, - slave); - ret = -1; - goto out; + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + svcs_reconfigure = _gf_true; } - } - ret = 0; -out: - if (ret && (msg[0] != '\0')) { - *op_errstr = gf_strdup (msg); - } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -int -glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag) -{ - - GF_ASSERT (volinfo); - GF_ASSERT (flag); - - if (volinfo->gsync_slaves->count) - *flag = _gf_true; - else - *flag = _gf_false; - - return 0; -} - -static int -glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, - char *slave, char **op_errstr) -{ - int ret = -1; - char msg[2048] = {0}; - uuid_t uuid = {0}; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS && THIS->private); - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (op_errstr); - - priv = THIS->private; - - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - snprintf (msg, sizeof (msg), "Volume %s needs to be started " - "before "GEOREP" start", volinfo->volname); + } + if (svcs_reconfigure) { + ret = glusterd_svcs_reconfigure(NULL); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SVC_RESTART_FAIL, + "Unable to restart " + "services"); + goto out; + } + } - goto out; - } - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if (ret == -1) { - snprintf (msg, sizeof (msg), GEOREP" session between %s & %s" - " not active", volinfo->volname, slave); - goto out; + ret = glusterd_store_global_info(this); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_OP_VERS_STORE_FAIL, + "Failed to store op-version."); + } } + /* No need to save cluster.op-version in conf->opts + */ + goto out; + } + ret = -1; + dup_opt = dict_new(); + if (!dup_opt) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_CREATE_FAIL, NULL); + goto out; + } + dict_copy(conf->opts, dup_opt); + ret = dict_set_str(dup_opt, key, value); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=%s", key, NULL); + goto out; + } + + ret = glusterd_get_next_global_opt_version_str(conf->opts, &next_version); + if (ret) + goto out; + + ret = dict_set_strn(dup_opt, GLUSTERD_GLOBAL_OPT_VERSION, + SLEN(GLUSTERD_GLOBAL_OPT_VERSION), next_version); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=%s", GLUSTERD_GLOBAL_OPT_VERSION, NULL); + goto out; + } + + ret = glusterd_store_options(this, dup_opt); + if (ret) + goto out; + + if (glusterd_is_quorum_changed(conf->opts, key, value)) + quorum_action = _gf_true; + + ret = dict_set_dynstrn(conf->opts, GLUSTERD_GLOBAL_OPT_VERSION, + SLEN(GLUSTERD_GLOBAL_OPT_VERSION), next_version); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=%s", GLUSTERD_GLOBAL_OPT_VERSION, NULL); + goto out; + } else + next_version = NULL; + + dup_value = gf_strdup(value); + if (!dup_value) + goto out; + + ret = dict_set_dynstr(conf->opts, key, dup_value); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=%s", key, NULL); + goto out; + } else + dup_value = NULL; /* Protect the allocation from GF_FREE */ - ret = 0; out: - if (ret && (msg[0] != '\0')) { - *op_errstr = gf_strdup (msg); - } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -static int -glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr) -{ - char *slave = NULL; - char *volname = NULL; - char errmsg[PATH_MAX] = {0, }; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - int ret = 0; - - ret = dict_get_str (dict, "master", &volname); - if (ret < 0) { - ret = 0; - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((ret) || (!exists)) { - gf_log ("", GF_LOG_WARNING, "volume name does not exist"); - snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" - " exist", volname); - *op_errstr = gf_strdup (errmsg); - ret = -1; - goto out; - } - - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) { - ret = 0; - goto out; - } - - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + GF_FREE(dup_value); + GF_FREE(key_fixed); + if (dup_opt) + dict_unref(dup_opt); + gf_msg_debug(this->name, 0, "returning %d", ret); + if (quorum_action) + glusterd_do_quorum_action(); + GF_FREE(next_version); + return ret; } - -static int -glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, - char **master, char **slave) +int +glusterd_op_get_max_opversion(char **op_errstr, dict_t *rsp_dict) { + int ret = -1; - int ret = -1; - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (master); - GF_ASSERT (slave); - - 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"); - 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"); - goto out; - } + GF_VALIDATE_OR_GOTO(THIS->name, rsp_dict, out); + ret = dict_set_int32n(rsp_dict, "max-opversion", SLEN("max-opversion"), + GD_OP_VERSION_MAX); + if (ret) { + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Setting value for max-opversion to dict failed"); + goto out; + } - ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + gf_msg_debug(THIS->name, 0, "Returning %d", ret); + return ret; } static int -glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) -{ - int ret = 0; - int type = 0; - char *volname = NULL; - char *slave = NULL; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - char errmsg[PATH_MAX] = {0,}; - - - 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"); - goto out; - } - - switch (type) { - case GF_GSYNC_OPTION_TYPE_STATUS: - ret = glusterd_verify_gsync_status_opts (dict, op_errstr); - - goto out; - case GF_GSYNC_OPTION_TYPE_CONFIG: - ret = gsync_verify_config_options (dict, op_errstr); - - goto out; - } - - ret = glusterd_op_gsync_args_get (dict, op_errstr, &volname, &slave); - if (ret) - goto out; +glusterd_set_shared_storage(dict_t *dict, char *key, char *value, + char **op_errstr) +{ + int32_t ret = -1; + char hooks_args[PATH_MAX] = { + 0, + }; + char errstr[PATH_MAX] = { + 0, + }; + xlator_t *this = NULL; + int32_t len = 0; + + this = THIS; + GF_VALIDATE_OR_GOTO("glusterd", this, out); + GF_VALIDATE_OR_GOTO(this->name, dict, out); + GF_VALIDATE_OR_GOTO(this->name, key, out); + GF_VALIDATE_OR_GOTO(this->name, value, out); + GF_VALIDATE_OR_GOTO(this->name, op_errstr, out); + + ret = 0; + + if (strcmp(key, GLUSTERD_SHARED_STORAGE_KEY)) { + goto out; + } + + /* Re-create the brick path so as to be * + * able to re-use it * + */ + ret = recursive_rmdir(GLUSTER_SHARED_STORAGE_BRICK_DIR); + if (ret) { + snprintf(errstr, PATH_MAX, + "Failed to remove shared " + "storage brick(%s). " + "Reason: %s", + GLUSTER_SHARED_STORAGE_BRICK_DIR, strerror(errno)); + gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DIR_OP_FAILED, "%s", + errstr); + ret = -1; + goto out; + } + + ret = mkdir_p(GLUSTER_SHARED_STORAGE_BRICK_DIR, 0755, _gf_true); + if (-1 == ret) { + snprintf(errstr, PATH_MAX, + "Failed to create shared " + "storage brick(%s). " + "Reason: %s", + GLUSTER_SHARED_STORAGE_BRICK_DIR, strerror(errno)); + gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_CREATE_DIR_FAILED, "%s", + errstr); + goto out; + } + + if (is_origin_glusterd(dict)) { + len = snprintf(hooks_args, sizeof(hooks_args), + "is_originator=1,local_node_hostname=%s", + local_node_hostname); + } else { + len = snprintf(hooks_args, sizeof(hooks_args), + "is_originator=0,local_node_hostname=%s", + local_node_hostname); + } + if ((len < 0) || (len >= sizeof(hooks_args))) { + ret = -1; + goto out; + } - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((ret) || (!exists)) { - gf_log ("", GF_LOG_WARNING, "volume name does not exist"); - snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" - " exist", volname); - *op_errstr = gf_strdup (errmsg); - ret = -1; - goto out; - } - - switch (type) { - case GF_GSYNC_OPTION_TYPE_START: - ret = glusterd_op_verify_gsync_start_options (volinfo, slave, - op_errstr); - break; - case GF_GSYNC_OPTION_TYPE_STOP: - ret = glusterd_op_verify_gsync_running (volinfo, slave, - op_errstr); - break; - } + ret = dict_set_dynstr_with_alloc(dict, "hooks_args", hooks_args); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Failed to set" + " hooks_args in dict."); + goto out; + } out: - return ret; -} + if (ret && strlen(errstr)) { + *op_errstr = gf_strdup(errstr); + } -static gf_boolean_t -glusterd_is_profile_on (glusterd_volinfo_t *volinfo) -{ - int ret = -1; - gf_boolean_t is_latency_on = _gf_false; - gf_boolean_t is_fd_stats_on = _gf_false; - - GF_ASSERT (volinfo); - - ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_CNT_FOP_HITS); - if (ret != -1) - is_fd_stats_on = ret; - ret = glusterd_volinfo_get_boolean (volinfo, VKEY_DIAG_LAT_MEASUREMENT); - if (ret != -1) - is_latency_on = ret; - if ((_gf_true == is_latency_on) && - (_gf_true == is_fd_stats_on)) - return _gf_true; - return _gf_false; + return ret; } static int -glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - char msg[2048] = {0,}; - int32_t stats_op = GF_CLI_STATS_NONE; - glusterd_volinfo_t *volinfo = NULL; - - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - snprintf (msg, sizeof (msg), "Volume name get failed"); - goto out; - } - - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((!exists) || (ret < 0)) { - snprintf (msg, sizeof (msg), "Volume %s, " - "doesn't exist", volname); - ret = -1; - goto out; - } - - ret = dict_get_int32 (dict, "op", &stats_op); - if (ret) { - snprintf (msg, sizeof (msg), "Volume profile op get failed"); - goto out; - } - - if (GF_CLI_STATS_START == stats_op) { - if (_gf_true == glusterd_is_profile_on (volinfo)) { - snprintf (msg, sizeof (msg), "Profile on Volume %s is" - " already started", volinfo->volname); - ret = -1; - goto out; - } - } - if ((GF_CLI_STATS_STOP == stats_op) || - (GF_CLI_STATS_INFO == stats_op)) { - if (_gf_false == glusterd_is_profile_on (volinfo)) { - snprintf (msg, sizeof (msg), "Profile on Volume %s is" - " not started", volinfo->volname); - ret = -1; - goto out; - } - } - if ((GF_CLI_STATS_TOP == stats_op) || - (GF_CLI_STATS_INFO == stats_op)) { - if (_gf_false == glusterd_is_volume_started (volinfo)) { - snprintf (msg, sizeof (msg), "Volume %s is not started.", - volinfo->volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - ret = -1; - goto out; - } - } - ret = 0; -out: - if (msg[0] != '\0') { - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - *op_errstr = gf_strdup (msg); - } - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - 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; - gf_boolean_t vol_added = _gf_false; - 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); +glusterd_op_set_volume(dict_t *dict, char **errstr) +{ + int ret = 0; + glusterd_volinfo_t *volinfo = NULL; + char *volname = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + int count = 1; + char *key = NULL; + char *key_fixed = NULL; + char *value = NULL; + char keystr[50] = { + 0, + }; + int keylen; + gf_boolean_t global_opt = _gf_false; + 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; + glusterd_svc_t *svc = NULL; + + this = THIS; + GF_ASSERT(this); + + priv = this->private; + GF_ASSERT(priv); + + ret = dict_get_int32n(dict, "count", SLEN("count"), &dict_count); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Count(dict),not set in Volume-Set"); + goto out; + } + + if (dict_count == 0) { + ret = glusterd_volset_help(NULL, errstr); + goto out; + } + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get volume name"); + goto out; + } + + if (strcasecmp(volname, "all") == 0) { + ret = glusterd_op_set_all_volume_options(this, dict, errstr); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + FMTSTR_CHECK_VOL_EXISTS, volname); + goto out; + } + + /* TODO: Remove this once v3.3 compatibility 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_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get new op-version from dict"); + goto out; + } + } + + for (count = 1; ret != -1; count++) { + keylen = snprintf(keystr, sizeof(keystr), "key%d", count); + ret = dict_get_strn(dict, keystr, keylen, &key); + if (ret) + break; + keylen = snprintf(keystr, sizeof(keystr), "value%d", count); + ret = dict_get_strn(dict, keystr, keylen, &value); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "invalid key,value pair in 'volume set'"); + ret = -1; + goto out; } - ret = dict_get_str (dict, "volname", &volname); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + if (strcmp(key, "config.memory-accounting") == 0) { + ret = gf_string2boolean(value, &volinfo->memory_accounting); + if (ret == -1) { + gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY, + "Invalid value in key-value pair."); 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"); + if (strcmp(key, "config.transport") == 0) { + gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_VOL_TRANSPORT_TYPE_CHANGE, + "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; + } } - ret = dict_get_int32 (dict, "count", &volinfo->brick_count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); - goto out; - } + ret = glusterd_check_ganesha_cmd(key, value, errstr, dict); + if (ret == -1) + goto out; - ret = dict_get_int32 (dict, "port", &volinfo->port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get port"); + if (!is_key_glusterd_hooks_friendly(key)) { + ret = glusterd_check_option_exists(key, &key_fixed); + GF_ASSERT(ret); + if (ret <= 0) { + key_fixed = NULL; 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; + global_opt = _gf_false; + if (glusterd_check_globaloption(key)) { + global_opt = _gf_true; + global_opts_set = _gf_true; } - 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; - } else if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) { - ret = dict_get_int32 (dict, "stripe-count", - &volinfo->stripe_count); - if (ret) - goto out; - ret = dict_get_int32 (dict, "replica-count", - &volinfo->replica_count); - if (ret) - goto out; + if (!global_opt) + value = gf_strdup(value); - sub_count = volinfo->stripe_count * volinfo->replica_count; + if (!value) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_SET_FAIL, + "Unable to set the options in 'volume set'"); + ret = -1; + goto out; } - ret = dict_get_str (dict, "transport", &trans_type); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get transport"); - goto out; - } + if (key_fixed) + key = key_fixed; - 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 (glusterd_is_quorum_changed(volinfo->dict, key, value)) + quorum_action = _gf_true; - if (strcasecmp (trans_type, "rdma") == 0) { - volinfo->transport_type = GF_TRANSPORT_RDMA; - volinfo->nfs_transport_type = GF_TRANSPORT_RDMA; - } else if (strcasecmp (trans_type, "tcp") == 0) { - volinfo->transport_type = GF_TRANSPORT_TCP; - volinfo->nfs_transport_type = GF_TRANSPORT_TCP; + if (global_opt) { + cds_list_for_each_entry(voliter, &priv->volumes, vol_list) + { + value = gf_strdup(value); + ret = dict_set_dynstr(voliter->dict, key, value); + if (ret) + goto out; + } } else { - volinfo->transport_type = GF_TRANSPORT_BOTH_TCP_RDMA; - volinfo->nfs_transport_type = GF_DEFAULT_NFS_TRANSPORT; + ret = dict_set_dynstr(volinfo->dict, key, value); + if (ret) + goto out; } - volinfo->sub_count = sub_count; - - if (bricks) { - brick_list = gf_strdup (bricks); - free_ptr = brick_list; + if (key_fixed) { + GF_FREE(key_fixed); + key_fixed = NULL; } + } - 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) { - glusterd_store_delete_volume (volinfo); - *op_errstr = gf_strdup ("Failed to store the Volume information"); - goto out; - } + if (count == 1) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_NO_OPTIONS_GIVEN, + "No options received "); + ret = -1; + goto out; + } - ret = glusterd_create_volfiles_and_notify_services (volinfo); + /* 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) { - *op_errstr = gf_strdup ("Failed to create volume files"); - goto out; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_OP_VERS_STORE_FAIL, + "Failed to store op-version"); + goto out; } + } + if (!global_opts_set) { + gd_update_volume_op_versions(volinfo); - ret = glusterd_volume_compute_cksum (volinfo); - if (ret) { - *op_errstr = gf_strdup ("Failed to compute checksum of volume"); + if (!volinfo->is_snap_volume) { + svc = &(volinfo->snapd.svc); + ret = svc->manager(svc, volinfo, PROC_START_NO_WAIT); + if (ret) goto out; } + svc = &(volinfo->gfproxyd.svc); + ret = svc->reconfigure(volinfo); + if (ret) + goto out; - volinfo->defrag_status = 0; - list_add_tail (&volinfo->vol_list, &priv->volumes); - vol_added = _gf_true; -out: - if (free_ptr) - GF_FREE(free_ptr); - if (!vol_added && volinfo) - glusterd_volinfo_delete (volinfo); - 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); + svc = &(volinfo->shd.svc); + ret = svc->reconfigure(volinfo); + if (ret) + goto out; + ret = glusterd_create_volfiles_and_notify_services(volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOLFILE_CREATE_FAIL, + "Unable to create volfile for" + " 'volume set'"); + ret = -1; + goto out; } - ret = glusterd_volinfo_find (volname, &volinfo); - - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } + ret = glusterd_store_volinfo(volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; - ret = dict_get_int32 (dict, "count", &count); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get count"); + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_svcs_reconfigure(volinfo); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SVC_RESTART_FAIL, + "Unable to restart services"); goto out; + } } + } else { + cds_list_for_each_entry(voliter, &priv->volumes, vol_list) + { + volinfo = voliter; + gd_update_volume_op_versions(volinfo); - ret = dict_get_str (dict, "bricks", &bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); - goto out; - } + if (!volinfo->is_snap_volume) { + svc = &(volinfo->snapd.svc); + ret = svc->manager(svc, volinfo, PROC_START_NO_WAIT); + if (ret) + goto out; + } - ret = glusterd_op_perform_add_bricks (volinfo, count, bricks); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to add bricks"); + svc = &(volinfo->gfproxyd.svc); + ret = svc->reconfigure(volinfo); + if (ret) goto out; - } - volinfo->defrag_status = 0; - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) + svc = &(volinfo->shd.svc); + ret = svc->reconfigure(volinfo); + 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"); + ret = glusterd_create_volfiles_and_notify_services(volinfo); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOLFILE_CREATE_FAIL, + "Unable to create volfile for" + " 'volume set'"); + ret = -1; 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) -{ - 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); + ret = glusterd_store_volinfo(volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) goto out; - } - - glusterd_delete_volfile (volinfo, src_brickinfo); - 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 (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_svcs_reconfigure(volinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not regenerate volfiles without pump"); - goto out; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SVC_RESTART_FAIL, + "Unable to restart services"); + goto out; } - - } - - 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; + GF_FREE(key_fixed); + gf_msg_debug(this->name, 0, "returning %d", ret); + if (quorum_action) + glusterd_do_quorum_action(); + 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; - } - +glusterd_op_sync_volume(dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ + int ret = -1; + char *volname = NULL; + char *hostname = NULL; + char msg[2048] = { + 0, + }; + int count = 1; + int vol_count = 0; + 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_strn(dict, "hostname", SLEN("hostname"), &hostname); + if (ret) { + snprintf(msg, sizeof(msg), + "hostname couldn't be " + "retrieved from msg"); + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Key=hostname", NULL); + *op_errstr = gf_strdup(msg); + goto out; + } + + if (!gf_is_local_addr(hostname)) { ret = 0; + goto out; + } -out: - return ret; -} - -static int -rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *brickinfo) -{ - glusterd_conf_t *priv = NULL; - runner_t runner = {0,}; - int ret = -1; - int32_t port = 0; - - priv = THIS->private; - - port = pmap_registry_alloc (THIS); - brickinfo->port = port; - - GF_ASSERT (port); - - runinit (&runner); - runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); - runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_DSTBRICKVOL_FILENAME, - priv->workdir, volinfo->volname); - runner_argprintf (&runner, "-p" "%s/vols/%s/"RB_DSTBRICK_PIDFILE, - priv->workdir, volinfo->volname); - runner_add_arg (&runner, "--xlator-option"); - runner_argprintf (&runner, "src-server.listen-port=%d", port); - - ret = runner_run (&runner); + // volname is not present in case of sync all + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (!ret) { + ret = glusterd_volinfo_find(volname, &volinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not start glusterfs"); - goto out; + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + "Volume with name: %s " + "not exists", + volname); + goto out; } + } - gf_log ("", GF_LOG_DEBUG, - "Successfully started glusterfs: brick=%s:%s", - brickinfo->hostname, brickinfo->path); - + if (!rsp_dict) { + // this should happen only on source + gf_smsg(this->name, GF_LOG_INFO, errno, GD_MSG_INVALID_ARGUMENT, NULL); ret = 0; + goto out; + } -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,}; - runner_t runner = {0,}; - struct stat buf; - int ret = -1; - - priv = THIS->private; - - runinit (&runner); - runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); - runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_CLIENTVOL_FILENAME, - priv->workdir, volinfo->volname); - runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, - priv->workdir, volinfo->volname); - - ret = runner_run (&runner); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not start glusterfs"); + if (volname) { + ret = glusterd_add_volume_to_dict(volinfo, rsp_dict, 1, "volume"); + if (ret) + goto out; + vol_count = 1; + } else { + cds_list_for_each_entry(volinfo, &priv->volumes, vol_list) + { + ret = glusterd_add_volume_to_dict(volinfo, rsp_dict, count, + "volume"); + if (ret) 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; + vol_count = count++; + } + } + ret = dict_set_int32n(rsp_dict, "count", SLEN("count"), vol_count); out: - return ret; -} + gf_msg_debug("glusterd", 0, "Returning %d", 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" - " option transport-type %s\n" - "end-volume\n" - "volume mnt-wb\n" - " type performance/write-behind\n" - " subvolumes mnt-client\n" - "end-volume\n"; + return ret; +} 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] = {0, }; - int ret = -1; - char *ttype = NULL; - - 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); - switch (volinfo->transport_type) { - case GF_TRANSPORT_RDMA: - ret = gf_asprintf (&ttype, "rdma"); - break; - case GF_TRANSPORT_TCP: - case GF_TRANSPORT_BOTH_TCP_RDMA: - ret = gf_asprintf (&ttype, "tcp"); - default: - gf_log (THIS->name, GF_LOG_ERROR, "Unknown " - "transport type"); - ret = -1; - goto out; - } - - fprintf (file, client_volfile_str, src_brickinfo->hostname, - src_brickinfo->path, src_brickinfo->port, ttype); - - fclose (file); - GF_FREE (ttype); - - ret = 0; - +glusterd_add_profile_volume_options(glusterd_volinfo_t *volinfo) +{ + int ret = -1; + + GF_ASSERT(volinfo); + + ret = dict_set_nstrn(volinfo->dict, VKEY_DIAG_LAT_MEASUREMENT, + SLEN(VKEY_DIAG_LAT_MEASUREMENT), "on", SLEN("on")); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "failed to set the volume %s " + "option %s value %s", + volinfo->volname, VKEY_DIAG_LAT_MEASUREMENT, "on"); + goto out; + } + + ret = dict_set_nstrn(volinfo->dict, VKEY_DIAG_CNT_FOP_HITS, + SLEN(VKEY_DIAG_CNT_FOP_HITS), "on", SLEN("on")); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "failed to set the volume %s " + "option %s value %s", + volinfo->volname, VKEY_DIAG_CNT_FOP_HITS, "on"); + goto out; + } out: - return ret; + gf_msg_debug("glusterd", 0, "Returning %d", ret); + 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 %s\n" - " subvolumes %s\n" - "end-volume\n"; - -static int -rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) +static void +glusterd_remove_profile_volume_options(glusterd_volinfo_t *volinfo) { - glusterd_conf_t *priv = NULL; - FILE *file = NULL; - char filename[PATH_MAX] = {0, }; - int ret = -1; - char *trans_type = NULL; + GF_ASSERT(volinfo); - 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); + dict_del_sizen(volinfo->dict, VKEY_DIAG_LAT_MEASUREMENT); + dict_del_sizen(volinfo->dict, VKEY_DIAG_CNT_FOP_HITS); +} - file = fopen (filename, "w+"); - if (!file) { - gf_log ("", GF_LOG_DEBUG, - "Open of volfile failed"); - ret = -1; +int +glusterd_op_stats_volume(dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ + int ret = -1; + char *volname = NULL; + char msg[2048] = { + 0, + }; + glusterd_volinfo_t *volinfo = NULL; + int32_t stats_op = GF_CLI_STATS_NONE; + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "volume name get failed"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + snprintf(msg, sizeof(msg), "Volume %s does not exists", volname); + + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, "%s", msg); + goto out; + } + + ret = dict_get_int32n(dict, "op", SLEN("op"), &stats_op); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "volume profile op get failed"); + goto out; + } + + switch (stats_op) { + case GF_CLI_STATS_START: + ret = glusterd_add_profile_volume_options(volinfo); + if (ret) goto out; - } - - switch (volinfo->transport_type) { - case GF_TRANSPORT_TCP: - case GF_TRANSPORT_BOTH_TCP_RDMA: - ret = gf_asprintf (&trans_type, "tcp"); - break; - case GF_TRANSPORT_RDMA: - ret = gf_asprintf (&trans_type, "rdma"); - break; - default: - gf_log (THIS->name, GF_LOG_ERROR, "Unknown " - "transport type"); - ret = -1; - goto out; - } - - fprintf (file, dst_brick_volfile_str, dst_brickinfo->path, - dst_brickinfo->path, dst_brickinfo->path, - trans_type, dst_brickinfo->path); + break; + case GF_CLI_STATS_STOP: + glusterd_remove_profile_volume_options(volinfo); + break; + case GF_CLI_STATS_INFO: + case GF_CLI_STATS_TOP: + // info is already collected in brick op. + // just goto out; + ret = 0; + goto out; + break; + default: + GF_ASSERT(0); + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, + "Invalid profile op: %d", stats_op); + ret = -1; + goto out; + break; + } + ret = glusterd_create_volfiles_and_notify_services(volinfo); + + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOLFILE_CREATE_FAIL, + "Unable to create volfile for" + " 'volume set'"); + ret = -1; + goto out; + } - GF_FREE (trans_type); + ret = glusterd_store_volinfo(volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) + goto out; - fclose (file); + if (GLUSTERD_STATUS_STARTED == volinfo->status) { + ret = glusterd_svcs_reconfigure(volinfo); + if (ret) + goto out; + } - ret = 0; + 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; + gf_msg_debug("glusterd", 0, "Returning %d", ret); - 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; + 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; +_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[16] = { + 0, + }; + char dict_key[64] = { + /* dict_key is small as prefix is up to 32 chars */ + 0, + }; + int keylen; + char *brick = NULL; + xlator_t *this = NULL; + + GF_ASSERT(dict); + GF_ASSERT(volinfo); + GF_ASSERT(prefix); + + this = THIS; + GF_ASSERT(this); + + ret = dict_get_int32n(volinfo->rebal.dict, "count", SLEN("count"), &count); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Failed to get brick count"); + goto out; + } + + keylen = snprintf(dict_key, sizeof(dict_key), "%s.count", prefix); + ret = dict_set_int32n(dict, dict_key, keylen, count); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set brick count in dict"); + goto out; + } + + for (i = 1; i <= count; i++) { + keylen = snprintf(brick_key, sizeof(brick_key), "brick%d", i); + + ret = dict_get_strn(volinfo->rebal.dict, brick_key, keylen, &brick); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get %s", brick_key); + goto out; + } + + keylen = snprintf(dict_key, sizeof(dict_key), "%s.%s", prefix, + brick_key); + if ((keylen < 0) || (keylen >= sizeof(dict_key))) { + ret = -1; + goto out; + } + ret = dict_set_strn(dict, dict_key, keylen, brick); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to add brick to dict"); + goto out; + } + brick = NULL; + } out: - return ret; + return ret; } +/* This adds the respective task-id and all available parameters of a task into + * a dictionary + */ static int -rb_destroy_maintenance_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) +_add_task_to_dict(dict_t *dict, glusterd_volinfo_t *volinfo, int op, int index) { - glusterd_conf_t *priv = NULL; - runner_t runner = {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); + int ret = -1; + char key[32] = { + 0, + }; + int keylen; + char *uuid_str = NULL; + int status = 0; + xlator_t *this = NULL; - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Cannot destroy maintenance " - "client"); - goto out; - } + GF_ASSERT(dict); + GF_ASSERT(volinfo); - runinit (&runner); - runner_add_args (&runner, "/bin/umount", "-f", NULL); - runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, - priv->workdir, volinfo->volname); + this = THIS; + GF_ASSERT(this); - ret = runner_run (&runner); - 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; - } + 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_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_ADD_REMOVE_BRICK_FAIL, + "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; - ret = 0; + default: + ret = -1; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_NO_TASK_ID, + "%s operation doesn't have a" + " task_id", + gd_op_list[op]); + goto out; + } + + keylen = snprintf(key, sizeof(key), "task%d.type", index); + ret = dict_set_strn(dict, key, keylen, (char *)gd_op_list[op]); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Error setting task type in dict"); + goto out; + } + + keylen = snprintf(key, sizeof(key), "task%d.id", index); + + if (!uuid_str) + goto out; + ret = dict_set_dynstrn(dict, key, keylen, uuid_str); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Error setting task id in dict"); + goto out; + } + uuid_str = NULL; + + keylen = snprintf(key, sizeof(key), "task%d.status", index); + ret = dict_set_int32n(dict, key, keylen, status); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Error setting task status in dict"); + goto out; + } out: - return ret; + if (uuid_str) + GF_FREE(uuid_str); + return ret; } static int -rb_spawn_maintenance_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) +glusterd_aggregate_task_status(dict_t *rsp_dict, glusterd_volinfo_t *volinfo) { - int ret = -1; + int ret = -1; + int tasks = 0; + xlator_t *this = NULL; - ret = rb_generate_client_volfile (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to generate client " - "volfile"); - goto out; - } + this = THIS; + GF_ASSERT(this); - ret = rb_mountpoint_mkdir (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to mkdir " - "mountpoint"); - goto out; - } + if (!gf_uuid_is_null(volinfo->rebal.rebalance_id)) { + ret = _add_task_to_dict(rsp_dict, volinfo, volinfo->rebal.op, tasks); - ret = rb_spawn_glusterfs_client (volinfo, src_brickinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); - goto out; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to add task details to dict"); + goto out; } - - ret = 0; + tasks++; + } + ret = dict_set_int32n(rsp_dict, "tasks", SLEN("tasks"), tasks); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Error setting tasks count in dict"); + goto out; + } 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; + 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; - } +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; +#ifdef BUILD_GNFS + gf_boolean_t nfs_disabled = _gf_false; +#endif + gf_boolean_t shd_enabled = _gf_false; + gf_boolean_t origin_glusterd = _gf_false; + int snapd_enabled, bitrot_enabled, volume_quota_enabled; - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); + this = THIS; + GF_ASSERT(this); + priv = this->private; - snprintf (start_value, 8192, "%s:%s:%d", - dst_brickinfo->hostname, - dst_brickinfo->path, - dst_brickinfo->port); + GF_ASSERT(priv); + GF_ASSERT(dict); - 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"); - } + origin_glusterd = is_origin_glusterd(dict); - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } + ret = dict_get_uint32(dict, "cmd", &cmd); + if (ret) + goto out; - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); + if (origin_glusterd) { ret = 0; + if ((cmd & GF_CLI_STATUS_ALL)) { + ret = glusterd_get_all_volnames(rsp_dict); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOLNAMES_GET_FAIL, + "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_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) + goto out; + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + "Volume with name: %s " + "does not exist", + volname); + goto out; + } + vol_opts = volinfo->dict; + + if ((cmd & GF_CLI_STATUS_QUOTAD) != 0) { + ret = glusterd_add_node_to_dict(priv->quotad_svc.name, rsp_dict, 0, + vol_opts); + if (ret) + goto out; + other_count++; + node_count++; +#ifdef BUILD_GNFS + } else if ((cmd & GF_CLI_STATUS_NFS) != 0) { + ret = glusterd_add_node_to_dict(priv->nfs_svc.name, rsp_dict, 0, + vol_opts); + if (ret) + goto out; + other_count++; + node_count++; +#endif + } else if ((cmd & GF_CLI_STATUS_BITD) != 0) { + ret = glusterd_add_node_to_dict(priv->bitd_svc.name, rsp_dict, 0, + vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + } else if ((cmd & GF_CLI_STATUS_SCRUB) != 0) { + ret = glusterd_add_node_to_dict(priv->scrub_svc.name, rsp_dict, 0, + vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + } else if ((cmd & GF_CLI_STATUS_SNAPD) != 0) { + ret = glusterd_add_snapd_to_dict(volinfo, rsp_dict, other_index); + if (ret) + goto out; + other_count++; + node_count++; + } else if ((cmd & GF_CLI_STATUS_SHD) != 0) { + ret = glusterd_add_shd_to_dict(volinfo, rsp_dict, other_index); + if (ret) + goto out; + other_count++; + node_count++; + } else if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_strn(dict, "brick", SLEN("brick"), &brick); + if (ret) + goto out; -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_INFO, - "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 = glusterd_volume_brickinfo_get_by_brick(brick, volinfo, &brickinfo, + _gf_false); + if (ret) + goto out; + + if (gf_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 { + snapd_enabled = glusterd_is_snapd_enabled(volinfo); + shd_enabled = gd_is_self_heal_enabled(volinfo, vol_opts); +#ifdef BUILD_GNFS + nfs_disabled = dict_get_str_boolean(vol_opts, NFS_DISABLE_MAP_KEY, + _gf_false); +#endif + volume_quota_enabled = glusterd_is_volume_quota_enabled(volinfo); + bitrot_enabled = glusterd_is_bitrot_enabled(volinfo); - 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"); + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + brick_index++; + if (gf_uuid_compare(brickinfo->uuid, MY_UUID)) + continue; - } + glusterd_add_brick_to_dict(volinfo, brickinfo, rsp_dict, + brick_index); - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; + if (cmd & GF_CLI_STATUS_DETAIL) { + glusterd_add_brick_detail_to_dict(volinfo, brickinfo, rsp_dict, + brick_index); + } + node_count++; } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; + if ((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE) { + other_index = brick_index + 1; + if (snapd_enabled) { + ret = glusterd_add_snapd_to_dict(volinfo, rsp_dict, + other_index); + if (ret) + goto out; + other_count++; + other_index++; + node_count++; + } + + if (glusterd_is_shd_compatible_volume(volinfo)) { + if (shd_enabled) { + ret = glusterd_add_shd_to_dict(volinfo, rsp_dict, + other_index); + if (ret) + goto out; + other_count++; + other_index++; + node_count++; + } + } +#ifdef BUILD_GNFS + if (!nfs_disabled) { + ret = glusterd_add_node_to_dict(priv->nfs_svc.name, rsp_dict, + other_index, vol_opts); + if (ret) + goto out; + other_index++; + other_count++; + node_count++; + } +#endif + if (volume_quota_enabled) { + ret = glusterd_add_node_to_dict(priv->quotad_svc.name, rsp_dict, + other_index, vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + other_index++; + } + + if (bitrot_enabled) { + ret = glusterd_add_node_to_dict(priv->bitd_svc.name, rsp_dict, + other_index, vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + other_index++; + /* For handling scrub status. Scrub daemon will be + * running automatically when bitrot is enable */ + ret = glusterd_add_node_to_dict(priv->scrub_svc.name, rsp_dict, + other_index, vol_opts); + if (ret) + goto out; + other_count++; + node_count++; + } + } + } + + ret = dict_set_int32n(rsp_dict, "type", SLEN("type"), volinfo->type); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Key=type", NULL); + goto out; + } + + ret = dict_set_int32n(rsp_dict, "brick-index-max", SLEN("brick-index-max"), + brick_index); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Key=brick-index-max", NULL); + goto out; + } + ret = dict_set_int32n(rsp_dict, "other-count", SLEN("other-count"), + other_count); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Key=other-count", NULL); + goto out; + } + ret = dict_set_int32n(rsp_dict, "count", SLEN("count"), node_count); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Key=count", NULL); + goto out; + } + + /* Active tasks */ + /* Tasks are added only for normal volume status request for either a + * single volume or all volumes + */ + if (!glusterd_status_has_tasks(cmd)) + goto out; + + ret = glusterd_aggregate_task_status(rsp_dict, volinfo); + if (ret) + goto out; + 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; + gf_msg_debug(this->name, 0, "Returning %d", ret); + + return ret; } static int -rb_kill_destination_brick (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *dst_brickinfo) +glusterd_op_ac_none(glusterd_op_sm_event_t *event, void *ctx) { - glusterd_conf_t *priv = NULL; - char pidfile[PATH_MAX] = {0,}; - - priv = THIS->private; + int ret = 0; - snprintf (pidfile, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_DSTBRICK_PIDFILE); + gf_msg_debug(THIS->name, 0, "Returning with %d", ret); - return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_true); + return ret; } static int -rb_do_operation_commit (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) +glusterd_op_sm_locking_failed(uuid_t *txn_id) { - int ret = -1; - int cmd_ret = -1; - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending commit xattr"); + int ret = -1; - 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"); + opinfo.op_ret = -1; + opinfo.op_errstr = gf_strdup("locking failed for one of the peer."); - cmd_ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_COMMIT_CMD, - "jargon"); - if (cmd_ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } + ret = glusterd_set_txn_opinfo(txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); + /* Inject a reject event such that unlocking gets triggered right away*/ + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_RCVD_RJT, txn_id, NULL); - 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 cmd_ret || ret; + return ret; } 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; - } +glusterd_op_ac_send_lock(glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + 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); + + RCU_READ_LOCK; + cds_list_for_each_entry_rcu(peerinfo, &priv->peers, uuid_list) + { + /* Only send requests to peers who were available before the + * transaction started + */ + if (peerinfo->generation > opinfo.txn_generation) + continue; + + if (!peerinfo->connected || !peerinfo->mgmt) + continue; + if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && + (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) + continue; + + /* Based on the op_version, acquire a cluster or mgmt_v3 lock */ + if (priv->op_version < GD_OP_VERSION_3_6_0) { + proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_LOCK]; + if (proc->fn) { + ret = proc->fn(NULL, this, peerinfo); + if (ret) { + RCU_READ_UNLOCK; + gf_msg(this->name, GF_LOG_WARNING, 0, + GD_MSG_LOCK_REQ_SEND_FAIL, + "Failed to send lock request " + "for operation 'Volume %s' to " + "peer %s", + gd_op_list[opinfo.op], peerinfo->hostname); + goto out; + } + /* Mark the peer as locked*/ + peerinfo->locked = _gf_true; + pending_count++; + } + } else { + dict = glusterd_op_get_ctx(); + dict_ref(dict); - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); + proc = &peerinfo->mgmt_v3->proctable[GLUSTERD_MGMT_V3_LOCK]; + if (proc->fn) { + ret = dict_set_static_ptr(dict, "peerinfo", peerinfo); + if (ret) { + RCU_READ_UNLOCK; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "failed to set peerinfo"); + dict_unref(dict); + goto out; + } - ret = 0; + ret = proc->fn(NULL, this, dict); + if (ret) { + RCU_READ_UNLOCK; + gf_msg(this->name, GF_LOG_WARNING, 0, + GD_MSG_MGMTV3_LOCK_REQ_SEND_FAIL, + "Failed to send mgmt_v3 lock " + "request for operation " + "'Volume %s' to peer %s", + gd_op_list[opinfo.op], peerinfo->hostname); + dict_unref(dict); + goto out; + } + /* Mark the peer as locked*/ + peerinfo->locked = _gf_true; + pending_count++; + } + } + } + RCU_READ_UNLOCK; + + opinfo.pending_count = pending_count; + + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); + + if (!opinfo.pending_count) + ret = glusterd_op_sm_inject_all_acc(&event->txn_id); 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_get_xattr_command (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo, - const char *xattr_key, - 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_lgetxattr (mount_point_path, xattr_key, value, 8192); - - if (ret < 0) { - gf_log ("", GF_LOG_DEBUG, - "getxattr failed"); - goto out; - } - - ret = 0; + if (ret) + ret = glusterd_op_sm_locking_failed(&event->txn_id); -out: - return ret; + gf_msg_debug(this->name, 0, "Returning with %d", ret); + return ret; } static int -rb_do_operation_status (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - char status[8192] = {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); +glusterd_op_ac_send_unlock(glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + 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); + + RCU_READ_LOCK; + cds_list_for_each_entry_rcu(peerinfo, &priv->peers, uuid_list) + { + /* Only send requests to peers who were available before the + * transaction started + */ + if (peerinfo->generation > opinfo.txn_generation) + continue; + + if (!peerinfo->connected || !peerinfo->mgmt || !peerinfo->locked) + continue; + if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && + (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) + continue; + /* Based on the op_version, + * release the cluster or mgmt_v3 lock */ + if (priv->op_version < GD_OP_VERSION_3_6_0) { + proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_UNLOCK]; + if (proc->fn) { + ret = proc->fn(NULL, this, peerinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); + opinfo.op_errstr = gf_strdup( + "Unlocking failed for one of " + "the peer."); + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_CLUSTER_UNLOCK_FAILED, + "Unlocking failed for operation" + " volume %s on peer %s", + gd_op_list[opinfo.op], peerinfo->hostname); + continue; + } + pending_count++; + peerinfo->locked = _gf_false; + } + } else { + dict = glusterd_op_get_ctx(); + dict_ref(dict); - ret = rb_get_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_STATUS_CMD, - status); + proc = &peerinfo->mgmt_v3->proctable[GLUSTERD_MGMT_V3_UNLOCK]; + if (proc->fn) { + ret = dict_set_static_ptr(dict, "peerinfo", peerinfo); 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; + opinfo.op_errstr = gf_strdup( + "Unlocking failed for one of the " + "peer."); + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_CLUSTER_UNLOCK_FAILED, + "Unlocking failed for operation" + " volume %s on peer %s", + gd_op_list[opinfo.op], peerinfo->hostname); + dict_unref(dict); + continue; + } + + ret = proc->fn(NULL, this, dict); + if (ret) { + opinfo.op_errstr = gf_strdup( + "Unlocking failed for one of the " + "peer."); + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_CLUSTER_UNLOCK_FAILED, + "Unlocking failed for operation" + " volume %s on peer %s", + gd_op_list[opinfo.op], peerinfo->hostname); + dict_unref(dict); + continue; } + pending_count++; + peerinfo->locked = _gf_false; + } + } + } + RCU_READ_UNLOCK; - ret = dict_set_dynstr (ctx, "status-reply", - status_reply); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "failed to set pump status in ctx"); + opinfo.pending_count = pending_count; - } + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); - umount: - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - } + if (!opinfo.pending_count) + ret = glusterd_op_sm_inject_all_acc(&event->txn_id); - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); -out: - return ret; + gf_msg_debug(this->name, 0, "Returning with %d", ret); + 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) +glusterd_op_ac_ack_drain(glusterd_op_sm_event_t *event, void *ctx) { - 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_INFO, - "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; - } + int ret = 0; - 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; - } - } + if (opinfo.pending_count > 0) + opinfo.pending_count--; - 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; - } - } + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); - } + if (!opinfo.pending_count) + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_ALL_ACK, &event->txn_id, + NULL); -out: - return ret; + gf_msg_debug(THIS->name, 0, "Returning with %d", ret); + 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) +glusterd_op_ac_send_unlock_drain(glusterd_op_sm_event_t *event, void *ctx) { - 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_INFO, - "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 glusterd_op_ac_ack_drain(event, ctx); } - - static int -glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) -{ - 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; - - this = THIS; - GF_ASSERT (this); - - 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); +glusterd_op_ac_lock(glusterd_op_sm_event_t *event, void *ctx) +{ + int32_t ret = 0; + char *volname = NULL; + char *globalname = NULL; + glusterd_op_lock_ctx_t *lock_ctx = NULL; + xlator_t *this = NULL; + uint32_t op_errno = 0; + glusterd_conf_t *conf = NULL; + uint32_t timeout = 0; + + GF_ASSERT(event); + GF_ASSERT(ctx); + + this = THIS; + GF_ASSERT(this); + conf = this->private; + GF_ASSERT(conf); + + lock_ctx = (glusterd_op_lock_ctx_t *)ctx; + + /* 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 { + /* Cli will add timeout key to dict if the default timeout is + * other than 2 minutes. Here we use this value to check whether + * mgmt_v3_lock_timeout should be set to default value or we + * need to change the value according to timeout value + * i.e, timeout + 120 seconds. */ + ret = dict_get_uint32(lock_ctx->dict, "timeout", &timeout); + if (!ret) + conf->mgmt_v3_lock_timeout = timeout + 120; + + ret = dict_get_strn(lock_ctx->dict, "volname", SLEN("volname"), + &volname); 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_INFO, - "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_INFO, - "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: - { - ctx = glusterd_op_get_ctx (GD_OP_REPLACE_BRICK); - if (ctx) { - ret = rb_do_operation_commit (volinfo, src_brickinfo, dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Commit operation failed"); - goto out; - } - } - - 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_INFO, - "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"); - 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); + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to acquire volname"); + else { + ret = glusterd_mgmt_v3_lock(volname, lock_ctx->uuid, &op_errno, + "vol"); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_LOCK_GET_FAIL, + "Unable to acquire lock for %s", volname); + goto out; + } + ret = dict_get_strn(lock_ctx->dict, "globalname", SLEN("globalname"), + &globalname); + if (!ret) { + ret = glusterd_mgmt_v3_lock(globalname, lock_ctx->uuid, &op_errno, + "global"); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_LOCK_GET_FAIL, + "Unable to acquire lock for %s", globalname); } - break; - - case GF_REPLACE_OP_ABORT: - { - - 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 (THIS->name, GF_LOG_ERROR, - "Abort operation failed"); - goto out; - } - } - - ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); - if (ret) { - gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to disable pump"); - } + out: + glusterd_op_mgmt_v3_lock_send_resp(lock_ctx->req, &event->txn_id, ret); + dict_unref(lock_ctx->dict); + } - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log (THIS->name, GF_LOG_INFO, - "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; - } - } - 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; - } + gf_msg_debug(THIS->name, 0, "Lock Returned %d", ret); + return ret; +} +static int +glusterd_op_ac_unlock(glusterd_op_sm_event_t *event, void *ctx) +{ + int32_t ret = 0; + char *volname = NULL; + char *globalname = 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; + + /* 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_strn(lock_ctx->dict, "volname", SLEN("volname"), + &volname); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to acquire volname"); + else { + ret = glusterd_mgmt_v3_unlock(volname, lock_ctx->uuid, "vol"); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_UNLOCK_FAIL, + "Unable to release lock for %s", volname); + goto out; } - break; - default: - ret = -1; - goto out; + ret = dict_get_strn(lock_ctx->dict, "globalname", SLEN("globalname"), + &globalname); + if (!ret) { + ret = glusterd_mgmt_v3_unlock(globalname, lock_ctx->uuid, "global"); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_UNLOCK_FAIL, + "Unable to release lock for %s", globalname); } + out: + glusterd_op_mgmt_v3_unlock_send_resp(lock_ctx->req, &event->txn_id, + ret); - if (ret) - goto out; - -out: - return ret; -} - -void -_delete_reconfig_opt (dict_t *this, char *key, data_t *value, void *data) -{ - int exists = 0; - int32_t is_force = 0; - - GF_ASSERT (data); - is_force = *((int32_t*)data); - exists = glusterd_check_option_exists(key, NULL); - - if (exists != 1) - goto out; + dict_unref(lock_ctx->dict); + } - if ((!is_force) && - (_gf_true == glusterd_check_voloption_flags (key, - OPT_FLAG_FORCE))) - goto out; + gf_msg_debug(this->name, 0, "Unlock Returned %d", ret); - gf_log ("", GF_LOG_DEBUG, "deleting dict with key=%s,value=%s", - key, value->data); - dict_del (this, key); -out: - return; + if (priv->pending_quorum_action) + glusterd_do_quorum_action(); + return ret; } -int -glusterd_options_reset (glusterd_volinfo_t *volinfo, int32_t is_force) +static int +glusterd_op_ac_local_unlock(glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - - gf_log ("", GF_LOG_DEBUG, "Received volume set reset command"); + int ret = 0; + uuid_t *originator = NULL; - GF_ASSERT (volinfo->dict); + GF_ASSERT(event); + GF_ASSERT(ctx); - dict_foreach (volinfo->dict, _delete_reconfig_opt, &is_force); + originator = (uuid_t *)ctx; - ret = glusterd_create_volfiles_and_notify_services (volinfo); + ret = glusterd_unlock(*originator); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" - " 'volume set'"); - ret = -1; - goto out; - } + gf_msg_debug(THIS->name, 0, "Unlock Returned %d", ret); - 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 (); - if (ret) - goto out; - - ret = 0; - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + return ret; } - static int -glusterd_op_reset_volume (dict_t *dict) +glusterd_op_ac_rcvd_lock_acc(glusterd_op_sm_event_t *event, void *ctx) { - glusterd_volinfo_t *volinfo = NULL; - int ret = -1; - char *volname = NULL; - int32_t is_force = 0; + int ret = 0; - 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, "force", &is_force); - if (ret) - is_force = 0; - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } + GF_ASSERT(event); - ret = glusterd_options_reset (volinfo, is_force); + if (opinfo.pending_count > 0) + opinfo.pending_count--; -out: - gf_log ("", GF_LOG_DEBUG, "'volume reset' returning %d", ret); - return ret; + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); -} + if (opinfo.pending_count > 0) + goto out; -int -stop_gsync (char *master, char *slave, char **msg) -{ - int32_t ret = 0; - int pfd = -1; - pid_t pid = 0; - char pidfile[PATH_MAX] = {0,}; - char buf [1024] = {0,}; - int i = 0; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - pfd = gsyncd_getpidfile (master, slave, pidfile); - if (pfd == -2) { - gf_log ("", GF_LOG_ERROR, GEOREP" stop validation " - " failed for %s & %s", master, slave); - ret = -1; - goto out; - } - if (gsync_status_byfd (pfd) == -1) { - gf_log ("", GF_LOG_ERROR, "gsyncd b/w %s & %s is not" - " running", master, slave); - if (msg) - *msg = gf_strdup ("Warning: "GEOREP" session was in " - "corrupt state"); - /* monitor gsyncd already dead */ - goto out; - } + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_ALL_ACC, &event->txn_id, + NULL); - ret = read (pfd, buf, 1024); - if (ret > 0) { - pid = strtol (buf, NULL, 10); - ret = kill (-pid, SIGTERM); - if (ret) { - gf_log ("", GF_LOG_WARNING, - "failed to kill gsyncd"); - goto out; - } - for (i = 0; i < 20; i++) { - if (gsync_status_byfd (pfd) == -1) { - /* monitor gsyncd is dead but worker may - * still be alive, give some more time - * before SIGKILL (hack) - */ - usleep (50000); - break; - } - usleep (50000); - } - kill (-pid, SIGKILL); - unlink (pidfile); - } - ret = 0; + gf_msg_debug(THIS->name, 0, "Returning %d", ret); out: - close (pfd); - return ret; + return ret; } int -glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, - dict_t *resp_dict); - -int -glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave, - dict_t *dict, dict_t *resp_dict, char **op_errstr) -{ - int32_t ret = -1; - char *op_name = NULL; - char *op_value = NULL; - runner_t runner = {0,}; - glusterd_conf_t *priv = NULL; - char *subop = NULL; - char *master = NULL; - - GF_ASSERT (slave); - GF_ASSERT (op_errstr); - GF_ASSERT (dict); - GF_ASSERT (resp_dict); - - ret = dict_get_str (dict, "subop", &subop); - if (ret != 0) - goto out; - - if (strcmp (subop, "get") == 0 || strcmp (subop, "get-all") == 0) { - /* deferred to cli */ - gf_log ("", GF_LOG_DEBUG, "Returning 0"); - return 0; - } - - ret = dict_get_str (dict, "op_name", &op_name); - if (ret != 0) - goto out; - - if (strcmp (subop, "set") == 0) { - ret = dict_get_str (dict, "op_value", &op_value); - if (ret != 0) - goto out; - } - - if (THIS) - priv = THIS->private; - if (priv == NULL) { - gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); - *op_errstr = gf_strdup ("glusterd defunct"); - goto out; - } - - master = ""; - runinit (&runner); - runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); - runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); - if (volinfo) { - master = volinfo->volname; - runner_argprintf (&runner, ":%s", master); - } - runner_add_arg (&runner, slave); - runner_argprintf (&runner, "--config-%s", subop); - runner_add_arg (&runner, op_name); - if (op_value) - runner_add_arg (&runner, op_value); - ret = runner_run (&runner); - if (ret) { - gf_log ("", GF_LOG_WARNING, "gsyncd failed to " - "%s %s option for %s %s peers", - subop, op_name, master, slave); - - gf_asprintf (op_errstr, GEOREP" config-%s failed for %s %s", - subop, master, slave); - - goto out; - } - ret = 0; - gf_asprintf (op_errstr, "config-%s successful", subop); - +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) { + gf_smsg(this->name, GF_LOG_ERROR, errno, GD_MSG_INVALID_ARGUMENT, NULL); + 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_dynstrn(dict, "vol-id", SLEN("vol-id"), volid); + if (ret) { + snprintf(msg, sizeof(msg), + "Failed to set volume id of volume" + " %s", + volname); + GF_FREE(volid); + goto out; + } out: - if (!ret && volinfo) { - ret = glusterd_check_restart_gsync_session (volinfo, slave, - resp_dict); - if (ret) - *op_errstr = gf_strdup ("internal error"); - } - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + if (msg[0] != '\0') { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_ID_SET_FAIL, "%s", msg); + *op_errstr = gf_strdup(msg); + } + return ret; } int -glusterd_gsync_read_frm_status (char *path, char *data) -{ - int ret = 0; - FILE *status_file = NULL; - - GF_ASSERT (path); - GF_ASSERT (data); - status_file = fopen (path, "r"); - if (status_file == NULL) { - gf_log ("", GF_LOG_WARNING, "Unable to read gsyncd status" - " file"); - return -1; - } - ret = fread (data, PATH_MAX, 1, status_file); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "Status file of gsyncd is corrupt"); - return -1; - } - - data[strlen(data)-1] = '\0'; - - return 0; +gd_set_commit_hash(dict_t *dict) +{ + struct timeval tv; + uint32_t hash; + + /* + * We need a commit hash that won't conflict with others we might have + * set, or zero which is the implicit value if we never have. Using + * seconds<<3 like this ensures that we'll only get a collision if two + * consecutive rebalances are separated by exactly 2^29 seconds - about + * 17 years - and even then there's only a 1/8 chance of a collision in + * the low order bits. It's far more likely that this code will have + * changed completely by then. If not, call me in 2031. + * + * P.S. Time zone changes? Yeah, right. + */ + gettimeofday(&tv, NULL); + hash = tv.tv_sec << 3; + + /* + * Make sure at least one of those low-order bits is set. The extra + * shifting is because not all machines have sub-millisecond time + * resolution. + */ + hash |= 1 << ((tv.tv_usec >> 10) % 3); + + return dict_set_uint32(dict, "commit-hash", hash); } int -glusterd_read_status_file (char *master, char *slave, - dict_t *dict) -{ - glusterd_conf_t *priv = NULL; - int ret = 0; - char statusfile[PATH_MAX] = {0, }; - char buff[PATH_MAX] = {0, }; - char mst[PATH_MAX] = {0, }; - char slv[PATH_MAX] = {0, }; - char sts[PATH_MAX] = {0, }; - int gsync_count = 0; - int status = 0; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - ret = glusterd_gsync_get_param_file (statusfile, "state", master, - slave, priv->workdir); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Unable to get the name of status" - "file for %s(master), %s(slave)", master, slave); - goto out; - - } +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; + xlator_t *this = NULL; + gf_boolean_t do_common = _gf_false; + + GF_ASSERT(req); + + this = THIS; + GF_ASSERT(this); + + req_dict = dict_new(); + if (!req_dict) + goto out; + + if (!op_ctx) { + op = glusterd_op_get_op(); + ctx = (void *)glusterd_op_get_ctx(); + if (!ctx) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_NO_OPTIONS_GIVEN, + "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_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Failed to get volume" + " operation"); + goto out; + } + ctx = op_ctx; +#undef GD_SYNC_OPCODE_KEY + } + + dict = ctx; + switch (op) { + case GD_OP_CREATE_VOLUME: { + ++glusterfs_port; + ret = dict_set_int32n(dict, "port", SLEN("port"), glusterfs_port); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set port in " + "dictionary"); + goto out; + } + dict_copy(dict, req_dict); + } break; + + case GD_OP_GSYNC_CREATE: + case GD_OP_GSYNC_SET: { + ret = glusterd_op_gsync_args_get(dict, op_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_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_DICT_GET_FAILED, + "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_unref(req_dict); + req_dict = dict_ref(dict); + } break; - ret = gsync_status (master, slave, &status); - if (ret == 0 && status == -1) { - strncpy (buff, "corrupt", sizeof (buff)); - goto done; - } else if (ret == -1) + case GD_OP_REMOVE_BRICK: { + dict_t *dict = ctx; + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_DICT_GET_FAILED, + "volname is not present in " + "operation ctx"); goto out; + } - ret = glusterd_gsync_read_frm_status (statusfile, buff); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Unable to read the status" - "file for %s(master), %s(slave)", master, slave); + ret = glusterd_dict_set_volid(dict, volname, op_errstr); + if (ret) goto out; - } - - done: - ret = dict_get_int32 (dict, "gsync-count", &gsync_count); - - if (ret) - gsync_count = 1; - else - gsync_count++; - - snprintf (mst, sizeof (mst), "master%d", gsync_count); - ret = dict_set_dynstr (dict, mst, gf_strdup (master)); - if (ret) + if (gd_set_commit_hash(dict) != 0) { goto out; + } - snprintf (slv, sizeof (slv), "slave%d", gsync_count); - ret = dict_set_dynstr (dict, slv, gf_strdup (slave)); - if (ret) - goto out; + dict_unref(req_dict); + req_dict = dict_ref(dict); + } break; - snprintf (sts, sizeof (slv), "status%d", gsync_count); - ret = dict_set_dynstr (dict, sts, gf_strdup (buff)); - if (ret) + case GD_OP_STATUS_VOLUME: { + ret = dict_get_uint32(dict, "cmd", &status_cmd); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Status command not present " + "in op ctx"); goto out; - ret = dict_set_int32 (dict, "gsync-count", gsync_count); - if (ret) - goto out; - - ret = 0; - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); - return ret; -} - -int -glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, - dict_t *resp_dict) -{ - - int ret = 0; - uuid_t uuid = {0, }; - glusterd_conf_t *priv = NULL; - char *status_msg = NULL; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; + } + if (GF_CLI_STATUS_ALL & status_cmd) { + dict_copy(dict, req_dict); + break; + } + do_common = _gf_true; + } break; - if (glusterd_gsync_get_uuid (slave, volinfo, uuid)) - /* session does not exist, nothing to do */ - goto out; - if (uuid_compare (priv->uuid, uuid) == 0) { - ret = stop_gsync (volinfo->volname, slave, &status_msg); - if (ret == 0 && status_msg) - ret = dict_set_str (resp_dict, "gsync-status", - status_msg); - if (ret == 0) - ret = glusterd_start_gsync (volinfo, slave, - uuid_utoa(priv->uuid), NULL); - } - - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} + 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_RESET_VOLUME: + case GD_OP_LOG_ROTATE: + case GD_OP_QUOTA: + case GD_OP_PROFILE_VOLUME: + case GD_OP_HEAL_VOLUME: + case GD_OP_STATEDUMP_VOLUME: + case GD_OP_CLEARLOCKS_VOLUME: + case GD_OP_DEFRAG_BRICK_VOLUME: + case GD_OP_BARRIER: + case GD_OP_BITROT: + case GD_OP_SCRUB_STATUS: + case GD_OP_SCRUB_ONDEMAND: + case GD_OP_RESET_BRICK: { + do_common = _gf_true; + } break; + + case GD_OP_REBALANCE: { + if (gd_set_commit_hash(dict) != 0) { + goto out; + } + do_common = _gf_true; + } break; + + case GD_OP_SYNC_VOLUME: + case GD_OP_COPY_FILE: + case GD_OP_SYS_EXEC: + case GD_OP_GANESHA: { + dict_copy(dict, req_dict); + } break; -int32_t -glusterd_marker_create_volfile (glusterd_volinfo_t *volinfo) -{ - int32_t ret = 0; + default: + break; + } - ret = glusterd_create_volfiles_and_notify_services (volinfo); + /* + * This has been moved out of the switch so that multiple ops with + * other special needs can all "fall through" to it. + */ + if (do_common) { + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile" - " for setting of marker while '"GEOREP" start'"); - ret = -1; - goto out; + gf_msg(this->name, GF_LOG_CRITICAL, -ret, GD_MSG_DICT_GET_FAILED, + "volname is not present in " + "operation ctx"); + 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 (glusterd_volinfo_t *volinfo) -{ - int ret = -1; - int marker_set = _gf_false; - char *gsync_status = NULL; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - marker_set = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME); - if (marker_set == -1) { - gf_log ("", GF_LOG_ERROR, "failed to get the marker status"); - ret = -1; + if (strcasecmp(volname, "all")) { + ret = glusterd_dict_set_volid(dict, volname, op_errstr); + if (ret) goto out; } + dict_copy(dict, req_dict); + } - if (marker_set == _gf_false) { - gsync_status = gf_strdup ("on"); - if (gsync_status == NULL) { - ret = -1; - goto out; - } - - ret = glusterd_gsync_volinfo_dict_set (volinfo, - VKEY_MARKER_XTIME, gsync_status); - if (ret < 0) - goto out; - - ret = glusterd_marker_create_volfile (volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Setting dict failed"); - goto out; - } - } - ret = 0; + *req = req_dict; + ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - - - - -int -glusterd_get_gsync_status_mst_slv( glusterd_volinfo_t *volinfo, - char *slave, dict_t *rsp_dict) -{ - uuid_t uuid = {0, }; - glusterd_conf_t *priv = NULL; - int ret = 0; - - GF_ASSERT (volinfo); - GF_ASSERT (slave); - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - - priv = THIS->private; - - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if ((ret == 0) && (uuid_compare (priv->uuid, uuid) != 0)) - goto out; - - if (ret) { - ret = 0; - gf_log ("", GF_LOG_INFO, "geo-replication status %s %s :" - "session is not active", volinfo->volname, slave); - goto out; - } - - ret = glusterd_read_status_file (volinfo->volname, slave, rsp_dict); - out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); - return ret; + return ret; } static int -glusterd_get_gsync_status_mst (glusterd_volinfo_t *volinfo, dict_t *rsp_dict) -{ - glusterd_gsync_status_temp_t param = {0, }; - - GF_ASSERT (volinfo); - - param.rsp_dict = rsp_dict; - param.volinfo = volinfo; - dict_foreach (volinfo->gsync_slaves, _get_status_mst_slv, ¶m); - - return 0; -} - -static int -glusterd_get_gsync_status_all ( dict_t *rsp_dict) -{ - - int32_t ret = 0; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - - GF_ASSERT (THIS); - priv = THIS->private; - - GF_ASSERT (priv); +glusterd_op_ac_send_stage_op(glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + int ret1 = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + dict_t *dict = NULL; + dict_t *rsp_dict = NULL; + char *op_errstr = NULL; + glusterd_op_t op = GD_OP_NONE; + uint32_t pending_count = 0; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + op = glusterd_op_get_op(); + + rsp_dict = dict_new(); + if (!rsp_dict) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_DICT_CREATE_FAIL, + "Failed to create rsp_dict"); + ret = -1; + goto out; + } + + ret = glusterd_op_build_payload(&dict, &op_errstr, NULL); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_OP_PAYLOAD_BUILD_FAIL, + 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_validate_quorum(this, op, dict, &op_errstr); + if (ret) { + gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_SERVER_QUORUM_NOT_MET, + "Server quorum not met. Rejecting operation."); + opinfo.op_errstr = op_errstr; + goto out; + } + + ret = glusterd_op_stage_validate(op, dict, &op_errstr, rsp_dict); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VALIDATE_FAILED, + 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; + } + + RCU_READ_LOCK; + cds_list_for_each_entry_rcu(peerinfo, &priv->peers, uuid_list) + { + /* Only send requests to peers who were available before the + * transaction started + */ + if (peerinfo->generation > opinfo.txn_generation) + continue; - list_for_each_entry (volinfo, &priv->volumes, vol_list) { - ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); - if (ret) - goto out; - } + 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_STAGE_OP]; + GF_ASSERT(proc); + if (proc->fn) { + ret = dict_set_static_ptr(dict, "peerinfo", peerinfo); + if (ret) { + RCU_READ_UNLOCK; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "failed to " + "set peerinfo"); + goto out; + } + + ret = proc->fn(NULL, this, dict); + if (ret) { + gf_msg(this->name, GF_LOG_WARNING, 0, + GD_MSG_STAGE_REQ_SEND_FAIL, + "Failed to " + "send stage request for operation " + "'Volume %s' to peer %s", + gd_op_list[op], peerinfo->hostname); + continue; + } + pending_count++; + } + } + RCU_READ_UNLOCK; + + opinfo.pending_count = pending_count; out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); - return ret; - -} - -static int -glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ - char *slave = NULL; - char *volname = NULL; - char errmsg[PATH_MAX] = {0, }; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - int ret = 0; - - - ret = dict_get_str (dict, "master", &volname); - if (ret < 0){ - ret = glusterd_get_gsync_status_all (rsp_dict); - goto out; - } + if (ret) + opinfo.op_ret = ret; - exists = glusterd_check_volume_exists (volname); - ret = glusterd_volinfo_find (volname, &volinfo); - if ((ret) || (!exists)) { - gf_log ("", GF_LOG_WARNING, "volume name does not exist"); - snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" - " exist", volname); - *op_errstr = gf_strdup (errmsg); - ret = -1; - goto out; - } + ret1 = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret1) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); + if (rsp_dict) + dict_unref(rsp_dict); - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) { - ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); - goto out; - } + if (dict) + dict_unref(dict); + if (ret) { + glusterd_op_sm_inject_event(GD_OP_EVENT_RCVD_RJT, &event->txn_id, NULL); + opinfo.op_ret = ret; + } - ret = glusterd_get_gsync_status_mst_slv (volinfo, slave, rsp_dict); + gf_msg_debug(this->name, 0, + "Sent stage op request for " + "'Volume %s' to %d peers", + gd_op_list[op], opinfo.pending_count); - out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + if (!opinfo.pending_count) + ret = glusterd_op_sm_inject_all_acc(&event->txn_id); + gf_msg_debug(this->name, 0, "Returning with %d", ret); + return ret; } - -int -glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +/* 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) { - int32_t ret = -1; - int32_t type = -1; - dict_t *ctx = NULL; - dict_t *resp_dict = NULL; - char *host_uuid = NULL; - char *slave = NULL; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_conf_t *priv = NULL; - char *status_msg = NULL; - uuid_t uuid = {0, }; - - GF_ASSERT (THIS); - GF_ASSERT (THIS->private); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - - priv = THIS->private; - - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) - goto out; + int ret = -1; + int i = 0; + char key[128]; + int keylen; + char *uuid_str = NULL; + uuid_t uuid = { + 0, + }; + char *hostname = NULL; + xlator_t *this = NULL; - ret = dict_get_str (dict, "host-uuid", &host_uuid); - if (ret < 0) - goto out; + this = THIS; + GF_ASSERT(this); - ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); - resp_dict = ctx ? ctx : rsp_dict; - GF_ASSERT (resp_dict); + GF_ASSERT(dict); + GF_ASSERT(key_fmt); - if (type == GF_GSYNC_OPTION_TYPE_STATUS) { - ret = glusterd_get_gsync_status (dict, op_errstr, resp_dict); - goto out; + for (i = idx_min; i < idx_max; i++) { + keylen = snprintf(key, sizeof(key), key_fmt, i); + ret = dict_get_strn(dict, key, keylen, &uuid_str); + if (ret) { + ret = 0; + continue; } - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) - goto out; - - if (dict_get_str (dict, "master", &volname) == 0) { - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_WARNING, "Volinfo for %s (master) not found", - volname); - goto out; - } - } + gf_msg_debug(this->name, 0, "Got uuid %s", uuid_str); - if (type == GF_GSYNC_OPTION_TYPE_CONFIG) { - ret = glusterd_gsync_configure (volinfo, slave, dict, resp_dict, - op_errstr); - goto out; + ret = gf_uuid_parse(uuid_str, uuid); + /* if parsing fails don't error out + * let the original value be retained + */ + if (ret) { + ret = 0; + continue; } - if (!volinfo) { - ret = -1; + hostname = glusterd_uuid_to_hostname(uuid); + if (hostname) { + gf_msg_debug(this->name, 0, "%s -> %s", uuid_str, hostname); + ret = dict_set_dynstrn(dict, key, keylen, hostname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Error setting hostname %s to dict", hostname); + GF_FREE(hostname); goto out; + } } - - if (type == GF_GSYNC_OPTION_TYPE_START) { - - ret = glusterd_set_marker_gsync (volinfo); - if (ret != 0) { - gf_log ("", GF_LOG_WARNING, "marker start failed"); - *op_errstr = gf_strdup ("failed to initialize indexing"); - ret = -1; - goto out; - } - ret = glusterd_store_slave_in_info(volinfo, slave, - host_uuid, op_errstr); - if (ret) - goto out; - - ret = glusterd_start_gsync (volinfo, slave, host_uuid, - op_errstr); - } - - if (type == GF_GSYNC_OPTION_TYPE_STOP) { - - ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); - if (ret) { - gf_log ("", GF_LOG_WARNING, GEOREP" is not set up for" - "%s(master) and %s(slave)", volname, slave); - *op_errstr = strdup (GEOREP" is not set up"); - goto out; - } - - ret = glusterd_remove_slave_in_info(volinfo, slave, - host_uuid, op_errstr); - if (ret) - goto out; - - if (uuid_compare (priv->uuid, uuid) != 0) { - goto out; - } - - ret = stop_gsync (volname, slave, &status_msg); - if (ret == 0 && status_msg) - ret = dict_set_str (resp_dict, "gsync-status", - status_msg); - if (ret != 0) - *op_errstr = gf_strdup ("internal error"); - } + } out: - gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); - return ret; + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } -int32_t -glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo) +static int +reassign_defrag_status(dict_t *dict, char *key, int keylen, + gf_defrag_status_t *status) { - int32_t ret = 0; - int flag = _gf_false; + int ret = 0; - flag = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA); - if (flag == -1) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota status"); - ret = -1; - goto out; - } - - if (flag == _gf_false) { - gf_log ("", GF_LOG_ERROR, "first enable the quota translator"); - ret = -1; - goto out; - } - ret = 0; -out: + if (!*status) return ret; -} -/* At the end of the function, the variable found will be set - * to true if the path to be removed was present in the limit-list, - * else will be false. - */ -int32_t -_glusterd_quota_remove_limits (char **quota_limits, char *path, - gf_boolean_t *found) -{ - 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 (found != NULL) - *found = _gf_false; - - 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 (found != NULL) - *found = _gf_true; - } - - while (qlimits [i + size] != ',' && - qlimits [i + size] != '\0') - size++; - - if (!flag) { - memcpy ((void *) &limits [i], (void *) &qlimits [i], size + 1); - } 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); + switch (*status) { + case GF_DEFRAG_STATUS_STARTED: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_STARTED; + break; - 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; - } - - memcpy ((void *) qlimits, (void *) limits, len + 1); - - *quota_limits = qlimits; - - ret = 0; - } - -out: - if (limits) - GF_FREE (limits); - - return ret; -} - -int32_t -glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname) -{ - int32_t ret = 0; - pid_t pid; - char mountdir [] = "/tmp/mntXXXXXX"; - runner_t runner = {0,}; - int status = 0; - - if (mkdtemp (mountdir) == NULL) { - gf_log ("glusterd", GF_LOG_DEBUG, - "failed to create a temporary mount directory"); - ret = -1; - goto out; - } + case GF_DEFRAG_STATUS_STOPPED: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_STOPPED; + break; - runinit (&runner); - runner_add_args (&runner, GFS_PREFIX"/sbin/glusterfs", "-s", - "localhost", "--volfile-id", volname, "-l", - DEFAULT_LOG_FILE_DIRECTORY"/quota-crawl.log", - mountdir, NULL); + case GF_DEFRAG_STATUS_COMPLETE: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_COMPLETE; + break; - ret = runner_run_reuse (&runner); - if (ret == -1) { - runner_log (&runner, "glusterd", GF_LOG_DEBUG, "command failed"); - runner_end (&runner); - goto out; - } - runner_end (&runner); + case GF_DEFRAG_STATUS_FAILED: + *status = GF_DEFRAG_STATUS_LAYOUT_FIX_FAILED; + break; + default: + break; + } - if ((pid = fork ()) < 0) { - gf_log ("glusterd", GF_LOG_WARNING, "fork from parent failed"); - ret = -1; - goto out; - } else if (pid == 0) {//first child - /* fork one more to not hold back main process on - * blocking call below - */ - pid = fork (); - if (pid) - _exit (pid > 0 ? EXIT_SUCCESS : EXIT_FAILURE); - - ret = chdir (mountdir); - if (ret == -1) { - gf_log ("glusterd", GF_LOG_WARNING, "chdir %s failed, " - "reason: %s", mountdir, strerror (errno)); - exit (EXIT_FAILURE); - } - runinit (&runner); - runner_add_args (&runner, "/usr/bin/find", "find", ".", NULL); - if (runner_start (&runner) == -1) - _exit (EXIT_FAILURE); - -#ifndef GF_LINUX_HOST_OS - runner_end (&runner); /* blocks in waitpid */ - runcmd ("umount", mountdir, NULL); -#else - runcmd ("umount", "-l", mountdir, NULL); -#endif - rmdir (mountdir); - _exit (EXIT_SUCCESS); - } - ret = (waitpid (pid, &status, 0) == pid && - WIFEXITED (status) && WEXITSTATUS (status) == EXIT_SUCCESS) ? 0 : -1; + ret = dict_set_int32n(dict, key, keylen, *status); + if (ret) + gf_msg(THIS->name, GF_LOG_WARNING, 0, GD_MSG_DICT_SET_FAILED, + "failed to reset defrag %s in dict", key); -out: - return ret; + return ret; } -char * -glusterd_quota_get_limit_value (char *quota_limits, char *path) -{ - 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); +/* 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[64] = { + 0, + }; + int keylen; + char *volname = NULL; + int ret = -1; + int i = 1; + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(THIS->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + gf_msg(THIS->name, GF_LOG_WARNING, 0, GD_MSG_VOL_NOT_FOUND, + 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; + } - break; - } - i = ++j; //skip ',' + do { + keylen = snprintf(key, sizeof(key), "status-%d", i); + ret = dict_get_int32n(dict, key, keylen, (int32_t *)&status); + if (ret) { + gf_msg(THIS->name, GF_LOG_WARNING, 0, GD_MSG_DICT_GET_FAILED, + "failed to get defrag %s", key); + goto out; } - - return ret_str; -} - -char* -_glusterd_quota_get_limit_usages (glusterd_volinfo_t *volinfo, - char *path, char **op_errstr) -{ - int32_t ret = 0; - char *quota_limits = NULL; - char *ret_str = NULL; - - if (volinfo == NULL) - return NULL; - - ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, - "a_limits); + ret = reassign_defrag_status(dict, key, keylen, &status); if (ret) - return NULL; - if (quota_limits == NULL) { - ret_str = NULL; - *op_errstr = gf_strdup ("Limit not set on 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 0; - - 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; - - ret_str = _glusterd_quota_get_limit_usages (volinfo, path, op_errstr); - } - } + goto out; + i++; + } while (i <= count); - if (ret_str) { - ret = dict_set_dynstr (ctx, "limit_list", ret_str); - } + ret = 0; out: - return ret; -} + return ret; +} + +/* This function is used to verify if op_ctx indeed + requires modification. This is necessary since the + dictionary for certain commands might not have the + necessary keys required for the op_ctx modification + to succeed. + + Special Cases: + - volume status all + - volume status + + Regular Cases: + - volume status <volname> <brick> + - volume status <volname> mem + - volume status <volname> clients + - volume status <volname> inode + - volume status <volname> fd + - volume status <volname> callpool + - volume status <volname> tasks +*/ -int32_t -glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, - gf_boolean_t *crawl) +static gf_boolean_t +glusterd_is_volume_status_modify_op_ctx(uint32_t cmd) { - int32_t ret = -1; - 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); - - if (glusterd_is_volume_started (volinfo) == 0) { - *op_errstr = gf_strdup ("Volume is stopped, start volume " - "to enable quota."); - goto out; - } - - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == 0) { - *op_errstr = gf_strdup ("Quota is already enabled"); - goto out; - } - - quota_status = gf_strdup ("on"); - if (!quota_status) { - gf_log ("", GF_LOG_ERROR, "memory allocation failed"); - *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); - goto out; - } - - ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); - if (ret) { - gf_log ("", GF_LOG_ERROR, "dict set failed"); - *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); - goto out; - } - - *op_errstr = gf_strdup ("Enabling quota has been successful"); - - *crawl = _gf_true; - - ret = 0; -out: - return ret; + if ((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE) { + if (cmd & GF_CLI_STATUS_BRICK) + return _gf_false; + if (cmd & GF_CLI_STATUS_ALL) + return _gf_false; + return _gf_true; + } + return _gf_false; } -int32_t -glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr) +int +glusterd_op_modify_port_key(dict_t *op_ctx, int brick_index_max) { - int32_t ret = -1; - char *quota_status = NULL, *quota_limits = NULL; - - GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); - GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + char *port = NULL; + int i = 0; + int ret = -1; + char key[64] = {0}; + int keylen; + char old_key[64] = {0}; + int old_keylen; - ret = glusterd_check_if_quota_trans_enabled (volinfo); - if (ret == -1) { - *op_errstr = gf_strdup ("Quota is already disabled"); - goto out; - } - - quota_status = gf_strdup ("off"); - if (!quota_status) { - gf_log ("", GF_LOG_ERROR, "memory allocation failed"); - *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); - goto out; - } - - ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); - if (ret) { - gf_log ("", GF_LOG_ERROR, "dict set failed"); - *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); - goto out; - } - - *op_errstr = gf_strdup ("Disabling quota has been successful"); - - ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, - "a_limits); - if (ret) { - gf_log ("", GF_LOG_WARNING, "failed to get the quota limits"); - } else { - GF_FREE (quota_limits); - } - - dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); - -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_volinfo_get (volinfo, VKEY_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; - } + for (i = 0; i <= brick_index_max; i++) { + keylen = snprintf(key, sizeof(key), "brick%d.rdma_port", i); + ret = dict_get_strn(op_ctx, key, keylen, &port); - 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"); + old_keylen = snprintf(old_key, sizeof(old_key), "brick%d.port", i); + ret = dict_get_strn(op_ctx, old_key, old_keylen, &port); + if (ret) 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"); + ret = dict_set_strn(op_ctx, key, keylen, port); + if (ret) goto out; - } - - if (quota_limits) { - ret = _glusterd_quota_remove_limits ("a_limits, path, NULL); - 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, VKEY_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"); + ret = dict_set_nstrn(op_ctx, old_key, old_keylen, "\0", SLEN("\0")); + if (ret) goto out; } - snprintf (msg, 1024, "limit set on %s", path); - *op_errstr = gf_strdup (msg); - - ret = 0; + } out: - return ret; + return ret; } -int32_t -glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) -{ - int32_t ret = -1; - char str [PATH_MAX + 1024] = {0,}; - char *quota_limits = NULL; - char *path = NULL; - gf_boolean_t flag = _gf_false; - - 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 ("Quota is disabled, please enable quota"); - goto out; - } - - ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, - "a_limits); - if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); - goto out; - } - - ret = dict_get_str (dict, "path", &path); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); - goto out; - } - - ret = _glusterd_quota_remove_limits ("a_limits, path, &flag); - if (ret == -1) { - if (flag == _gf_true) - snprintf (str, sizeof (str), "Removing limit on %s has " - "been unsuccessful", path); - else - snprintf (str, sizeof (str), "%s has no limit set", path); - *op_errstr = gf_strdup (str); - goto out; - } else { - if (flag == _gf_true) - snprintf (str, sizeof (str), "Removed quota limit on " - "%s", path); - else - snprintf (str, sizeof (str), "no limit set on %s", - path); - *op_errstr = gf_strdup (str); - } - - if (quota_limits) { - ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, - quota_limits); +/* 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; + glusterd_conf_t *conf = NULL; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + char *port = 0; + int i = 0; + char key[64] = { + 0, + }; + int keylen; + + this = THIS; + GF_ASSERT(this); + conf = this->private; + + if (ctx) + op_ctx = ctx; + else + op_ctx = glusterd_op_get_ctx(); + + if (!op_ctx) { + gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_OPCTX_NULL, + "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_msg_debug(this->name, 0, "Failed to get status cmd"); + goto out; + } + + if (!glusterd_is_volume_status_modify_op_ctx(cmd)) { + gf_msg_debug(this->name, 0, + "op_ctx modification not required for status " + "operation being performed"); + goto out; + } + + ret = dict_get_int32n(op_ctx, "brick-index-max", + SLEN("brick-index-max"), &brick_index_max); + if (ret) { + gf_msg_debug(this->name, 0, "Failed to get brick-index-max"); + goto out; + } + + ret = dict_get_int32n(op_ctx, "other-count", SLEN("other-count"), + &other_count); + if (ret) { + gf_msg_debug(this->name, 0, "Failed to get other-count"); + goto out; + } + + count = brick_index_max + other_count + 1; + + /* + * a glusterd lesser than version 3.7 will be sending the + * rdma port in older key. Changing that value from here + * to support backward compatibility + */ + ret = dict_get_strn(op_ctx, "volname", SLEN("volname"), &volname); + if (ret) + goto out; + + for (i = 0; i <= brick_index_max; i++) { + keylen = snprintf(key, sizeof(key), "brick%d.rdma_port", i); + ret = dict_get_strn(op_ctx, key, keylen, &port); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); + ret = dict_set_nstrn(op_ctx, key, keylen, "\0", SLEN("\0")); + if (ret) goto out; } - } else { - dict_del (volinfo->dict, VKEY_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; + } + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) + goto out; + if (conf->op_version < GD_OP_VERSION_3_7_0 && + volinfo->transport_type == GF_TRANSPORT_RDMA) { + ret = glusterd_op_modify_port_key(op_ctx, brick_index_max); + if (ret) + goto out; + } + /* add 'brick%d.peerid' into op_ctx with value of 'brick%d.path'. + nfs/sshd like services have this additional uuid */ + { + char *uuid_str = NULL; + char *uuid = NULL; + int i; + + for (i = brick_index_max + 1; i < count; i++) { + keylen = snprintf(key, sizeof(key), "brick%d.path", i); + ret = dict_get_strn(op_ctx, key, keylen, &uuid_str); + if (!ret) { + keylen = snprintf(key, sizeof(key), "brick%d.peerid", + i); + uuid = gf_strdup(uuid_str); + if (!uuid) { + gf_msg_debug(this->name, 0, + "unable to create dup of" + " uuid_str"); + continue; + } + ret = dict_set_dynstrn(op_ctx, key, keylen, uuid); + if (ret != 0) { + GF_FREE(uuid); + } + } + } + } - GF_ASSERT (dict); - GF_ASSERT (op_errstr); + ret = glusterd_op_volume_dict_uuid_to_hostname( + op_ctx, "brick%d.path", 0, count); + if (ret) + gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_CONVERSION_FAILED, + "Failed uuid to hostname conversion"); - priv = THIS->private; + break; - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); + case GD_OP_PROFILE_VOLUME: + ret = dict_get_str_boolean(op_ctx, "nfs", _gf_false); + if (!ret) goto out; - } - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + ret = dict_get_int32n(op_ctx, "count", SLEN("count"), &count); + if (ret) { + gf_msg_debug(this->name, 0, "Failed to get brick count"); 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; + ret = glusterd_op_volume_dict_uuid_to_hostname(op_ctx, "%d-brick", + 1, (count + 1)); + if (ret) + gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_CONVERSION_FAILED, + "Failed uuid to hostname conversion"); - goto create_vol; - } + break; - 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 is disabled"); - goto out; + /* For both rebalance and remove-brick status, the glusterd op is the + * same + */ + case GD_OP_DEFRAG_BRICK_VOLUME: + case GD_OP_SCRUB_STATUS: + case GD_OP_SCRUB_ONDEMAND: + ret = dict_get_int32n(op_ctx, "count", SLEN("count"), &count); + if (ret) { + gf_msg_debug(this->name, 0, "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 *uuid_str = NULL; + char *uuid = NULL; + int i; + + for (i = 1; i <= count; i++) { + keylen = snprintf(key, sizeof(key), "node-uuid-%d", i); + ret = dict_get_strn(op_ctx, key, keylen, &uuid_str); + if (!ret) { + keylen = snprintf(key, sizeof(key), "node-name-%d", i); + uuid = gf_strdup(uuid_str); + if (!uuid) { + gf_msg_debug(this->name, 0, + "unable to create dup of" + " uuid_str"); + continue; + } + ret = dict_set_dynstrn(op_ctx, key, keylen, uuid); + if (ret != 0) { + GF_FREE(uuid); + } + } } + } - ret = glusterd_quota_get_limit_usages (priv, volinfo, volname, - dict, op_errstr); - - 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; - } + ret = glusterd_op_volume_dict_uuid_to_hostname( + op_ctx, "node-name-%d", 1, (count + 1)); + if (ret) + gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_CONVERSION_FAILED, + "Failed uuid to hostname conversion"); - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; + /* Since Both rebalance and bitrot scrub status/ondemand + * are going to use same code path till here, we should + * break in case of scrub status. + */ + if (op == GD_OP_SCRUB_STATUS || op == GD_OP_SCRUB_ONDEMAND) { + break; + } - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); + ret = glusterd_op_check_peer_defrag_status(op_ctx, count); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_DEFRAG_STATUS_UPDATE_FAIL, + "Failed to reset defrag status for fix-layout"); + break; - ret = 0; + default: + ret = 0; + gf_msg_debug(this->name, 0, "op_ctx modification not required"); + break; + } out: - ctx = glusterd_op_get_ctx (GD_OP_QUOTA); - if (ctx && start_crawl == _gf_true) - glusterd_quota_initiate_fs_crawl (priv, volname); - - 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; - } - - return ret; + if (ret) + gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_OPCTX_UPDATE_FAIL, + "op_ctx modification failed"); + return; } 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; -} +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 = ""; + char *cmd_subdir = NULL; + int ret = -1; + int32_t len = 0; + + 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: + type_subdir = "pre"; + break; + case GD_COMMIT_HOOK_POST: + type_subdir = "post"; + break; + } + + cmd_subdir = glusterd_hooks_get_hooks_cmd_subdir(op); + if (strlen(cmd_subdir) == 0) + return -1; -int -glusterd_start_bricks (glusterd_volinfo_t *volinfo) -{ - glusterd_brickinfo_t *brickinfo = NULL; + GLUSTERD_GET_HOOKS_DIR(hookdir, GLUSTERD_HOOK_VER, priv); + len = snprintf(scriptdir, sizeof(scriptdir), "%s/%s/%s", hookdir, + cmd_subdir, type_subdir); + if ((len < 0) || (len >= sizeof(scriptdir))) { + return -1; + } - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (glusterd_brick_start (volinfo, brickinfo)) - return -1; - } + switch (type) { + case GD_COMMIT_HOOK_NONE: + case GD_COMMIT_HOOK_MAX: + /*Won't be called*/ + break; - return 0; -} + 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; + } -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; + return ret; } static int -glusterd_op_log_level (dict_t *dict) -{ - int32_t ret = -1; - glusterd_volinfo_t *volinfo = NULL; - char *volname = NULL; - char *xlator = NULL; - char *loglevel = NULL; - xlator_t *this = NULL; - glusterd_conf_t *priv = 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, "Unable to get volume name"); - goto out; - } - - ret = dict_get_str (dict, "xlator", &xlator); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); - goto out; - } - - ret = dict_get_str (dict, "loglevel", &loglevel); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get Loglevel to use"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Cannot find volume: %s", volname); - goto out; - } - - xlator = gf_strdup (xlator); - - ret = dict_set_dynstr (volinfo->dict, "xlator", xlator); - if (ret) - goto out; - - loglevel = gf_strdup (loglevel); +glusterd_op_ac_send_commit_op(glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + int ret1 = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + dict_t *dict = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + char *op_errstr = NULL; + glusterd_op_t op = GD_OP_NONE; + uint32_t pending_count = 0; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + op = glusterd_op_get_op(); + + ret = glusterd_op_build_payload(&dict, &op_errstr, NULL); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_OP_PAYLOAD_BUILD_FAIL, + 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(op, dict, &op_errstr, + NULL); // rsp_dict invalid for source + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_COMMIT_OP_FAIL, + 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; + } + + RCU_READ_LOCK; + cds_list_for_each_entry_rcu(peerinfo, &priv->peers, uuid_list) + { + /* Only send requests to peers who were available before the + * transaction started + */ + if (peerinfo->generation > opinfo.txn_generation) + continue; - ret = dict_set_dynstr (volinfo->dict, "loglevel", loglevel); - if (ret) - goto out; + if (!peerinfo->connected || !peerinfo->mgmt) + continue; + if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && + (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) + continue; - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to create volfile for command" - " 'log level'"); - ret = -1; - goto out; + proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_COMMIT_OP]; + GF_ASSERT(proc); + if (proc->fn) { + ret = dict_set_static_ptr(dict, "peerinfo", peerinfo); + if (ret) { + RCU_READ_UNLOCK; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "failed to set peerinfo"); + goto out; + } + ret = proc->fn(NULL, this, dict); + if (ret) { + gf_msg(this->name, GF_LOG_WARNING, 0, + GD_MSG_COMMIT_REQ_SEND_FAIL, + "Failed to " + "send commit request for operation " + "'Volume %s' to peer %s", + gd_op_list[op], peerinfo->hostname); + continue; + } + pending_count++; + } + } + RCU_READ_UNLOCK; + + opinfo.pending_count = pending_count; + gf_msg_debug(this->name, 0, + "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) + opinfo.op_ret = ret; + + ret1 = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret1) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); + + if (ret) { + glusterd_op_sm_inject_event(GD_OP_EVENT_RCVD_RJT, &event->txn_id, NULL); + opinfo.op_ret = ret; + } + + if (!opinfo.pending_count) { + if (op == GD_OP_REPLACE_BRICK) { + ret = glusterd_op_sm_inject_all_acc(&event->txn_id); + } else { + glusterd_op_modify_op_ctx(op, NULL); + ret = glusterd_op_sm_inject_all_acc(&event->txn_id); } + goto err; + } - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; - - ret = 0; +err: + gf_msg_debug(this->name, 0, "Returning with %d", ret); - out: - gf_log ("glusterd", GF_LOG_DEBUG, "(cli log level) Returning: %d", ret); - return ret; + return ret; } static int -glusterd_op_set_volume (dict_t *dict) +glusterd_op_ac_rcvd_stage_op_acc(glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - glusterd_volinfo_t *volinfo = NULL; - char *volname = NULL; - 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, }; - gf_boolean_t global_opt = _gf_false; - glusterd_volinfo_t *voliter = 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) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - 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 (!ret) { - ret = glusterd_check_option_exists (key, &key_fixed); - GF_ASSERT (ret); - if (ret == -1) { - key_fixed = NULL; - goto out; - } - ret = 0; - } - - ret = glusterd_check_globaloption (key); - if (ret) - 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; - } - - if (!global_opt) - value = gf_strdup (value); - - if (!value) { - gf_log ("", GF_LOG_ERROR, - "Unable to set the options in 'volume set'"); - ret = -1; - goto out; - } - - if (key_fixed) - key = key_fixed; - - if (global_opt) { - list_for_each_entry (voliter, &priv->volumes, vol_list) { - value = gf_strdup (value); - ret = dict_set_dynstr (voliter->dict, key, value); - if (ret) - goto out; - } - } - else { - ret = dict_set_dynstr (volinfo->dict, key, value); - if (ret) - goto out; - } - - if (key_fixed) { - GF_FREE (key_fixed); - - key_fixed = NULL; - } - } - - - if ( count == 1 ) { - gf_log ("", GF_LOG_ERROR, "No options received "); - ret = -1; - goto out; - } - - if (!global_opt) { - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", 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; - } - } + int ret = 0; - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; + GF_ASSERT(event); - if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_check_generate_start_nfs (); - if (ret) { - gf_log ("", GF_LOG_WARNING, - "Unable to restart NFS-Server"); - goto out; - } - } + if (opinfo.pending_count > 0) + opinfo.pending_count--; - } - else { - list_for_each_entry (voliter, &priv->volumes, vol_list) { - volinfo = voliter; - ret = glusterd_create_volfiles_and_notify_services (volinfo); - if (ret) { - gf_log ("", 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 (); - if (ret) { - gf_log ("", GF_LOG_WARNING, - "Unable to restart NFS-Server"); - goto out; - } - } - } - } + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); + if (opinfo.pending_count > 0) + goto out; - - ret = 0; + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_STAGE_ACC, &event->txn_id, + NULL); out: - if (key_fixed) - GF_FREE (key_fixed); - gf_log ("", GF_LOG_DEBUG, "returning %d", ret); - return ret; + gf_msg_debug(THIS->name, 0, "Returning %d", ret); + + return ret; } static int -glusterd_op_remove_brick (dict_t *dict) +glusterd_op_ac_stage_op_failed(glusterd_op_sm_event_t *event, void *ctx) { - 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,}; + int ret = 0; - ret = dict_get_str (dict, "volname", &volname); + GF_ASSERT(event); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); - goto out; - } + if (opinfo.pending_count > 0) + opinfo.pending_count--; - ret = glusterd_volinfo_find (volname, &volinfo); + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); - 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; + if (opinfo.pending_count > 0) + 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 (); + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_ALL_ACK, &event->txn_id, + NULL); out: - return ret; -} - + gf_msg_debug(THIS->name, 0, "Returning %d", 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; + return ret; } static int -glusterd_op_start_volume (dict_t *dict, char **op_errstr) +glusterd_op_ac_commit_op_failed(glusterd_op_sm_event_t *event, void *ctx) { - 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; + int ret = 0; - ret = glusterd_volinfo_find (volname, &volinfo); + GF_ASSERT(event); - if (ret) - goto out; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_brick_start (volinfo, brickinfo); - if (ret) - goto out; - } + if (opinfo.pending_count > 0) + opinfo.pending_count--; - glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) - goto out; + if (opinfo.pending_count > 0) + goto out; - ret = glusterd_check_generate_start_nfs (); + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_ALL_ACK, &event->txn_id, + NULL); out: - gf_log ("", GF_LOG_DEBUG, "returning %d ", ret); - return ret; + gf_msg_debug(THIS->name, 0, "Returning %d", ret); + + return ret; } static int -glusterd_op_log_filename (dict_t *dict) +glusterd_op_ac_brick_op_failed(glusterd_op_sm_event_t *event, void *ctx) { - 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; + int ret = 0; + glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; + gf_boolean_t free_errstr = _gf_false; + xlator_t *this = NULL; - 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; - } - } + this = THIS; + GF_ASSERT(this); + GF_ASSERT(event); + GF_ASSERT(ctx); + ev_ctx = ctx; + ret = glusterd_remove_pending_entry(&opinfo.pending_bricks, + ev_ctx->pending_node->node); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNKNOWN_RESPONSE, + "unknown response received "); 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); + free_errstr = _gf_true; + goto out; + } + if (opinfo.brick_pending_count > 0) + opinfo.brick_pending_count--; + if (opinfo.op_ret == 0) + opinfo.op_ret = ev_ctx->op_ret; + + if (opinfo.op_errstr == NULL) + opinfo.op_errstr = ev_ctx->op_errstr; + else + free_errstr = _gf_true; + + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); + + if (opinfo.brick_pending_count > 0) + goto out; + + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_ALL_ACK, &event->txn_id, + ev_ctx->commit_ctx); - 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); + if (ev_ctx->rsp_dict) + dict_unref(ev_ctx->rsp_dict); + if (free_errstr && ev_ctx->op_errstr) + GF_FREE(ev_ctx->op_errstr); + GF_FREE(ctx); + gf_msg_debug(this->name, 0, "Returning %d", ret); - return ret; + return ret; } static int -glusterd_op_log_rotate (dict_t *dict) +glusterd_op_ac_rcvd_commit_op_acc(glusterd_op_sm_event_t *event, void *ctx) { - 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; - } + int ret = 0; + gf_boolean_t commit_ack_inject = _gf_true; + glusterd_op_t op = GD_OP_NONE; + xlator_t *this = NULL; - 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; + this = THIS; + GF_ASSERT(this); + op = glusterd_op_get_op(); + GF_ASSERT(event); - snprintf (logfile, PATH_MAX, "%s.%"PRIu64, - brickinfo->logfile, key); + if (opinfo.pending_count > 0) + opinfo.pending_count--; - ret = rename (brickinfo->logfile, logfile); - if (ret) - gf_log ("", GF_LOG_WARNING, "rename failed"); + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); - ret = kill (pid, SIGHUP); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to SIGHUP to %d", pid); - goto out; - } - ret = 0; + if (opinfo.pending_count > 0) + goto out; - /* If request was for brick, only one iteration is enough */ - if (brick) - break; + if (op == GD_OP_REPLACE_BRICK) { + ret = glusterd_op_sm_inject_all_acc(&event->txn_id); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_RBOP_START_FAIL, + "Couldn't start " + "replace-brick operation."); + goto out; } - if (ret && !valid_brick) - ret = 0; + commit_ack_inject = _gf_false; + goto out; + } out: - if (tmpbrkinfo) - glusterd_brickinfo_delete (tmpbrkinfo); - - 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 (commit_ack_inject) { 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 (); + 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*/ + } -out: - return ret; + return ret; } static int -glusterd_op_sync_volume (dict_t *dict, char **op_errstr, - dict_t *rsp_dict) +glusterd_op_ac_rcvd_unlock_acc(glusterd_op_sm_event_t *event, void *ctx) { - int ret = -1; - char *volname = NULL; - char *hostname = NULL; - char msg[2048] = {0,}; - int count = 1; - int vol_count = 0; - 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, "hostname", &hostname); - if (ret) { - snprintf (msg, sizeof (msg), "hostname couldn't be " - "retrieved from msg"); - *op_errstr = gf_strdup (msg); - goto out; - } + int ret = 0; - if (glusterd_is_local_addr (hostname)) { - ret = 0; - goto out; - } + GF_ASSERT(event); - //volname is not present in case of sync all - ret = dict_get_str (dict, "volname", &volname); - if (!ret) { - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Volume with name: %s " - "not exists", volname); - goto out; - } - } + if (opinfo.pending_count > 0) + opinfo.pending_count--; - if (!rsp_dict) { - //this should happen only on source - ret = 0; - goto out; - } + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); - if (volname) { - ret = glusterd_add_volume_to_dict (volinfo, rsp_dict, - 1); - vol_count = 1; - } else { - list_for_each_entry (volinfo, &priv->volumes, vol_list) { - ret = glusterd_add_volume_to_dict (volinfo, - rsp_dict, count); - if (ret) - goto out; + if (opinfo.pending_count > 0) + goto out; - vol_count = count++; - } - } - ret = dict_set_int32 (rsp_dict, "count", vol_count); + ret = glusterd_op_sm_inject_event(GD_OP_EVENT_ALL_ACC, &event->txn_id, + NULL); -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_msg_debug(THIS->name, 0, "Returning %d", ret); - return ret; +out: + return ret; } -static int -glusterd_add_profile_volume_options (glusterd_volinfo_t *volinfo) +int32_t +glusterd_op_clear_errstr() { - int ret = -1; - char *latency_key = NULL; - char *fd_stats_key = NULL; - - GF_ASSERT (volinfo); - - 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) { - gf_log ("glusterd", GF_LOG_ERROR, "failed to set the volume %s " - "option %s value %s", - volinfo->volname, latency_key, "on"); - goto out; - } - - ret = dict_set_str (volinfo->dict, fd_stats_key, "on"); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "failed to set the volume %s " - "option %s value %s", - volinfo->volname, fd_stats_key, "on"); - goto out; - } -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + opinfo.op_errstr = NULL; + return 0; } -static void -glusterd_remove_profile_volume_options (glusterd_volinfo_t *volinfo) +int32_t +glusterd_op_set_ctx(void *ctx) { - char *latency_key = NULL; - char *fd_stats_key = NULL; + opinfo.op_ctx = ctx; - GF_ASSERT (volinfo); - - 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); + return 0; } -static int -glusterd_op_stats_volume (dict_t *dict, char **op_errstr, - dict_t *rsp_dict) +int32_t +glusterd_op_reset_ctx() { - int ret = -1; - char *volname = NULL; - char msg[2048] = {0,}; - glusterd_volinfo_t *volinfo = NULL; - int32_t stats_op = GF_CLI_STATS_NONE; - - 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 exists", - volname); - - gf_log ("", GF_LOG_ERROR, "%s", msg); - goto out; - } - - ret = dict_get_int32 (dict, "op", &stats_op); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "volume profile op get failed"); - goto out; - } - - switch (stats_op) { - case GF_CLI_STATS_START: - ret = glusterd_add_profile_volume_options (volinfo); - if (ret) - goto out; - break; - case GF_CLI_STATS_STOP: - glusterd_remove_profile_volume_options (volinfo); - break; - case GF_CLI_STATS_INFO: - case GF_CLI_STATS_TOP: - //info is already collected in brick op. - //just goto out; - ret = 0; - goto out; - break; - default: - GF_ASSERT (0); - gf_log ("glusterd", GF_LOG_ERROR, "Invalid profile op: %d", - stats_op); - ret = -1; - goto out; - break; - } - ret = glusterd_create_volfiles_and_notify_services (volinfo); + glusterd_op_set_ctx(NULL); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to create volfile for" - " 'volume set'"); - ret = -1; - goto out; - } + return 0; +} - ret = glusterd_store_volinfo (volinfo, - GLUSTERD_VOLINFO_VER_AC_INCREMENT); +int32_t +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; + rpcsvc_request_t *req = NULL; + void *ctx = NULL; + char *op_errstr = NULL; + char *volname = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT(this); + + priv = this->private; + GF_ASSERT(priv); + + op = glusterd_op_get_op(); + ctx = glusterd_op_get_ctx(); + op_ret = opinfo.op_ret; + op_errno = opinfo.op_errno; + 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 < GD_OP_VERSION_3_6_0) { + ret = glusterd_unlock(MY_UUID); + /* unlock can't/shouldn't fail here!! */ if (ret) - goto out; - - if (GLUSTERD_STATUS_STARTED == volinfo->status) - ret = glusterd_check_generate_start_nfs (); + gf_msg(this->name, GF_LOG_CRITICAL, 0, GD_MSG_GLUSTERD_UNLOCK_FAIL, + "Unable to clear local lock, ret: %d", ret); + else + gf_msg_debug(this->name, 0, "Cleared local lock"); + } else { + ret = dict_get_strn(ctx, "volname", SLEN("volname"), &volname); + if (ret) + gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_DICT_GET_FAILED, + "No Volume name present. " + "Locks have not been held."); + if (volname) { + ret = glusterd_mgmt_v3_unlock(volname, MY_UUID, "vol"); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_UNLOCK_FAIL, + "Unable to release lock for %s", volname); + } + } + + ret = glusterd_op_send_cli_response(op, op_ret, op_errno, req, ctx, + op_errstr); + + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_NO_CLI_RESP, + "Responding to cli failed, " + "ret: %d", + ret); + // Ignore this error, else state machine blocks ret = 0; + } -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} + if (op_errstr && (strcmp(op_errstr, ""))) + GF_FREE(op_errstr); -static int -glusterd_op_ac_none (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; + if (priv->pending_quorum_action) + glusterd_do_quorum_action(); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + /* Clearing the transaction opinfo */ + ret = glusterd_clear_txn_opinfo(txn_id); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_CLEAR_FAIL, + "Unable to clear transaction's opinfo"); - return ret; + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } static int -glusterd_op_ac_send_lock (glusterd_op_sm_event_t *event, void *ctx) +glusterd_op_ac_unlocked_all(glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - rpc_clnt_procedure_t *proc = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - uint32_t pending_count = 0; - - this = THIS; - priv = this->private; - GF_ASSERT (priv); + int ret = 0; - list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - GF_ASSERT (peerinfo); + GF_ASSERT(event); - if (!peerinfo->connected || !peerinfo->mgmt) - continue; - if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && - (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) - continue; + ret = glusterd_op_txn_complete(&event->txn_id); - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_LOCK]; - if (proc->fn) { - ret = proc->fn (NULL, this, peerinfo); - if (ret) - continue; - pending_count++; - } - } + gf_msg_debug(THIS->name, 0, "Returning %d", ret); - 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); - - return ret; + return ret; } static int -glusterd_op_ac_send_unlock (glusterd_op_sm_event_t *event, void *ctx) +glusterd_op_ac_stage_op(glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - rpc_clnt_procedure_t *proc = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - uint32_t pending_count = 0; + int ret = -1; + glusterd_req_ctx_t *req_ctx = NULL; + int32_t status = 0; + dict_t *rsp_dict = NULL; + char *op_errstr = NULL; + dict_t *dict = NULL; + xlator_t *this = NULL; + uuid_t *txn_id = NULL; + glusterd_op_info_t txn_op_info = { + {0}, + }; + glusterd_conf_t *priv = NULL; - this = THIS; - priv = this->private; - GF_ASSERT (priv); + this = THIS; + GF_ASSERT(this); - /*ret = glusterd_unlock (priv->uuid); + priv = this->private; + GF_ASSERT(priv); - if (ret) - goto out; - */ + GF_ASSERT(ctx); - list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - GF_ASSERT (peerinfo); + req_ctx = ctx; - if (!peerinfo->connected || !peerinfo->mgmt) - continue; - if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && - (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) - continue; + dict = req_ctx->dict; - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_CLUSTER_UNLOCK]; - if (proc->fn) { - ret = proc->fn (NULL, this, peerinfo); - if (ret) - 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); - - return ret; - -} + rsp_dict = dict_new(); + if (!rsp_dict) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_DICT_CREATE_FAIL, + "Failed to get new dictionary"); + return -1; + } -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; + status = glusterd_op_stage_validate(req_ctx->op, dict, &op_errstr, + rsp_dict); + if (status) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_VALIDATE_FAILED, + "Stage failed on operation" + " 'Volume %s', Status : %d", + gd_op_list[req_ctx->op], status); + } - GF_ASSERT (event); - GF_ASSERT (ctx); + txn_id = GF_MALLOC(sizeof(uuid_t), gf_common_mt_uuid_t); - lock_ctx = (glusterd_op_lock_ctx_t *)ctx; + if (txn_id) + gf_uuid_copy(*txn_id, event->txn_id); + else { + ret = -1; + goto out; + } + ret = glusterd_get_txn_opinfo(&event->txn_id, &txn_op_info); + + ret = dict_set_bin(rsp_dict, "transaction_id", txn_id, sizeof(*txn_id)); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set transaction id."); + GF_FREE(txn_id); + txn_id = NULL; + goto out; + } + + ret = glusterd_op_stage_send_resp(req_ctx->req, req_ctx->op, status, + op_errstr, rsp_dict); - status = glusterd_lock (lock_ctx->uuid); +out: + if (op_errstr && (strcmp(op_errstr, ""))) + GF_FREE(op_errstr); - gf_log ("", GF_LOG_DEBUG, "Lock Returned %d", status); + gf_msg_debug(this->name, 0, "Returning with %d", ret); - ret = glusterd_op_lock_send_resp (lock_ctx->req, status); + /* for no volname transactions, the txn_opinfo needs to be cleaned up + * as there's no unlock event triggered. However if the originator node of + * this transaction is still running with a version lower than 60000, + * txn_opinfo can't be cleared as that'll lead to a race of referring op_ctx + * after it's being freed. + */ + if (txn_op_info.skip_locking && priv->op_version >= GD_OP_VERSION_6_0 && + txn_id) + ret = glusterd_clear_txn_opinfo(txn_id); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + if (rsp_dict) + dict_unref(rsp_dict); - return ret; + return ret; } -static int -glusterd_op_ac_unlock (glusterd_op_sm_event_t *event, void *ctx) +static gf_boolean_t +glusterd_need_brick_op(glusterd_op_t op) { - int ret = 0; - glusterd_op_lock_ctx_t *lock_ctx = NULL; + gf_boolean_t ret = _gf_false; - GF_ASSERT (event); - GF_ASSERT (ctx); + GF_ASSERT(GD_OP_NONE < op && op < GD_OP_MAX); - lock_ctx = (glusterd_op_lock_ctx_t *)ctx; + switch (op) { + case GD_OP_PROFILE_VOLUME: + case GD_OP_STATUS_VOLUME: + case GD_OP_DEFRAG_BRICK_VOLUME: + case GD_OP_HEAL_VOLUME: + case GD_OP_SCRUB_STATUS: + case GD_OP_SCRUB_ONDEMAND: + ret = _gf_true; + break; + default: + ret = _gf_false; + } - ret = glusterd_unlock (lock_ctx->uuid); + return ret; +} - gf_log ("", GF_LOG_DEBUG, "Unlock Returned %d", ret); +dict_t * +glusterd_op_init_commit_rsp_dict(glusterd_op_t op) +{ + dict_t *rsp_dict = NULL; + dict_t *op_ctx = NULL; - ret = glusterd_op_unlock_send_resp (lock_ctx->req, ret); + GF_ASSERT(GD_OP_NONE < op && op < GD_OP_MAX); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + 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 ret; + return rsp_dict; } static int -glusterd_op_ac_rcvd_lock_acc (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; +glusterd_op_ac_commit_op(glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = 0; + glusterd_req_ctx_t *req_ctx = NULL; + int32_t status = 0; + char *op_errstr = NULL; + dict_t *dict = NULL; + dict_t *rsp_dict = NULL; + xlator_t *this = NULL; + uuid_t *txn_id = NULL; + glusterd_op_info_t txn_op_info = { + {0}, + }; + gf_boolean_t need_cleanup = _gf_true; + + this = THIS; + GF_ASSERT(this); + GF_ASSERT(ctx); + + req_ctx = ctx; + + dict = req_ctx->dict; + + rsp_dict = glusterd_op_init_commit_rsp_dict(req_ctx->op); + if (NULL == rsp_dict) + return -1; - GF_ASSERT (event); + if (GD_OP_CLEARLOCKS_VOLUME == req_ctx->op) { + /*clear locks should be run only on + * originator glusterd*/ + status = 0; - if (opinfo.pending_count > 0) - opinfo.pending_count--; + } else { + status = glusterd_op_commit_perform(req_ctx->op, dict, &op_errstr, + rsp_dict); + } - if (opinfo.pending_count > 0) - goto out; + if (status) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_COMMIT_OP_FAIL, + "Commit of operation " + "'Volume %s' failed: %d", + gd_op_list[req_ctx->op], status); - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); + txn_id = GF_MALLOC(sizeof(uuid_t), gf_common_mt_uuid_t); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + if (txn_id) + gf_uuid_copy(*txn_id, event->txn_id); + else { + ret = -1; + goto out; + } + ret = glusterd_get_txn_opinfo(&event->txn_id, &txn_op_info); + if (ret) { + gf_msg_callingfn(this->name, GF_LOG_ERROR, 0, + GD_MSG_TRANS_OPINFO_GET_FAIL, + "Unable to get transaction opinfo " + "for transaction ID : %s", + uuid_utoa(event->txn_id)); + goto out; + } + + ret = dict_set_bin(rsp_dict, "transaction_id", txn_id, sizeof(*txn_id)); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set transaction id."); + if (txn_op_info.skip_locking) + ret = glusterd_clear_txn_opinfo(txn_id); + need_cleanup = _gf_false; + GF_FREE(txn_id); + goto out; + } + + ret = glusterd_op_commit_send_resp(req_ctx->req, req_ctx->op, status, + op_errstr, rsp_dict); out: - return ret; -} + if (op_errstr && (strcmp(op_errstr, ""))) + GF_FREE(op_errstr); -int -glusterd_op_build_payload (glusterd_op_t op, dict_t **req) -{ - int ret = -1; - void *ctx = NULL; - dict_t *req_dict = NULL; - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - GF_ASSERT (req); - - 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 (rsp_dict) + dict_unref(rsp_dict); + /* for no volname transactions, the txn_opinfo needs to be cleaned up + * as there's no unlock event triggered + */ + if (need_cleanup && txn_id && txn_op_info.skip_locking) + ret = glusterd_clear_txn_opinfo(txn_id); + gf_msg_debug(this->name, 0, "Returning with %d", ret); - switch (op) { - case GD_OP_CREATE_VOLUME: - { - dict_t *dict = ctx; - ++glusterfs_port; - ret = dict_set_int32 (dict, "port", glusterfs_port); - if (ret) - goto out; - dict_copy (dict, req_dict); - } - break; - - case GD_OP_DELETE_VOLUME: - { - glusterd_op_delete_volume_ctx_t *ctx1 = ctx; - ret = dict_set_str (req_dict, "volname", - ctx1->volume_name); - if (ret) - goto out; - } - break; - - 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_LOG_LEVEL: - { - dict_t *dict = ctx; - dict_copy (dict, req_dict); - } - break; - - default: - break; - } - - *req = req_dict; - ret = 0; - -out: - return ret; + return ret; } static int -glusterd_op_ac_send_stage_op (glusterd_op_sm_event_t *event, void *ctx) +glusterd_op_ac_send_commit_failed(glusterd_op_sm_event_t *event, void *ctx) { - int ret = 0; - rpc_clnt_procedure_t *proc = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - dict_t *dict = NULL; - char *op_errstr = NULL; - int i = 0; - 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.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); - - return ret; - } + int ret = 0; + glusterd_req_ctx_t *req_ctx = NULL; + dict_t *op_ctx = NULL; - glusterd_op_clear_pending_op (i); + GF_ASSERT(ctx); - ret = glusterd_op_build_payload (i, &dict); - if (ret) - 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"); - opinfo.op_errstr = op_errstr; - goto out; - } + req_ctx = ctx; - list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - GF_ASSERT (peerinfo); + op_ctx = glusterd_op_get_ctx(); - 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_STAGE_OP]; - GF_ASSERT (proc); - if (proc->fn) { - ret = dict_set_static_ptr (dict, "peerinfo", peerinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to set peerinfo"); - goto out; - } + ret = glusterd_op_commit_send_resp(req_ctx->req, req_ctx->op, opinfo.op_ret, + opinfo.op_errstr, op_ctx); - ret = proc->fn (NULL, this, dict); - if (ret) - continue; - pending_count++; - } - } - - opinfo.pending_count = pending_count; -out: - if (dict) - dict_unref (dict); - if (ret) { - glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); - opinfo.op_ret = ret; - } - - gf_log ("glusterd", GF_LOG_INFO, "Sent op req to %d peers", - opinfo.pending_count); - - if (!opinfo.pending_count) - ret = glusterd_op_sm_inject_all_acc (); - - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + if (opinfo.op_errstr && (strcmp(opinfo.op_errstr, ""))) { + GF_FREE(opinfo.op_errstr); + opinfo.op_errstr = NULL; + } - return ret; + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); + gf_msg_debug(THIS->name, 0, "Returning with %d", ret); + return ret; } -static int32_t -glusterd_op_start_rb_timer (dict_t *dict) +static int +glusterd_op_sm_transition_state(glusterd_op_info_t *opinfo, + glusterd_op_sm_t *state, + glusterd_op_sm_event_type_t event_type) { - int32_t op = 0; - struct timeval timeout = {0, }; - glusterd_conf_t *priv = NULL; - int32_t ret = -1; + glusterd_conf_t *conf = NULL; - GF_ASSERT (dict); - priv = THIS->private; + GF_ASSERT(state); + GF_ASSERT(opinfo); - ret = dict_get_int32 (dict, "operation", &op); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "dict_get on operation failed"); - goto out; - } + conf = THIS->private; + GF_ASSERT(conf); - if (op == GF_REPLACE_OP_START || - op == GF_REPLACE_OP_ABORT) - timeout.tv_sec = 5; - else - timeout.tv_sec = 1; - - timeout.tv_usec = 0; - - - priv->timer = gf_timer_call_after (THIS->ctx, timeout, - glusterd_do_replace_brick, - (void *) dict); - - ret = 0; + (void)glusterd_sm_tr_log_transition_add( + &conf->op_sm_log, opinfo->state.state, state[event_type].next_state, + event_type); -out: - return ret; + opinfo->state.state = state[event_type].next_state; + return 0; } -static int -glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx) +int32_t +glusterd_op_stage_validate(glusterd_op_t op, dict_t *dict, char **op_errstr, + dict_t *rsp_dict) { - int ret = 0; - rpc_clnt_procedure_t *proc = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - dict_t *dict = NULL; - dict_t *op_dict = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - char *op_errstr = NULL; - int i = 0; - uint32_t pending_count = 0; + int ret = -1; + xlator_t *this = THIS; - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); + switch (op) { + case GD_OP_CREATE_VOLUME: + ret = glusterd_op_stage_create_volume(dict, op_errstr, rsp_dict); + break; - for ( i = GD_OP_NONE; i < GD_OP_MAX; i++) { - if (opinfo.commit_op[i]) - break; - } + case GD_OP_START_VOLUME: + ret = glusterd_op_stage_start_volume(dict, op_errstr, rsp_dict); + break; - if (GD_OP_MAX == i) { - //No pending ops, return - return 0; - } + case GD_OP_STOP_VOLUME: + ret = glusterd_op_stage_stop_volume(dict, op_errstr); + break; - glusterd_op_clear_commit_op (i); + case GD_OP_DELETE_VOLUME: + ret = glusterd_op_stage_delete_volume(dict, op_errstr); + break; - ret = glusterd_op_build_payload (i, &dict); + case GD_OP_ADD_BRICK: + ret = glusterd_op_stage_add_brick(dict, op_errstr, rsp_dict); + break; - if (ret) - goto out; + case GD_OP_REPLACE_BRICK: + ret = glusterd_op_stage_replace_brick(dict, op_errstr, rsp_dict); + break; - ret = glusterd_op_commit_perform (i, dict, &op_errstr, NULL); //rsp_dict invalid for source - if (ret) { - gf_log ("", GF_LOG_ERROR, "Commit failed"); - opinfo.op_errstr = op_errstr; - goto out; - } + case GD_OP_SET_VOLUME: + ret = glusterd_op_stage_set_volume(dict, op_errstr); + break; - list_for_each_entry (peerinfo, &priv->peers, uuid_list) { - GF_ASSERT (peerinfo); + case GD_OP_GANESHA: + ret = glusterd_op_stage_set_ganesha(dict, op_errstr); + break; - if (!peerinfo->connected || !peerinfo->mgmt) - continue; - if ((peerinfo->state.state != GD_FRIEND_STATE_BEFRIENDED) && - (glusterd_op_get_op() != GD_OP_SYNC_VOLUME)) - continue; + case GD_OP_RESET_VOLUME: + ret = glusterd_op_stage_reset_volume(dict, op_errstr); + break; + case GD_OP_REMOVE_BRICK: + ret = glusterd_op_stage_remove_brick(dict, op_errstr); + break; - proc = &peerinfo->mgmt->proctable[GLUSTERD_MGMT_COMMIT_OP]; - GF_ASSERT (proc); - if (proc->fn) { - ret = dict_set_static_ptr (dict, "peerinfo", peerinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "failed to set peerinfo"); - goto out; - } - ret = proc->fn (NULL, this, dict); - if (ret) - continue; - pending_count++; - } - } + case GD_OP_LOG_ROTATE: + ret = glusterd_op_stage_log_rotate(dict, op_errstr); + break; - opinfo.pending_count = pending_count; - gf_log ("glusterd", GF_LOG_INFO, "Sent op req to %d peers", - opinfo.pending_count); -out: - if (dict) - dict_unref (dict); - if (ret) { - glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); - opinfo.op_ret = ret; - } + case GD_OP_SYNC_VOLUME: + ret = glusterd_op_stage_sync_volume(dict, op_errstr); + break; - 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; - } + case GD_OP_GSYNC_CREATE: + ret = glusterd_op_stage_gsync_create(dict, op_errstr); + break; - op_dict = dict_ref (op_dict); - ret = glusterd_op_start_rb_timer (op_dict); - } + case GD_OP_GSYNC_SET: + ret = glusterd_op_stage_gsync_set(dict, op_errstr); + break; -err: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + case GD_OP_PROFILE_VOLUME: + ret = glusterd_op_stage_stats_volume(dict, op_errstr); + break; + + case GD_OP_QUOTA: + ret = glusterd_op_stage_quota(dict, op_errstr, rsp_dict); + 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; + + case GD_OP_BARRIER: + ret = glusterd_op_stage_barrier(dict, op_errstr); + break; + + case GD_OP_BITROT: + case GD_OP_SCRUB_STATUS: + case GD_OP_SCRUB_ONDEMAND: + ret = glusterd_op_stage_bitrot(dict, op_errstr, rsp_dict); + break; - return ret; + default: + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, + "Unknown op %s", gd_op_list[op]); + } + gf_msg_debug(this->name, 0, "OP = %d. Returning %d", op, ret); + return ret; } -static int -glusterd_op_ac_rcvd_stage_op_acc (glusterd_op_sm_event_t *event, void *ctx) +static void +glusterd_wait_for_blockers(glusterd_conf_t *priv) +{ + while (GF_ATOMIC_GET(priv->blockers)) { + synccond_wait(&priv->cond_blockers, &priv->big_lock); + } +} + +int32_t +glusterd_op_commit_perform(glusterd_op_t op, dict_t *dict, char **op_errstr, + dict_t *rsp_dict) { - int ret = 0; + int ret = -1; + xlator_t *this = THIS; - GF_ASSERT (event); + 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); + break; - if (opinfo.pending_count > 0) - opinfo.pending_count--; + case GD_OP_START_VOLUME: + ret = glusterd_op_start_volume(dict, op_errstr); + break; - if (opinfo.pending_count > 0) - goto out; + case GD_OP_STOP_VOLUME: + ret = glusterd_op_stop_volume(dict); + break; + + case GD_OP_DELETE_VOLUME: + glusterd_wait_for_blockers(this->private); + ret = glusterd_op_delete_volume(dict); + break; + + case GD_OP_ADD_BRICK: + glusterd_wait_for_blockers(this->private); + ret = glusterd_op_add_brick(dict, op_errstr); + break; + + case GD_OP_REPLACE_BRICK: + glusterd_wait_for_blockers(this->private); + ret = glusterd_op_replace_brick(dict, rsp_dict); + break; + + case GD_OP_SET_VOLUME: + ret = glusterd_op_set_volume(dict, op_errstr); + break; + case GD_OP_GANESHA: + ret = glusterd_op_set_ganesha(dict, op_errstr); + break; + case GD_OP_RESET_VOLUME: + ret = glusterd_op_reset_volume(dict, op_errstr); + break; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_STAGE_ACC, NULL); + case GD_OP_REMOVE_BRICK: + glusterd_wait_for_blockers(this->private); + ret = glusterd_op_remove_brick(dict, op_errstr); + break; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + case GD_OP_LOG_ROTATE: + ret = glusterd_op_log_rotate(dict); + break; - return ret; -} + case GD_OP_SYNC_VOLUME: + ret = glusterd_op_sync_volume(dict, op_errstr, rsp_dict); + break; -static int -glusterd_op_ac_stage_op_failed (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; + case GD_OP_GSYNC_CREATE: + ret = glusterd_op_gsync_create(dict, op_errstr, rsp_dict); + break; - GF_ASSERT (event); + case GD_OP_GSYNC_SET: + ret = glusterd_op_gsync_set(dict, op_errstr, rsp_dict); + break; - if (opinfo.pending_count > 0) - opinfo.pending_count--; + case GD_OP_PROFILE_VOLUME: + ret = glusterd_op_stats_volume(dict, op_errstr, rsp_dict); + break; - if (opinfo.pending_count > 0) - goto out; + case GD_OP_QUOTA: + ret = glusterd_op_quota(dict, op_errstr, rsp_dict); + break; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, NULL); + case GD_OP_STATUS_VOLUME: + ret = glusterd_op_status_volume(dict, op_errstr, rsp_dict); + break; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + case GD_OP_REBALANCE: + case GD_OP_DEFRAG_BRICK_VOLUME: + ret = glusterd_op_rebalance(dict, op_errstr, rsp_dict); + break; - return ret; -} + case GD_OP_HEAL_VOLUME: + ret = glusterd_op_heal_volume(dict, op_errstr); + break; -static int -glusterd_op_ac_commit_op_failed (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; + case GD_OP_STATEDUMP_VOLUME: + ret = glusterd_op_statedump_volume(dict, op_errstr); + break; - GF_ASSERT (event); + case GD_OP_CLEARLOCKS_VOLUME: + ret = glusterd_op_clearlocks_volume(dict, op_errstr, rsp_dict); + break; - if (opinfo.pending_count > 0) - opinfo.pending_count--; + case GD_OP_COPY_FILE: + ret = glusterd_op_copy_file(dict, op_errstr); + break; - if (opinfo.pending_count > 0) - goto out; + case GD_OP_SYS_EXEC: + ret = glusterd_op_sys_exec(dict, op_errstr, rsp_dict); + break; - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, NULL); + case GD_OP_BARRIER: + ret = glusterd_op_barrier(dict, op_errstr); + break; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + case GD_OP_BITROT: + case GD_OP_SCRUB_STATUS: + case GD_OP_SCRUB_ONDEMAND: + ret = glusterd_op_bitrot(dict, op_errstr, rsp_dict); + break; - return ret; + default: + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, + "Unknown op %s", gd_op_list[op]); + break; + } + + if (ret == 0) + glusterd_op_commit_hook(op, dict, GD_COMMIT_HOOK_POST); + + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } static int -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; - - 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); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "unknown response received " - "from %s:%s", brickinfo->hostname, brickinfo->path); +glusterd_bricks_select_stop_volume(dict_t *dict, char **op_errstr, + struct cds_list_head *selected) +{ + int ret = 0; + int flags = 0; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + 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) { + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + FMTSTR_CHECK_VOL_EXISTS, volname); + gf_asprintf(op_errstr, FMTSTR_CHECK_VOL_EXISTS, volname); + goto out; + } + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (glusterd_is_brick_started(brickinfo)) { + pending_node = GF_CALLOC(1, sizeof(*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { ret = -1; - free_errstr = _gf_true; - goto out; - } - if (opinfo.brick_pending_count > 0) - opinfo.brick_pending_count--; - if (opinfo.op_ret == 0) - opinfo.op_ret = ev_ctx->op_ret; - - if (opinfo.op_errstr == NULL) - opinfo.op_errstr = ev_ctx->op_errstr; - else - free_errstr = _gf_true; - - if (opinfo.brick_pending_count > 0) goto out; - - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACK, ev_ctx->commit_ctx); + } else { + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } + /* + * This is not really the right place to do it, but + * it's the most convenient. + * TBD: move this to *after* the RPC + */ + brickinfo->status = GF_BRICK_STOPPED; + } + } out: - if (ev_ctx->rsp_dict) - dict_unref (ev_ctx->rsp_dict); - if (free_errstr && ev_ctx->op_errstr) - GF_FREE (ev_ctx->op_errstr); - GF_FREE (ctx); - gf_log ("", 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 (); + return ret; } -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; - } +static int +glusterd_bricks_select_remove_brick(dict_t *dict, char **op_errstr, + struct cds_list_head *selected) +{ + int ret = -1; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + char *brick = NULL; + int32_t count = 0; + int32_t i = 1; + char key[64] = { + 0, + }; + int keylen; + glusterd_pending_node_t *pending_node = NULL; + int32_t command = 0; + int32_t force = 0; + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + "Unable to allocate memory"); + goto out; + } + + ret = dict_get_int32n(dict, "count", SLEN("count"), &count); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, -ret, GD_MSG_DICT_GET_FAILED, + "Unable to get count"); + goto out; + } + + ret = dict_get_int32n(dict, "command", SLEN("command"), &command); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, -ret, GD_MSG_DICT_GET_FAILED, + "Unable to get command"); + goto out; + } + + ret = dict_get_int32n(dict, "force", SLEN("force"), &force); + if (ret) { + gf_msg(THIS->name, GF_LOG_INFO, 0, GD_MSG_DICT_GET_FAILED, + "force flag is not set"); + ret = 0; + goto out; + } - gf_log ("", GF_LOG_DEBUG, - "src brick=%s", src_brick); + while (i <= count) { + keylen = snprintf(key, sizeof(key), "brick%d", i); - ret = dict_get_str (dict, "dst-brick", &dst_brick); + ret = dict_get_strn(dict, key, keylen, &brick); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); - goto out; + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get brick"); + goto out; } - gf_log ("", GF_LOG_DEBUG, - "dst brick=%s", dst_brick); + ret = glusterd_volume_brickinfo_get_by_brick(brick, volinfo, &brickinfo, + _gf_false); - ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); + if (glusterd_is_brick_started(brickinfo)) { + 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 = brickinfo; + pending_node->type = GD_NODE_BRICK; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } + /* + * This is not really the right place to do it, but + * it's the most convenient. + * TBD: move this to *after* the RPC + */ + brickinfo->status = GF_BRICK_STOPPED; + } + i++; + } - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); - goto out; - } +out: + return ret; +} - 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; - } +static int +glusterd_bricks_select_profile_volume(dict_t *dict, char **op_errstr, + struct cds_list_head *selected) +{ + int ret = -1; + char *volname = NULL; + char msg[2048] = { + 0, + }; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + xlator_t *this = NULL; + int32_t stats_op = GF_CLI_STATS_NONE; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_pending_node_t *pending_node = NULL; + char *brick = NULL; + int32_t pid = -1; + char pidfile[PATH_MAX] = {0}; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "volume name get failed"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + snprintf(msg, sizeof(msg), "Volume %s does not exists", volname); + + *op_errstr = gf_strdup(msg); + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, "%s", msg); + goto out; + } + + ret = dict_get_int32n(dict, "op", SLEN("op"), &stats_op); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "volume profile op get failed"); + goto out; + } + + switch (stats_op) { + case GF_CLI_STATS_START: + case GF_CLI_STATS_STOP: + goto out; + break; + case GF_CLI_STATS_INFO: +#ifdef BUILD_GNFS + ret = dict_get_str_boolean(dict, "nfs", _gf_false); + if (ret) { + if (!priv->nfs_svc.online) { + ret = -1; + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_NFS_SERVER_NOT_RUNNING, + "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_svc); + pending_node->type = GD_NODE_NFS; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); - if (!dst_brickinfo) { - gf_log ("", GF_LOG_DEBUG, "Unable to get dst-brickinfo"); + ret = 0; goto out; - } + } +#endif + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (glusterd_is_brick_started(brickinfo)) { + /* + * In normal use, glusterd_is_brick_started + * will give us the answer we need. However, + * in our tests the brick gets detached behind + * our back, so we need to double-check this + * way. + */ + GLUSTERD_GET_BRICK_PIDFILE(pidfile, volinfo, brickinfo, + priv); + if (!gf_is_service_running(pidfile, &pid)) { + continue; + } + 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 = brickinfo; + pending_node->type = GD_NODE_BRICK; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } + } + } + break; - ret = glusterd_resolve_brick (dst_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); - goto out; - } + case GF_CLI_STATS_TOP: +#ifdef BUILD_GNFS + ret = dict_get_str_boolean(dict, "nfs", _gf_false); + if (ret) { + if (!priv->nfs_svc.online) { + ret = -1; + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_NFS_SERVER_NOT_RUNNING, + "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_svc); + pending_node->type = GD_NODE_NFS; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; - ret = dict_get_int32 (dict, "src-brick-port", &src_port); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src-brick port"); + ret = 0; 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"); - } + } +#endif + ret = dict_get_strn(dict, "brick", SLEN("brick"), &brick); + if (!ret) { + ret = glusterd_volume_brickinfo_get_by_brick( + brick, volinfo, &brickinfo, _gf_true); + if (ret) + goto out; - dst_brickinfo->port = dst_port; - src_brickinfo->port = src_port; + if (!glusterd_is_brick_started(brickinfo)) + goto out; - switch (op) { - case GF_REPLACE_OP_START: - if (!dst_port) { + 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 = brickinfo; + pending_node->type = GD_NODE_BRICK; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + goto out; + } + } + ret = 0; + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (glusterd_is_brick_started(brickinfo)) { + 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 = brickinfo; + pending_node->type = GD_NODE_BRICK; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } } + } + break; - 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; - } + GF_ASSERT(0); + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_INVALID_ENTRY, + "Invalid profile op: %d", stats_op); + ret = -1; + goto out; + break; + } 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); + gf_msg_debug("glusterd", 0, "Returning %d", ret); - glusterd_op_sm (); + return ret; } - - -static int -glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) +int +_get_hxl_children_count(glusterd_volinfo_t *volinfo) { - glusterd_conf_t *priv = NULL; - dict_t *dict = NULL; - int ret = 0; - gf_boolean_t commit_ack_inject = _gf_false; - - priv = THIS->private; - GF_ASSERT (event); - - if (opinfo.pending_count > 0) - opinfo.pending_count--; - - 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) - goto out; - commit_ack_inject = _gf_false; - 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); - } - - return ret; + if (volinfo->type == GF_CLUSTER_TYPE_DISPERSE) { + return volinfo->disperse_count; + } else { + return volinfo->replica_count; + } } static int -glusterd_op_ac_rcvd_unlock_acc (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; - - GF_ASSERT (event); - - if (opinfo.pending_count > 0) - opinfo.pending_count--; - - if (opinfo.pending_count > 0) - goto out; - - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_ALL_ACC, NULL); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - +_add_hxlator_to_dict(dict_t *dict, glusterd_volinfo_t *volinfo, int index, + int count) +{ + int ret = -1; + char key[64] = { + 0, + }; + int keylen; + char *xname = NULL; + char *xl_type = 0; + + if (volinfo->type == GF_CLUSTER_TYPE_DISPERSE) { + xl_type = "disperse"; + } else { + xl_type = "replicate"; + } + keylen = snprintf(key, sizeof(key), "xl-%d", count); + ret = gf_asprintf(&xname, "%s-%s-%d", volinfo->volname, xl_type, index); + if (ret == -1) + goto out; + + ret = dict_set_dynstrn(dict, key, keylen, xname); + if (ret) + goto out; + + ret = dict_set_int32(dict, xname, index); out: - return ret; -} - - -int32_t -glusterd_op_clear_errstr() { - opinfo.op_errstr = NULL; - return 0; -} - -int32_t -glusterd_op_set_ctx (glusterd_op_t op, void *ctx) -{ - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - opinfo.op_ctx[op] = ctx; - - return 0; - + return ret; } -int32_t -glusterd_op_reset_ctx (glusterd_op_t op) +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; - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); + if (!dict) { + ret = -1; + goto out; + } + + ret = dict_get_strn(dict, "per-replica-cmd-hostname", + SLEN("per-replica-cmd-hostname"), &hostname); + if (ret) + goto out; + ret = dict_get_strn(dict, "per-replica-cmd-path", + SLEN("per-replica-cmd-path"), &path); + if (ret) + goto out; + + replica_count = volinfo->replica_count; + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (gf_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++; + } - glusterd_op_set_ctx (op, NULL); +out: + if (ret) + cmd_replica_index = -1; - return 0; + return cmd_replica_index; } -int32_t -glusterd_op_txn_complete () +int +_select_hxlator_with_matching_brick(xlator_t *this, glusterd_volinfo_t *volinfo, + dict_t *dict, int *index) { - 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 *path = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + int hxl_children = 0; + if (!dict || dict_get_strn(dict, "per-replica-cmd-path", + SLEN("per-replica-cmd-path"), &path)) + return -1; - priv = THIS->private; - GF_ASSERT (priv); + hxl_children = _get_hxl_children_count(volinfo); + if ((*index) == 0) + (*index)++; - ret = glusterd_unlock (priv->uuid); + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (gf_uuid_is_null(brickinfo->uuid)) + (void)glusterd_resolve_brick(brickinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_CRITICAL, - "Unable to clear local lock, ret: %d", ret); - goto out; + if ((!gf_uuid_compare(MY_UUID, brickinfo->uuid)) && + (!strncmp(brickinfo->path, path, strlen(path)))) { + _add_hxlator_to_dict(dict, volinfo, ((*index) - 1) / hxl_children, + 0); + return 1; } + (*index)++; + } - gf_log ("glusterd", GF_LOG_INFO, "Cleared local lock"); + return 0; +} +void +_select_hxlators_with_local_bricks(xlator_t *this, glusterd_volinfo_t *volinfo, + dict_t *dict, int *index, int *hxlator_count) +{ + glusterd_brickinfo_t *brickinfo = NULL; + int hxl_children = 0; + gf_boolean_t add = _gf_false; - 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; + hxl_children = _get_hxl_children_count(volinfo); + if ((*index) == 0) + (*index)++; - opinfo.op_ret = 0; - opinfo.op_errno = 0; + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (gf_uuid_is_null(brickinfo->uuid)) + (void)glusterd_resolve_brick(brickinfo); - op = glusterd_op_get_op (); + if (!gf_uuid_compare(MY_UUID, brickinfo->uuid)) + add = _gf_true; - 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 ((*index) % hxl_children == 0) { + if (add) { + _add_hxlator_to_dict(dict, volinfo, + ((*index) - 1) / hxl_children, + (*hxlator_count)); + (*hxlator_count)++; + } + add = _gf_false; } -out: - pthread_mutex_unlock (&opinfo.lock); - ret = glusterd_op_send_cli_response (cli_op, op_ret, - op_errno, req, ctx, op_errstr); - - if (ret) { - gf_log ("", 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; + (*index)++; + } } -static int -glusterd_op_ac_unlocked_all (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; - - GF_ASSERT (event); - - ret = glusterd_op_txn_complete (); - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; +int +_select_hxlators_for_full_self_heal(xlator_t *this, glusterd_volinfo_t *volinfo, + dict_t *dict, int *index, + int *hxlator_count) +{ + glusterd_brickinfo_t *brickinfo = NULL; + int hxl_children = 0; + uuid_t candidate = {0}; + int brick_index = 0; + glusterd_peerinfo_t *peerinfo = NULL; + int delta = 0; + uuid_t candidate_max = {0}; + + if ((*index) == 0) + (*index)++; + if (volinfo->type == GF_CLUSTER_TYPE_DISPERSE) { + hxl_children = volinfo->disperse_count; + } else { + hxl_children = volinfo->replica_count; + } + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (gf_uuid_compare(brickinfo->uuid, candidate_max) > 0) { + if (!gf_uuid_compare(MY_UUID, brickinfo->uuid)) { + gf_uuid_copy(candidate_max, brickinfo->uuid); + } else { + peerinfo = glusterd_peerinfo_find(brickinfo->uuid, NULL); + if (peerinfo && peerinfo->connected) { + gf_uuid_copy(candidate_max, brickinfo->uuid); + } + } + } + } + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (gf_uuid_is_null(brickinfo->uuid)) + (void)glusterd_resolve_brick(brickinfo); + + delta %= hxl_children; + if ((*index + delta) == (brick_index + hxl_children)) { + if (!gf_uuid_compare(MY_UUID, brickinfo->uuid)) { + gf_uuid_copy(candidate, brickinfo->uuid); + } else { + peerinfo = glusterd_peerinfo_find(brickinfo->uuid, NULL); + if (peerinfo && peerinfo->connected) { + gf_uuid_copy(candidate, brickinfo->uuid); + } else if (peerinfo && + (!gf_uuid_compare(candidate_max, MY_UUID))) { + _add_hxlator_to_dict(dict, volinfo, + ((*index) - 1) / hxl_children, + (*hxlator_count)); + (*hxlator_count)++; + } + } + + if (!gf_uuid_compare(MY_UUID, candidate)) { + _add_hxlator_to_dict(dict, volinfo, + ((*index) - 1) / hxl_children, + (*hxlator_count)); + (*hxlator_count)++; + } + gf_uuid_clear(candidate); + brick_index += hxl_children; + delta++; + } + + (*index)++; + } + return *hxlator_count; } static int -glusterd_op_stage_quota (dict_t *dict, char **op_errstr) -{ - int ret = 0; - char *volname = NULL; - gf_boolean_t exists = _gf_false; - - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - - 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) { - gf_log ("", GF_LOG_ERROR, "Volume with name: %s " - "does not exist", - volname); - *op_errstr = gf_strdup ("Invalid volume name"); - ret = -1; - goto out; - } +glusterd_bricks_select_snap(dict_t *dict, char **op_errstr, + struct cds_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_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get" + " volname"); + goto out; + } + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) + goto out; + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + brick_index++; + if (gf_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; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } + + ret = 0; out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; + gf_msg_debug(THIS->name, 0, "Returning ret %d", ret); + return ret; } static int -glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = -1; - glusterd_req_ctx_t *req_ctx = NULL; - int32_t status = 0; - dict_t *rsp_dict = NULL; - char *op_errstr = NULL; - dict_t *dict = NULL; - - GF_ASSERT (ctx); - - req_ctx = ctx; - - dict = req_ctx->dict; - - rsp_dict = dict_new (); - if (!rsp_dict) { - gf_log ("", GF_LOG_DEBUG, - "Out of memory"); - return -1; - } - - status = glusterd_op_stage_validate (req_ctx->op, dict, &op_errstr, - rsp_dict); - - if (status) { - gf_log ("", GF_LOG_ERROR, "Validate failed: %d", status); - } - - ret = glusterd_op_stage_send_resp (req_ctx->req, req_ctx->op, - status, op_errstr, rsp_dict); +fill_shd_status_for_local_bricks(dict_t *dict, glusterd_volinfo_t *volinfo, + cli_cmd_type type, int *index, + dict_t *req_dict) +{ + glusterd_brickinfo_t *brickinfo = NULL; + static char *msg = "self-heal-daemon is not running on"; + char key[32] = { + 0, + }; + int keylen; + char value[128] = { + 0, + }; + int ret = 0; + xlator_t *this = NULL; + int cmd_replica_index = -1; + + this = THIS; + + if (type == PER_HEAL_XL) { + cmd_replica_index = get_replica_index_for_per_replica_cmd(volinfo, + req_dict); + if (cmd_replica_index == -1) { + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_REPLICA_INDEX_GET_FAIL, + "Could not find the " + "replica index for per replica type command"); + ret = -1; + goto out; + } + } + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (gf_uuid_is_null(brickinfo->uuid)) + (void)glusterd_resolve_brick(brickinfo); + + if (gf_uuid_compare(MY_UUID, brickinfo->uuid)) { + (*index)++; + continue; + } + + if (type == PER_HEAL_XL) { + if (cmd_replica_index != ((*index) / volinfo->replica_count)) { + (*index)++; + continue; + } + } + keylen = snprintf(key, sizeof(key), "%d-status", (*index)); + snprintf(value, sizeof(value), "%s %s", msg, uuid_utoa(MY_UUID)); + ret = dict_set_dynstrn(dict, key, keylen, gf_strdup(value)); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Unable to" + "set the dictionary for shd status msg"); + goto out; + } + keylen = snprintf(key, sizeof(key), "%d-shd-status", (*index)); + ret = dict_set_nstrn(dict, key, keylen, "off", SLEN("off")); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Unable to" + " set dictionary for shd status msg"); + goto out; + } + + (*index)++; + } - 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); - - return ret; +out: + return ret; } +int +glusterd_shd_select_brick_xlator(dict_t *dict, gf_xl_afr_op_t heal_op, + glusterd_volinfo_t *volinfo, int *index, + int *hxlator_count, dict_t *rsp_dict) +{ + int ret = -1; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + glusterd_svc_t *svc = NULL; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + svc = &(volinfo->shd.svc); + + switch (heal_op) { + case GF_SHD_OP_INDEX_SUMMARY: + case GF_SHD_OP_STATISTICS_HEAL_COUNT: + if (!svc->online) { + if (!rsp_dict) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_OPCTX_NULL, + "Received " + "empty ctx."); + goto out; + } + + ret = fill_shd_status_for_local_bricks( + rsp_dict, volinfo, ALL_HEAL_XL, index, dict); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_SHD_STATUS_SET_FAIL, + "Unable to " + "fill the shd status for the local " + "bricks"); + goto out; + } + break; + + case GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA: + if (!svc->online) { + if (!rsp_dict) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_OPCTX_NULL, + "Received " + "empty ctx."); + goto out; + } + ret = fill_shd_status_for_local_bricks( + rsp_dict, volinfo, PER_HEAL_XL, index, dict); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_SHD_STATUS_SET_FAIL, + "Unable to " + "fill the shd status for the local" + " bricks."); + goto out; + } + break; -static gf_boolean_t -glusterd_need_brick_op (glusterd_op_t op) -{ - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - switch (op) { - case GD_OP_PROFILE_VOLUME: - return _gf_true; default: - return _gf_false; - } - return _gf_false; -} - -static dict_t* -glusterd_op_init_commit_rsp_dict (glusterd_op_t op) -{ - dict_t *rsp_dict = NULL; - dict_t *op_ctx = NULL; - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - if (glusterd_need_brick_op (op)) { - op_ctx = glusterd_op_get_ctx (op); - GF_ASSERT (op_ctx); - rsp_dict = dict_ref (op_ctx); - } else { - rsp_dict = dict_new (); - } - - return rsp_dict; + break; + } + + switch (heal_op) { + case GF_SHD_OP_HEAL_FULL: + _select_hxlators_for_full_self_heal(this, volinfo, dict, index, + hxlator_count); + break; + case GF_SHD_OP_STATISTICS_HEAL_COUNT_PER_REPLICA: + (*hxlator_count) += _select_hxlator_with_matching_brick( + this, volinfo, dict, index); + break; + default: + _select_hxlators_with_local_bricks(this, volinfo, dict, index, + hxlator_count); + break; + } + ret = (*hxlator_count); +out: + return ret; } 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; - int32_t status = 0; - char *op_errstr = NULL; - dict_t *dict = NULL; - dict_t *rsp_dict = NULL; - - GF_ASSERT (ctx); - - req_ctx = ctx; - - dict = req_ctx->dict; - - rsp_dict = glusterd_op_init_commit_rsp_dict (req_ctx->op); - if (NULL == rsp_dict) - return -1; - status = glusterd_op_commit_perform (req_ctx->op, dict, &op_errstr, - rsp_dict); - - if (status) { - gf_log ("", GF_LOG_ERROR, "Commit failed: %d", status); - } - - ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, - status, op_errstr, rsp_dict); - - glusterd_op_fini_ctx (req_ctx->op); - if (op_errstr && (strcmp (op_errstr, ""))) - GF_FREE (op_errstr); - - if (rsp_dict) - dict_unref (rsp_dict); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); +glusterd_bricks_select_heal_volume(dict_t *dict, char **op_errstr, + struct cds_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_SHD_OP_INVALID; + int hxlator_count = 0; + int index = 0; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "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_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, "%s", msg); + goto out; + } + + ret = dict_get_int32n(dict, "heal-op", SLEN("heal-op"), + (int32_t *)&heal_op); + if (ret || (heal_op == GF_SHD_OP_INVALID)) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "heal op invalid"); + goto out; + } + ret = glusterd_shd_select_brick_xlator(dict, heal_op, volinfo, &index, + &hxlator_count, rsp_dict); + if (ret < 0) { + goto out; + } + + if (!hxlator_count) + goto out; + if (hxlator_count == -1) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_XLATOR_COUNT_GET_FAIL, + "Could not determine the" + "translator count"); + ret = -1; + goto out; + } + + ret = dict_set_int32n(dict, "count", SLEN("count"), hxlator_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 = &(volinfo->shd.svc); + pending_node->type = GD_NODE_SHD; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } - return ret; +out: + gf_msg_debug(THIS->name, 0, "Returning ret %d", ret); + return ret; } static int -glusterd_op_ac_send_commit_failed (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; - glusterd_req_ctx_t *req_ctx = NULL; - dict_t *op_ctx = NULL; - - GF_ASSERT (ctx); - - req_ctx = ctx; - - op_ctx = glusterd_op_get_ctx (req_ctx->op); - - 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; - } +glusterd_bricks_select_rebalance_volume(dict_t *dict, char **op_errstr, + struct cds_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_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "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_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, "%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; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); - return ret; +out: + return ret; } static int -glusterd_op_sm_transition_state (glusterd_op_info_t *opinfo, - glusterd_op_sm_t *state, - glusterd_op_sm_event_type_t event_type) -{ - glusterd_conf_t *conf = NULL; - - GF_ASSERT (state); - GF_ASSERT (opinfo); - - conf = THIS->private; - GF_ASSERT (conf); - - (void) glusterd_sm_tr_log_transition_add (&conf->op_sm_log, - opinfo->state.state, - state[event_type].next_state, - event_type); - - opinfo->state.state = state[event_type].next_state; - return 0; -} - -int32_t -glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr, - dict_t *rsp_dict) -{ - int ret = -1; - - switch (op) { - case GD_OP_CREATE_VOLUME: - ret = glusterd_op_stage_create_volume (dict, op_errstr); - break; - - case GD_OP_START_VOLUME: - ret = glusterd_op_stage_start_volume (dict, op_errstr); - break; - - case GD_OP_STOP_VOLUME: - ret = glusterd_op_stage_stop_volume (dict, op_errstr); - break; - - case GD_OP_DELETE_VOLUME: - ret = glusterd_op_stage_delete_volume (dict, op_errstr); - break; - - case GD_OP_ADD_BRICK: - ret = glusterd_op_stage_add_brick (dict, op_errstr); - break; - - case GD_OP_REPLACE_BRICK: - ret = glusterd_op_stage_replace_brick (dict, op_errstr, - rsp_dict); - break; - - case GD_OP_SET_VOLUME: - ret = glusterd_op_stage_set_volume (dict, op_errstr); - break; - - case GD_OP_RESET_VOLUME: - ret = glusterd_op_stage_reset_volume (dict, 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); - break; - - case GD_OP_LOG_ROTATE: - ret = glusterd_op_stage_log_rotate (dict, op_errstr); - break; - - case GD_OP_SYNC_VOLUME: - ret = glusterd_op_stage_sync_volume (dict, op_errstr); - break; - - case GD_OP_GSYNC_SET: - ret = glusterd_op_stage_gsync_set (dict, op_errstr); - break; - - case GD_OP_PROFILE_VOLUME: - ret = glusterd_op_stage_stats_volume (dict, op_errstr); - break; - - case GD_OP_QUOTA: - ret = glusterd_op_stage_quota (dict, op_errstr); - break; - - case GD_OP_LOG_LEVEL: - ret = glusterd_op_stage_log_level (dict, op_errstr); - break; - - default: - gf_log ("", GF_LOG_ERROR, "Unknown op %d", - op); - } - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - - -int32_t -glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, - dict_t *rsp_dict) -{ - int ret = -1; - - switch (op) { - case GD_OP_CREATE_VOLUME: - ret = glusterd_op_create_volume (dict, op_errstr); - break; - - case GD_OP_START_VOLUME: - ret = glusterd_op_start_volume (dict, op_errstr); - break; - - case GD_OP_STOP_VOLUME: - ret = glusterd_op_stop_volume (dict); - break; - - case GD_OP_DELETE_VOLUME: - ret = glusterd_op_delete_volume (dict); - break; - - case GD_OP_ADD_BRICK: - ret = glusterd_op_add_brick (dict, op_errstr); - break; - - case GD_OP_REPLACE_BRICK: - ret = glusterd_op_replace_brick (dict, rsp_dict); - break; - - case GD_OP_SET_VOLUME: - ret = glusterd_op_set_volume (dict); - break; - - case GD_OP_RESET_VOLUME: - ret = glusterd_op_reset_volume (dict); - break; - - case GD_OP_REMOVE_BRICK: - ret = glusterd_op_remove_brick (dict); - break; - - case GD_OP_LOG_FILENAME: - ret = glusterd_op_log_filename (dict); - break; - - case GD_OP_LOG_ROTATE: - ret = glusterd_op_log_rotate (dict); - break; - - case GD_OP_SYNC_VOLUME: - ret = glusterd_op_sync_volume (dict, op_errstr, rsp_dict); - break; - - case GD_OP_GSYNC_SET: - ret = glusterd_op_gsync_set (dict, op_errstr, rsp_dict); - break; - - case GD_OP_PROFILE_VOLUME: - ret = glusterd_op_stats_volume (dict, op_errstr, - rsp_dict); - break; - - case GD_OP_QUOTA: - ret = glusterd_op_quota (dict, op_errstr); - break; +glusterd_bricks_select_status_volume(dict_t *dict, char **op_errstr, + struct cds_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; + glusterd_svc_t *svc = NULL; + + GF_ASSERT(dict); + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + ret = dict_get_int32n(dict, "cmd", SLEN("cmd"), &cmd); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "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: + case GF_CLI_STATUS_QUOTAD: + case GF_CLI_STATUS_SNAPD: + case GF_CLI_STATUS_BITD: + case GF_CLI_STATUS_SCRUB: + case GF_CLI_STATUS_CLIENT_LIST: + break; + default: + goto out; + } + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "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_strn(dict, "brick", SLEN("brick"), &brickname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get brick"); + goto out; + } + ret = glusterd_volume_brickinfo_get_by_brick(brickname, volinfo, + &brickinfo, _gf_false); + if (ret) + goto out; - case GD_OP_LOG_LEVEL: - ret = glusterd_op_log_level (dict); - break; + if (gf_uuid_compare(brickinfo->uuid, MY_UUID) || + !glusterd_is_brick_started(brickinfo)) + goto out; - default: - gf_log ("", GF_LOG_ERROR, "Unknown op %d", - op); - break; + 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; + cds_list_add_tail(&pending_node->list, selected); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} + ret = 0; +#ifdef BUILD_GNFS + } else if ((cmd & GF_CLI_STATUS_NFS) != 0) { + if (!priv->nfs_svc.online) { + ret = -1; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_NFS_SERVER_NOT_RUNNING, + "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_svc); + pending_node->type = GD_NODE_NFS; + pending_node->index = 0; + cds_list_add_tail(&pending_node->list, selected); -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); -} + ret = 0; +#endif + } else if ((cmd & GF_CLI_STATUS_SHD) != 0) { + svc = &(volinfo->shd.svc); + if (!svc->online) { + ret = -1; + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SELF_HEALD_DISABLED, + "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 = svc; + pending_node->type = GD_NODE_SHD; + pending_node->index = 0; + cds_list_add_tail(&pending_node->list, selected); -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); - - 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; -} + ret = 0; + } else if ((cmd & GF_CLI_STATUS_QUOTAD) != 0) { + if (!priv->quotad_svc.online) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_QUOTAD_NOT_RUNNING, + "Quotad is not " + "running"); + ret = -1; + 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->quotad_svc); + pending_node->type = GD_NODE_QUOTAD; + pending_node->index = 0; + cds_list_add_tail(&pending_node->list, selected); -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; + ret = 0; + } else if ((cmd & GF_CLI_STATUS_BITD) != 0) { + if (!priv->bitd_svc.online) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BITROT_NOT_RUNNING, + "Bitrot is not " + "running"); + ret = -1; + 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->bitd_svc); + pending_node->type = GD_NODE_BITD; + pending_node->index = 0; + cds_list_add_tail(&pending_node->list, selected); - GF_ASSERT (op_errstr); + ret = 0; + } else if ((cmd & GF_CLI_STATUS_SCRUB) != 0) { + if (!priv->scrub_svc.online) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SCRUBBER_NOT_RUNNING, + "Scrubber is not " + "running"); + ret = -1; + 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->scrub_svc); + pending_node->type = GD_NODE_SCRUB; + pending_node->index = 0; + cds_list_add_tail(&pending_node->list, selected); - switch (op) { - case GD_OP_PROFILE_VOLUME: - ret = glusterd_profile_volume_brick_rsp (brickinfo, rsp_dict, - op_ctx, op_errstr); - break; + ret = 0; + } else if ((cmd & GF_CLI_STATUS_SNAPD) != 0) { + if (!volinfo->snapd.svc.online) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAPD_NOT_RUNNING, + "snapd is not " + "running"); + ret = -1; + goto out; + } + pending_node = GF_CALLOC(1, sizeof(*pending_node), + gf_gld_mt_pending_node_t); + if (!pending_node) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY, + "failed to allocate " + "memory for pending node"); + ret = -1; + goto out; + } + + pending_node->node = (void *)(&volinfo->snapd); + pending_node->type = GD_NODE_SNAPD; + pending_node->index = 0; + cds_list_add_tail(&pending_node->list, selected); - default: - break; + ret = 0; + } else { + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + brick_index++; + if (gf_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_msg(THIS->name, GF_LOG_ERROR, ENOMEM, GD_MSG_NO_MEMORY, + "Unable to allocate memory"); + goto out; + } + pending_node->node = brickinfo; + pending_node->type = GD_NODE_BRICK; + pending_node->index = brick_index; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; } - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + } +out: + return ret; } static int -glusterd_bricks_select_stop_volume (dict_t *dict, char **op_errstr) -{ - int ret = 0; - int flags = 0; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - 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); +glusterd_bricks_select_scrub(dict_t *dict, char **op_errstr, + struct cds_list_head *selected) +{ + int ret = -1; + char *volname = NULL; + char msg[2048] = { + 0, + }; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_pending_node_t *pending_node = NULL; + + this = THIS; + priv = this->private; + GF_ASSERT(this); + GF_ASSERT(priv); + + GF_ASSERT(dict); + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Unable to get" + " volname"); + 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_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_VOL_NOT_FOUND, "%s", + msg); + goto out; + } + + if (!priv->scrub_svc.online) { + ret = 0; + snprintf(msg, sizeof(msg), "Scrubber daemon is not running"); - if (ret) - goto out; + gf_msg_debug(this->name, 0, "%s", msg); + 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), - gf_gld_mt_pending_node_t); - if (!pending_node) { - ret = -1; - goto out; - } else { - pending_node->node = brickinfo; - list_add_tail (&pending_node->list, &opinfo.pending_bricks); - pending_node = NULL; - } - } - } + 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->scrub_svc); + pending_node->type = GD_NODE_SCRUB; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; out: - return ret; + gf_msg_debug(this->name, 0, "Returning %d", ret); + return ret; } - +/* Select the bricks to send the barrier request to. + * This selects the bricks of the given volume which are present on this peer + * and are running + */ static int -glusterd_bricks_select_remove_brick (dict_t *dict, char **op_errstr) -{ - int ret = -1; - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - char *brick = NULL; - int32_t count = 0; - int32_t i = 1; - char key[256] = {0,}; - glusterd_pending_node_t *pending_node = 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 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 ("glusterd", GF_LOG_ERROR, "Unable to get brick"); - goto out; - } - - ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, - &brickinfo); - if (ret) - goto out; - if (glusterd_is_brick_started (brickinfo)) { - 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 = brickinfo; - list_add_tail (&pending_node->list, &opinfo.pending_bricks); - pending_node = NULL; - } - } - i++; - } +glusterd_bricks_select_barrier(dict_t *dict, struct cds_list_head *selected) +{ + int ret = -1; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_pending_node_t *pending_node = NULL; + + GF_ASSERT(dict); + + ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); + if (ret) { + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, + "Failed to get volname"); + goto out; + } + + ret = glusterd_volinfo_find(volname, &volinfo); + if (ret) { + gf_msg(THIS->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND, + "Failed to find volume %s", volname); + goto out; + } + + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (gf_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; + cds_list_add_tail(&pending_node->list, selected); + pending_node = NULL; + } out: - return ret; + gf_msg_debug(THIS->name, 0, "Returning %d", ret); + return ret; } static int -glusterd_bricks_select_profile_volume (dict_t *dict, char **op_errstr) +glusterd_op_ac_send_brick_op(glusterd_op_sm_event_t *event, void *ctx) { - int ret = -1; - char *volname = NULL; - char msg[2048] = {0,}; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *volinfo = NULL; - xlator_t *this = NULL; - int32_t stats_op = GF_CLI_STATS_NONE; - glusterd_brickinfo_t *brickinfo = NULL; - 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"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - snprintf (msg, sizeof (msg), "Volume %s does not exists", - volname); - - *op_errstr = gf_strdup (msg); - gf_log ("", GF_LOG_ERROR, "%s", msg); - goto out; - } - - ret = dict_get_int32 (dict, "op", &stats_op); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "volume profile op get failed"); - goto out; - } - - switch (stats_op) { - case GF_CLI_STATS_START: - case GF_CLI_STATS_STOP: - goto out; - break; - case GF_CLI_STATS_INFO: - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (glusterd_is_brick_started (brickinfo)) { - 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 = brickinfo; - list_add_tail (&pending_node->list, - &opinfo.pending_bricks); - pending_node = NULL; - } - } - } - break; + int ret = 0; + rpc_clnt_procedure_t *proc = NULL; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + glusterd_op_t op = GD_OP_NONE; + glusterd_req_ctx_t *req_ctx = NULL; + char *op_errstr = NULL; + gf_boolean_t free_req_ctx = _gf_false; - case GF_CLI_STATS_TOP: - ret = dict_get_str (dict, "brick", &brick); - if (!ret) { - ret = glusterd_volume_brickinfo_get_by_brick (brick, - volinfo, &brickinfo); - 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 = brickinfo; - list_add_tail (&pending_node->list, - &opinfo.pending_bricks); - pending_node = NULL; - goto out; - } - } - ret = 0; - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (glusterd_is_brick_started (brickinfo)) { - 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 = brickinfo; - list_add_tail (&pending_node->list, - &opinfo.pending_bricks); - pending_node = NULL; - } - } - } - break; + this = THIS; + priv = this->private; - default: - GF_ASSERT (0); - gf_log ("glusterd", GF_LOG_ERROR, "Invalid profile op: %d", - stats_op); - ret = -1; - goto out; - break; - } + if (ctx) { + req_ctx = ctx; + } else { + req_ctx = GF_CALLOC(1, sizeof(*req_ctx), gf_gld_mt_op_allack_ctx_t); + if (!req_ctx) + goto out; + free_req_ctx = _gf_true; + op = glusterd_op_get_op(); + req_ctx->op = op; + gf_uuid_copy(req_ctx->uuid, MY_UUID); + ret = glusterd_op_build_payload(&req_ctx->dict, &op_errstr, NULL); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_BRICK_OP_PAYLOAD_BUILD_FAIL, 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[GLUSTERD_BRICK_OP]; + if (proc->fn) { + ret = proc->fn(NULL, this, req_ctx); + if (ret) + goto out; + } + 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, &event->txn_id, + req_ctx); + } out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + if (ret && free_req_ctx) + GF_FREE(req_ctx); + gf_msg_debug(this->name, 0, "Returning with %d", ret); - return ret; + return ret; } static int -glusterd_op_ac_send_brick_op (glusterd_op_sm_event_t *event, void *ctx) -{ - int ret = 0; - rpc_clnt_procedure_t *proc = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - glusterd_op_t op = GD_OP_NONE; - glusterd_req_ctx_t *req_ctx = NULL; - - this = THIS; - priv = this->private; - - if (ctx) { - req_ctx = ctx; - } else { - req_ctx = GF_CALLOC (1, sizeof (*req_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?? - goto out; - } - - proc = &priv->gfs_mgmt->proctable[GD_MGMT_BRICK_OP]; - if (proc->fn) { - ret = proc->fn (NULL, this, req_ctx); - if (ret) - goto out; - } - - 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); - } - -out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); - - return ret; -} +glusterd_op_ac_rcvd_brick_op_acc(glusterd_op_sm_event_t *event, void *ctx) +{ + int ret = -1; + glusterd_op_brick_rsp_ctx_t *ev_ctx = NULL; + char *op_errstr = NULL; + glusterd_op_t op = GD_OP_NONE; + gd_node_type type = GD_NODE_NONE; + dict_t *op_ctx = NULL; + glusterd_req_ctx_t *req_ctx = NULL; + void *pending_entry = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO("glusterd", this, out); + GF_VALIDATE_OR_GOTO(this->name, event, out); + GF_VALIDATE_OR_GOTO(this->name, ctx, out); + ev_ctx = ctx; + GF_VALIDATE_OR_GOTO(this->name, ev_ctx, out); + + req_ctx = ev_ctx->commit_ctx; + GF_VALIDATE_OR_GOTO(this->name, req_ctx, out); + + 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, pending_entry); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_UNKNOWN_RESPONSE, + "unknown response received "); + ret = -1; + goto out; + } + if (opinfo.brick_pending_count > 0) + opinfo.brick_pending_count--; -static int -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; - dict_t *op_ctx = NULL; - gf_boolean_t free_errstr = _gf_true; - glusterd_req_ctx_t *req_ctx = NULL; - - GF_ASSERT (event); - GF_ASSERT (ctx); - ev_ctx = ctx; - - req_ctx = ev_ctx->commit_ctx; - GF_ASSERT (req_ctx); - - brickinfo = ev_ctx->brickinfo; - GF_ASSERT (brickinfo); - - ret = glusterd_remove_pending_entry (&opinfo.pending_bricks, brickinfo); - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "unknown response received " - "from %s:%s", brickinfo->hostname, brickinfo->path); - ret = -1; - free_errstr = _gf_true; - goto out; - } + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); - if (opinfo.brick_pending_count > 0) - opinfo.brick_pending_count--; - op = req_ctx->op; - op_ctx = glusterd_op_get_ctx (op); + glusterd_handle_node_rsp(req_ctx->dict, pending_entry, op, ev_ctx->rsp_dict, + op_ctx, &op_errstr, type); - glusterd_handle_brick_rsp (brickinfo, op, ev_ctx->rsp_dict, - op_ctx, &op_errstr); - if (opinfo.brick_pending_count > 0) - goto out; + 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); - - return ret; + if (ev_ctx && ev_ctx->rsp_dict) + dict_unref(ev_ctx->rsp_dict); + GF_FREE(ev_ctx); + gf_msg_debug(this ? this->name : "glusterd", 0, "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 cds_list_head *selected, dict_t *rsp_dict) { - int ret = 0; + int ret = 0; - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (op > GD_OP_NONE); - GF_ASSERT (op < GD_OP_MAX); + GF_ASSERT(dict); + GF_ASSERT(op_errstr); + GF_ASSERT(op > GD_OP_NONE); + GF_ASSERT(op < GD_OP_MAX); - switch (op) { + switch (op) { case GD_OP_STOP_VOLUME: - ret = glusterd_bricks_select_stop_volume (dict, op_errstr); - break; - + 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); - break; + 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); - break; - + 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_BARRIER: + ret = glusterd_bricks_select_barrier(dict, selected); + break; + case GD_OP_SNAP: + ret = glusterd_bricks_select_snap(dict, op_errstr, selected); + break; + case GD_OP_SCRUB_STATUS: + case GD_OP_SCRUB_ONDEMAND: + ret = glusterd_bricks_select_scrub(dict, op_errstr, selected); + break; default: - break; - } - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -glusterd_op_sm_t glusterd_op_state_default [] = { - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_NONE - {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_send_lock},//EVENT_START_LOCK - {GD_OP_STATE_LOCKED, glusterd_op_ac_lock}, //EVENT_LOCK - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_RCVD_ACC - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_ALL_ACC - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_STAGE_ACC - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_RCVD_RJT - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_STAGE_OP - {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {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_MAX + break; + } + + gf_msg_debug(THIS->name, 0, "Returning %d", ret); + + return ret; +} + +glusterd_op_sm_t glusterd_op_state_default[] = { + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_NONE + {GD_OP_STATE_LOCK_SENT, glusterd_op_ac_send_lock}, // EVENT_START_LOCK + {GD_OP_STATE_LOCKED, glusterd_op_ac_lock}, // EVENT_LOCK + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_RCVD_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_ALL_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_STAGE_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_RCVD_RJT + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_STAGE_OP + {GD_OP_STATE_DEFAULT, glusterd_op_ac_none}, // EVENT_COMMIT_OP + {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_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_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_LOCK_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK - {GD_OP_STATE_LOCK_SENT, 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_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_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_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_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 - {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_RCVD_RJT - {GD_OP_STATE_STAGED, glusterd_op_ac_stage_op}, //EVENT_STAGE_OP - {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {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_LOCKED, 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_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 + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, // EVENT_RCVD_RJT + {GD_OP_STATE_STAGED, glusterd_op_ac_stage_op}, // EVENT_STAGE_OP + {GD_OP_STATE_LOCKED, glusterd_op_ac_none}, // EVENT_COMMIT_OP + {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_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_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_STAGE_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK - {GD_OP_STATE_STAGE_OP_SENT, 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_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_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_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_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 - {GD_OP_STATE_STAGE_OP_FAILED, 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_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_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK - {GD_OP_STATE_STAGE_OP_FAILED, 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_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 + {GD_OP_STATE_STAGE_OP_FAILED, 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_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_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_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 - {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_RCVD_RJT - {GD_OP_STATE_STAGED, glusterd_op_ac_none}, //EVENT_STAGE_OP - {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_send_brick_op}, //EVENT_COMMIT_OP - {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_STAGED, 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_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 + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, // EVENT_RCVD_RJT + {GD_OP_STATE_STAGED, glusterd_op_ac_none}, // EVENT_STAGE_OP + {GD_OP_STATE_BRICK_COMMITTED, + glusterd_op_ac_send_brick_op}, // EVENT_COMMIT_OP + {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_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 - {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT - {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_COMMIT_OP_SENT, glusterd_op_ac_send_commit_op}, //EVENT_ALL_ACK - {GD_OP_STATE_BRICK_OP_SENT, 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_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 + {GD_OP_STATE_BRICK_OP_SENT, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_OP_FAILED, + glusterd_op_ac_brick_op_failed}, // EVENT_RCVD_RJT + {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_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_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 - {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT - {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_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK - {GD_OP_STATE_BRICK_OP_FAILED, 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_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 + {GD_OP_STATE_BRICK_OP_FAILED, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_OP_FAILED, + glusterd_op_ac_brick_op_failed}, // EVENT_RCVD_RJT + {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_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_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 - {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT - {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_STAGE_OP - {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {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_BRICK_COMMITTED, 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_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 + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_COMMIT_FAILED, + glusterd_op_ac_brick_op_failed}, // EVENT_RCVD_RJT + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, // EVENT_STAGE_OP + {GD_OP_STATE_BRICK_COMMITTED, glusterd_op_ac_none}, // EVENT_COMMIT_OP + {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_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 - {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_brick_op_failed}, //EVENT_RCVD_RJT - {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_STAGE_OP - {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {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_BRICK_COMMIT_FAILED, 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_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 + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_BRICK_COMMIT_FAILED, + glusterd_op_ac_brick_op_failed}, // EVENT_RCVD_RJT + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, // EVENT_STAGE_OP + {GD_OP_STATE_BRICK_COMMIT_FAILED, glusterd_op_ac_none}, // EVENT_COMMIT_OP + {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_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 - {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_commit_op_failed}, //EVENT_RCVD_RJT - {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_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_ALL_ACK - {GD_OP_STATE_COMMIT_OP_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_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 + {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_COMMIT_OP_FAILED, + glusterd_op_ac_commit_op_failed}, // EVENT_RCVD_RJT + {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_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_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 - {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, //EVENT_COMMIT_ACC - {GD_OP_STATE_COMMIT_OP_FAILED, glusterd_op_ac_commit_op_failed}, //EVENT_RCVD_RJT - {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_COMMIT_OP_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK - {GD_OP_STATE_COMMIT_OP_SENT, 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_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 + {GD_OP_STATE_UNLOCK_SENT, glusterd_op_ac_send_unlock}, // EVENT_COMMIT_ACC + {GD_OP_STATE_COMMIT_OP_FAILED, + glusterd_op_ac_commit_op_failed}, // EVENT_RCVD_RJT + {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_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_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 - {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_COMMIT_ACC - {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_RCVD_RJT - {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_STAGE_OP - {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, //EVENT_COMMIT_OP - {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_COMMITED, 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_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 + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, // EVENT_COMMIT_ACC + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, // EVENT_RCVD_RJT + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, // EVENT_STAGE_OP + {GD_OP_STATE_COMMITED, glusterd_op_ac_none}, // EVENT_COMMIT_OP + {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_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_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_UNLOCK_SENT, glusterd_op_ac_none}, //EVENT_ALL_ACK - {GD_OP_STATE_UNLOCK_SENT, 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_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_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_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_table [] = { - glusterd_op_state_default, - glusterd_op_state_lock_sent, - glusterd_op_state_locked, - glusterd_op_state_stage_op_sent, - glusterd_op_state_staged, - glusterd_op_state_commit_op_sent, - glusterd_op_state_committed, - glusterd_op_state_unlock_sent, - glusterd_op_state_stage_op_failed, - glusterd_op_state_commit_op_failed, - 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_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, glusterd_op_state_lock_sent, + glusterd_op_state_locked, glusterd_op_state_stage_op_sent, + glusterd_op_state_staged, glusterd_op_state_commit_op_sent, + glusterd_op_state_committed, glusterd_op_state_unlock_sent, + glusterd_op_state_stage_op_failed, glusterd_op_state_commit_op_failed, + 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_ack_drain}; + int -glusterd_op_sm_new_event (glusterd_op_sm_event_type_t event_type, - glusterd_op_sm_event_t **new_event) +glusterd_op_sm_new_event(glusterd_op_sm_event_type_t event_type, + glusterd_op_sm_event_t **new_event) { - glusterd_op_sm_event_t *event = NULL; + glusterd_op_sm_event_t *event = NULL; - GF_ASSERT (new_event); - GF_ASSERT (GD_OP_EVENT_NONE <= event_type && - GD_OP_EVENT_MAX > event_type); + GF_ASSERT(new_event); + GF_ASSERT(GD_OP_EVENT_NONE <= event_type && GD_OP_EVENT_MAX > event_type); - event = GF_CALLOC (1, sizeof (*event), gf_gld_mt_op_sm_event_t); + event = GF_CALLOC(1, sizeof(*event), gf_gld_mt_op_sm_event_t); - if (!event) - return -1; + if (!event) + return -1; - *new_event = event; - event->event = event_type; - INIT_LIST_HEAD (&event->list); + *new_event = event; + event->event = event_type; + CDS_INIT_LIST_HEAD(&event->list); - return 0; + return 0; } int -glusterd_op_sm_inject_event (glusterd_op_sm_event_type_t event_type, - void *ctx) +glusterd_op_sm_inject_event(glusterd_op_sm_event_type_t event_type, + uuid_t *txn_id, void *ctx) { - int32_t ret = -1; - glusterd_op_sm_event_t *event = NULL; + int32_t ret = -1; + glusterd_op_sm_event_t *event = NULL; - GF_ASSERT (event_type < GD_OP_EVENT_MAX && - event_type >= GD_OP_EVENT_NONE); + GF_ASSERT(event_type < GD_OP_EVENT_MAX && event_type >= GD_OP_EVENT_NONE); - ret = glusterd_op_sm_new_event (event_type, &event); + ret = glusterd_op_sm_new_event(event_type, &event); - if (ret) - goto out; + if (ret) + goto out; + + event->ctx = ctx; - event->ctx = ctx; + if (txn_id) + gf_uuid_copy(event->txn_id, *txn_id); - gf_log ("glusterd", GF_LOG_DEBUG, "Enqueuing event: '%s'", - glusterd_op_sm_event_name_get (event->event)); - list_add_tail (&event->list, &gd_op_sm_queue); + gf_msg_debug(THIS->name, 0, "Enqueue event: '%s'", + glusterd_op_sm_event_name_get(event->event)); + cds_list_add_tail(&event->list, &gd_op_sm_queue); out: - return ret; + return ret; +} + +void +glusterd_destroy_req_ctx(glusterd_req_ctx_t *ctx) +{ + if (!ctx) + return; + if (ctx->dict) + dict_unref(ctx->dict); + GF_FREE(ctx); } void -glusterd_destroy_req_ctx (glusterd_req_ctx_t *ctx) +glusterd_destroy_local_unlock_ctx(uuid_t *ctx) { - if (!ctx) - return; - if (ctx->dict) - dict_unref (ctx->dict); - GF_FREE (ctx); + if (!ctx) + return; + GF_FREE(ctx); } void -glusterd_destroy_op_event_ctx (glusterd_op_sm_event_t *event) +glusterd_destroy_op_event_ctx(glusterd_op_sm_event_t *event) { - if (!event) - return; + if (!event) + return; - switch (event->event) { + switch (event->event) { case GD_OP_EVENT_LOCK: case GD_OP_EVENT_UNLOCK: - glusterd_destroy_lock_ctx (event->ctx); - break; + glusterd_destroy_lock_ctx(event->ctx); + break; case GD_OP_EVENT_STAGE_OP: case GD_OP_EVENT_ALL_ACK: - glusterd_destroy_req_ctx (event->ctx); - break; + 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; - } + break; + } } int -glusterd_op_sm () -{ - glusterd_op_sm_event_t *event = NULL; - glusterd_op_sm_event_t *tmp = NULL; - int ret = -1; - 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; - - (void ) pthread_mutex_lock (&gd_op_sm_lock); - - while (!list_empty (&gd_op_sm_queue)) { - - list_for_each_entry_safe (event, tmp, &gd_op_sm_queue, list) { - - list_del_init (&event->list); - event_type = event->event; - gf_log ("", GF_LOG_DEBUG, "Dequeued event of type: '%s'", - glusterd_op_sm_event_name_get(event_type)); - - state = glusterd_op_state_table[opinfo.state.state]; - - GF_ASSERT (state); - - handler = state[event_type].handler; - GF_ASSERT (handler); - - ret = handler (event, event->ctx); - - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "handler returned: %d", ret); - glusterd_destroy_op_event_ctx (event); - GF_FREE (event); - continue; - } - - ret = glusterd_op_sm_transition_state (&opinfo, state, - event_type); - - if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, - "Unable to transition" - "state from '%s' to '%s'", - glusterd_op_sm_state_name_get(opinfo.state.state), - glusterd_op_sm_state_name_get(state[event_type].next_state)); - (void ) pthread_mutex_unlock (&gd_op_sm_lock); - return ret; - } +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; + glusterd_conf_t *priv = NULL; + + this = THIS; + GF_ASSERT(this); + priv = this->private; + GF_ASSERT(priv); + + ret = synclock_trylock(&gd_op_sm_lock); + if (ret) { + lock_err = errno; + gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_LOCK_FAIL, + "lock failed due to %s", strerror(lock_err)); + goto lock_failed; + } + + while (!cds_list_empty(&gd_op_sm_queue)) { + cds_list_for_each_entry_safe(event, tmp, &gd_op_sm_queue, list) + { + cds_list_del_init(&event->list); + event_type = event->event; + gf_msg_debug(this->name, 0, + "Dequeued event of " + "type: '%s'", + glusterd_op_sm_event_name_get(event_type)); + + gf_msg_debug(this->name, 0, "transaction ID = %s", + uuid_utoa(event->txn_id)); + + ret = glusterd_get_txn_opinfo(&event->txn_id, &txn_op_info); + if (ret) { + gf_msg_callingfn(this->name, GF_LOG_ERROR, 0, + GD_MSG_TRANS_OPINFO_GET_FAIL, + "Unable to get transaction " + "opinfo for transaction ID :" + "%s", + uuid_utoa(event->txn_id)); + 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); + + handler = state[event_type].handler; + GF_ASSERT(handler); + + ret = handler(event, event->ctx); + + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_HANDLER_RETURNED, + "handler returned: %d", ret); + glusterd_destroy_op_event_ctx(event); + GF_FREE(event); + continue; + } + + ret = glusterd_op_sm_transition_state(&opinfo, state, event_type); + + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_EVENT_STATE_TRANSITION_FAIL, + "Unable to transition" + "state from '%s' to '%s'", + glusterd_op_sm_state_name_get(opinfo.state.state), + glusterd_op_sm_state_name_get( + state[event_type].next_state)); + (void)synclock_unlock(&gd_op_sm_lock); + return ret; + } - glusterd_destroy_op_event_ctx (event); - GF_FREE (event); + 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_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_TRANS_OPINFO_CLEAR_FAIL, + "Unable to clear " + "transaction's opinfo"); + } else { + if ((priv->op_version < GD_OP_VERSION_6_0) || + !(event_type == GD_OP_EVENT_STAGE_OP && + opinfo.state.state == GD_OP_STATE_STAGED && + opinfo.skip_locking)) { + ret = glusterd_set_txn_opinfo(&event->txn_id, &opinfo); + if (ret) + gf_msg(this->name, GF_LOG_ERROR, 0, + GD_MSG_TRANS_OPINFO_SET_FAIL, + "Unable to set " + "transaction's opinfo"); } - } - - - (void ) pthread_mutex_unlock (&gd_op_sm_lock); - ret = 0; - - return ret; -} - -int32_t -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; - - return 0; - -} - -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; + glusterd_destroy_op_event_ctx(event); + GF_FREE(event); } + } - if ( i == GD_OP_MAX) - ret = -1; - else - ret = i; + (void)synclock_unlock(&gd_op_sm_lock); + ret = 0; - return ret; +lock_failed: + return ret; } - int32_t -glusterd_op_set_cli_op (glusterd_op_t op) +glusterd_op_set_op(glusterd_op_t op) { + GF_ASSERT(op < GD_OP_MAX); + GF_ASSERT(op > GD_OP_NONE); - int32_t ret = 0; - - ret = pthread_mutex_trylock (&opinfo.lock); - - if (ret) - goto out; - - opinfo.cli_op = op; + opinfo.op = op; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; + return 0; } int32_t -glusterd_op_set_req (rpcsvc_request_t *req) +glusterd_op_get_op() { - - GF_ASSERT (req); - opinfo.req = req; - return 0; -} - -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; - - return 0; - + return opinfo.op; } int32_t -glusterd_op_init_ctx (glusterd_op_t op) +glusterd_op_set_req(rpcsvc_request_t *req) { - int ret = 0; - dict_t *dict = NULL; - - if (_gf_false == glusterd_need_brick_op (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; + GF_ASSERT(req); + opinfo.req = req; + return 0; } - - int32_t -glusterd_op_fini_ctx (glusterd_op_t op) +glusterd_op_clear_op(glusterd_op_t op) { - dict_t *dict = NULL; + opinfo.op = GD_OP_NONE; - 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; + return 0; } - - int32_t -glusterd_op_free_ctx (glusterd_op_t op, void *ctx, gf_boolean_t ctx_free) +glusterd_op_free_ctx(glusterd_op_t op, void *ctx) { - - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - if (ctx && ctx_free) { - switch (op) { - case GD_OP_CREATE_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: - case GD_OP_START_VOLUME: - case GD_OP_RESET_VOLUME: - case GD_OP_GSYNC_SET: - case GD_OP_QUOTA: - case GD_OP_PROFILE_VOLUME: - case GD_OP_LOG_LEVEL: - dict_unref (ctx); - break; - case GD_OP_DELETE_VOLUME: - GF_FREE (ctx); - break; - default: - GF_ASSERT (0); - break; - } + 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_ROTATE: + case GD_OP_SYNC_VOLUME: + case GD_OP_SET_VOLUME: + case GD_OP_START_VOLUME: + case GD_OP_RESET_VOLUME: + 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: + case GD_OP_MAX_OPVERSION: + dict_unref(ctx); + break; + default: + GF_ASSERT(0); + break; } - return 0; + } + glusterd_op_reset_ctx(); + return 0; } void * -glusterd_op_get_ctx (glusterd_op_t op) +glusterd_op_get_ctx() { - 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; - - 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) -{ - GF_ASSERT (op < GD_OP_MAX); - GF_ASSERT (op > GD_OP_NONE); - - return opinfo.ctx_free[op]; - + return opinfo.op_ctx; } int -glusterd_op_sm_init () -{ - INIT_LIST_HEAD (&gd_op_sm_queue); - 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) +glusterd_op_sm_init() { - 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; + CDS_INIT_LIST_HEAD(&gd_op_sm_queue); + synclock_init(&gd_op_sm_lock, SYNC_LOCK_DEFAULT); + return 0; } |
