diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-mgmt.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt.c | 2011 |
1 files changed, 0 insertions, 2011 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.c b/xlators/mgmt/glusterd/src/glusterd-mgmt.c deleted file mode 100644 index 1c99f92e114..00000000000 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt.c +++ /dev/null @@ -1,2011 +0,0 @@ -/* - Copyright (c) 2013-2014 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. -*/ -/* rpc related syncops */ -#include "rpc-clnt.h" -#include "protocol-common.h" -#include "xdr-generic.h" -#include "glusterd1-xdr.h" -#include "glusterd-syncop.h" - -#include "glusterd.h" -#include "glusterd-utils.h" -#include "glusterd-locks.h" -#include "glusterd-mgmt.h" -#include "glusterd-op-sm.h" -#include "glusterd-volgen.h" -#include "glusterd-store.h" - -extern struct rpc_clnt_program gd_mgmt_v3_prog; - - -void -gd_mgmt_v3_collate_errors (struct syncargs *args, int op_ret, int op_errno, - char *op_errstr, int op_code, - glusterd_peerinfo_t *peerinfo, u_char *uuid) -{ - char *peer_str = NULL; - char err_str[PATH_MAX] = "Please check log file for details."; - char op_err[PATH_MAX] = ""; - int32_t len = -1; - xlator_t *this = NULL; - int is_operrstr_blk = 0; - char *err_string = NULL; - char *cli_err_str = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (args); - GF_ASSERT (uuid); - - if (op_ret) { - args->op_ret = op_ret; - args->op_errno = op_errno; - - if (peerinfo) - peer_str = peerinfo->hostname; - else - peer_str = uuid_utoa (uuid); - - is_operrstr_blk = (op_errstr && strcmp (op_errstr, "")); - err_string = (is_operrstr_blk) ? op_errstr : err_str; - - switch (op_code) { - case GLUSTERD_MGMT_V3_LOCK: - { - len = snprintf (op_err, sizeof(op_err), - "Locking failed " - "on %s. %s", peer_str, - err_string); - break; - } - case GLUSTERD_MGMT_V3_PRE_VALIDATE: - { - len = snprintf (op_err, sizeof(op_err), - "Pre Validation failed " - "on %s. %s", peer_str, - err_string); - break; - } - case GLUSTERD_MGMT_V3_BRICK_OP: - { - len = snprintf (op_err, sizeof(op_err), - "Brick ops failed " - "on %s. %s", peer_str, - err_string); - break; - } - case GLUSTERD_MGMT_V3_COMMIT: - { - len = snprintf (op_err, sizeof(op_err), - "Commit failed" - " on %s. %s", peer_str, - err_string); - break; - } - case GLUSTERD_MGMT_V3_POST_VALIDATE: - { - len = snprintf (op_err, sizeof(op_err), - "Post Validation failed " - "on %s. %s", peer_str, - err_string); - break; - } - case GLUSTERD_MGMT_V3_UNLOCK: - { - len = snprintf (op_err, sizeof(op_err), - "Unlocking failed " - "on %s. %s", peer_str, - err_string); - break; - } - default : - len = snprintf (op_err, sizeof(op_err), - "Unknown error! " - "on %s. %s", peer_str, - err_string); - } - - cli_err_str = ((is_operrstr_blk) ? op_errstr : op_err); - - if (args->errstr) { - len = snprintf (err_str, sizeof(err_str), - "%s\n%s", args->errstr, - cli_err_str); - GF_FREE (args->errstr); - args->errstr = NULL; - } else - len = snprintf (err_str, sizeof(err_str), - "%s", cli_err_str); - - gf_log (this->name, GF_LOG_ERROR, "%s", op_err); - args->errstr = gf_strdup (err_str); - } - - return; -} - -int32_t -gd_mgmt_v3_pre_validate_fn (glusterd_op_t op, dict_t *dict, - char **op_errstr, dict_t *rsp_dict) -{ - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (rsp_dict); - - switch (op) { - case GD_OP_SNAP: - ret = glusterd_snapshot_prevalidate (dict, op_errstr, - rsp_dict); - - if (ret) { - gf_log (this->name, GF_LOG_WARNING, - "Snapshot Prevalidate Failed"); - goto out; - } - - break; - - default: - break; - } - - ret = 0; -out: - gf_log (this->name, GF_LOG_DEBUG, "OP = %d. Returning %d", op, ret); - return ret; -} - -int32_t -gd_mgmt_v3_brick_op_fn (glusterd_op_t op, dict_t *dict, - char **op_errstr, dict_t *rsp_dict) -{ - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (rsp_dict); - - switch (op) { - case GD_OP_SNAP: - { - ret = glusterd_snapshot_brickop (dict, op_errstr, rsp_dict); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "snapshot brickop " - "failed"); - goto out; - } - break; - } - default: - break; - } - - ret = 0; -out: - gf_log (this->name, GF_LOG_TRACE, "OP = %d. Returning %d", op, ret); - return ret; -} - -int32_t -gd_mgmt_v3_commit_fn (glusterd_op_t op, dict_t *dict, - char **op_errstr, dict_t *rsp_dict) -{ - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (rsp_dict); - - switch (op) { - case GD_OP_SNAP: - { - ret = glusterd_snapshot (dict, op_errstr, rsp_dict); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, - "Snapshot Commit Failed"); - goto out; - } - break; - } - default: - break; - } - - ret = 0; -out: - gf_log (this->name, GF_LOG_DEBUG, "OP = %d. Returning %d", op, ret); - return ret; -} - -int32_t -gd_mgmt_v3_post_validate_fn (glusterd_op_t op, int32_t op_ret, dict_t *dict, - char **op_errstr, dict_t *rsp_dict) -{ - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (rsp_dict); - - switch (op) { - case GD_OP_SNAP: - { - ret = glusterd_snapshot_postvalidate (dict, op_ret, - op_errstr, - rsp_dict); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, - "postvalidate operation failed"); - goto out; - } - break; - } - default: - break; - } - - ret = 0; - -out: - gf_log (this->name, GF_LOG_TRACE, "OP = %d. Returning %d", op, ret); - return ret; -} - -int32_t -gd_mgmt_v3_lock_cbk_fn (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - int32_t ret = -1; - struct syncargs *args = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - gd1_mgmt_v3_lock_rsp rsp = {{0},}; - call_frame_t *frame = NULL; - int32_t op_ret = -1; - int32_t op_errno = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (myframe); - - /* Even though the lock command has failed, while collating the errors - (gd_mgmt_v3_collate_errors), args->op_ret and args->op_errno will be - used. @args is obtained from frame->local. So before checking the - status of the request and going out if its a failure, args should be - set to frame->local. Otherwise, while collating args will be NULL. - This applies to other phases such as prevalidate, brickop, commit and - postvalidate also. - */ - frame = myframe; - args = frame->local; - peerinfo = frame->cookie; - frame->local = NULL; - frame->cookie = NULL; - - if (-1 == req->rpc_status) { - op_errno = ENOTCONN; - goto out; - } - - if (!iov) { - gf_log (this->name, GF_LOG_ERROR, "iov is NULL"); - op_errno = EINVAL; - goto out; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gd1_mgmt_v3_lock_rsp); - if (ret < 0) - goto out; - - uuid_copy (args->uuid, rsp.uuid); - - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - -out: - gd_mgmt_v3_collate_errors (args, op_ret, op_errno, NULL, - GLUSTERD_MGMT_V3_LOCK, - peerinfo, rsp.uuid); - if (rsp.dict.dict_val) - free (rsp.dict.dict_val); - STACK_DESTROY (frame->root); - synctask_barrier_wake(args); - return 0; -} - -int32_t -gd_mgmt_v3_lock_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - return glusterd_big_locked_cbk (req, iov, count, myframe, - gd_mgmt_v3_lock_cbk_fn); -} - -int -gd_mgmt_v3_lock (glusterd_op_t op, dict_t *op_ctx, - glusterd_peerinfo_t *peerinfo, - struct syncargs *args, uuid_t my_uuid, - uuid_t recv_uuid) -{ - gd1_mgmt_v3_lock_req req = {{0},}; - glusterd_conf_t *conf = THIS->private; - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (op_ctx); - GF_ASSERT (peerinfo); - GF_ASSERT (args); - - ret = dict_allocate_and_serialize (op_ctx, - &req.dict.dict_val, - &req.dict.dict_len); - if (ret) - goto out; - - uuid_copy (req.uuid, my_uuid); - req.op = op; - synclock_unlock (&conf->big_lock); - ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, peerinfo, - &gd_mgmt_v3_prog, - GLUSTERD_MGMT_V3_LOCK, - gd_mgmt_v3_lock_cbk, - (xdrproc_t) xdr_gd1_mgmt_v3_lock_req); - synclock_lock (&conf->big_lock); -out: - GF_FREE (req.dict.dict_val); - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int -glusterd_mgmt_v3_initiate_lockdown (glusterd_op_t op, dict_t *dict, - char **op_errstr, int npeers, - gf_boolean_t *is_acquired, - struct list_head *peers) -{ - char *volname = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - int32_t ret = -1; - int32_t peer_cnt = 0; - struct syncargs args = {0}; - uuid_t peer_uuid = {0}; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - GF_ASSERT (is_acquired); - - /* Trying to acquire multiple mgmt_v3 locks on local node */ - ret = glusterd_multiple_mgmt_v3_lock (dict, MY_UUID); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to acquire mgmt_v3 locks on localhost"); - goto out; - } - - *is_acquired = _gf_true; - - if (!npeers) { - ret = 0; - goto out; - } - - /* Sending mgmt_v3 lock req to other nodes in the cluster */ - gd_syncargs_init (&args, NULL); - synctask_barrier_init((&args)); - peer_cnt = 0; - list_for_each_local_xaction_peers (peerinfo, peers) { - gd_mgmt_v3_lock (op, dict, peerinfo, &args, - MY_UUID, peer_uuid); - peer_cnt++; - } - gd_synctask_barrier_wait((&args), peer_cnt); - - if (args.errstr) - *op_errstr = gf_strdup (args.errstr); - - ret = args.op_ret; - - gf_log (this->name, GF_LOG_DEBUG, "Sent lock op req for %s " - "to %d peers. Returning %d", gd_op_list[op], peer_cnt, ret); -out: - if (ret) { - if (*op_errstr) - gf_log (this->name, GF_LOG_ERROR, "%s", - *op_errstr); - - if (volname) - ret = gf_asprintf (op_errstr, - "Another transaction is in progress " - "for %s. Please try again after " - "sometime.", volname); - else - ret = gf_asprintf (op_errstr, - "Another transaction is in progress " - "Please try again after sometime."); - - if (ret == -1) - *op_errstr = NULL; - - ret = -1; - } - - return ret; -} - -int -glusterd_pre_validate_aggr_rsp_dict (glusterd_op_t op, - dict_t *aggr, dict_t *rsp) -{ - int32_t ret = 0; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (aggr); - GF_ASSERT (rsp); - - switch (op) { - case GD_OP_SNAP: - ret = glusterd_snap_pre_validate_use_rsp_dict (aggr, rsp); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to aggregate prevalidate " - "response dictionaries."); - goto out; - } - break; - default: - ret = -1; - gf_log (this->name, GF_LOG_ERROR, "Invalid op (%s)", - gd_op_list[op]); - - break; - } -out: - return ret; -} - -int32_t -gd_mgmt_v3_pre_validate_cbk_fn (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - int32_t ret = -1; - struct syncargs *args = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - gd1_mgmt_v3_pre_val_rsp rsp = {{0},}; - call_frame_t *frame = NULL; - int32_t op_ret = -1; - int32_t op_errno = -1; - dict_t *rsp_dict = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (myframe); - - frame = myframe; - args = frame->local; - peerinfo = frame->cookie; - frame->local = NULL; - frame->cookie = NULL; - - if (-1 == req->rpc_status) { - op_errno = ENOTCONN; - goto out; - } - - if (!iov) { - gf_log (this->name, GF_LOG_ERROR, "iov is NULL"); - op_errno = EINVAL; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gd1_mgmt_v3_pre_val_rsp); - if (ret < 0) - goto out; - - if (rsp.dict.dict_len) { - /* Unserialize the dictionary */ - rsp_dict = dict_new (); - - ret = dict_unserialize (rsp.dict.dict_val, - rsp.dict.dict_len, - &rsp_dict); - if (ret < 0) { - free (rsp.dict.dict_val); - goto out; - } else { - rsp_dict->extra_stdfree = rsp.dict.dict_val; - } - } - - uuid_copy (args->uuid, rsp.uuid); - pthread_mutex_lock (&args->lock_dict); - { - ret = glusterd_pre_validate_aggr_rsp_dict (rsp.op, args->dict, - rsp_dict); - } - pthread_mutex_unlock (&args->lock_dict); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s", - "Failed to aggregate response from " - " node/brick"); - if (!rsp.op_ret) - op_ret = ret; - else { - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - } - } else { - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - } - -out: - if (rsp_dict) - dict_unref (rsp_dict); - - gd_mgmt_v3_collate_errors (args, op_ret, op_errno, rsp.op_errstr, - GLUSTERD_MGMT_V3_PRE_VALIDATE, - peerinfo, rsp.uuid); - - if (rsp.op_errstr) - free (rsp.op_errstr); - - STACK_DESTROY (frame->root); - synctask_barrier_wake(args); - return 0; -} - -int32_t -gd_mgmt_v3_pre_validate_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - return glusterd_big_locked_cbk (req, iov, count, myframe, - gd_mgmt_v3_pre_validate_cbk_fn); -} - -int -gd_mgmt_v3_pre_validate_req (glusterd_op_t op, dict_t *op_ctx, - glusterd_peerinfo_t *peerinfo, - struct syncargs *args, uuid_t my_uuid, - uuid_t recv_uuid) -{ - int32_t ret = -1; - gd1_mgmt_v3_pre_val_req req = {{0},}; - glusterd_conf_t *conf = THIS->private; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (op_ctx); - GF_ASSERT (peerinfo); - GF_ASSERT (args); - - ret = dict_allocate_and_serialize (op_ctx, - &req.dict.dict_val, - &req.dict.dict_len); - if (ret) - goto out; - - uuid_copy (req.uuid, my_uuid); - req.op = op; - synclock_unlock (&conf->big_lock); - ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, peerinfo, - &gd_mgmt_v3_prog, - GLUSTERD_MGMT_V3_PRE_VALIDATE, - gd_mgmt_v3_pre_validate_cbk, - (xdrproc_t) xdr_gd1_mgmt_v3_pre_val_req); - synclock_lock (&conf->big_lock); -out: - GF_FREE (req.dict.dict_val); - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int -glusterd_mgmt_v3_pre_validate (glusterd_op_t op, dict_t *req_dict, - char **op_errstr, int npeers, - struct list_head *peers) -{ - int32_t ret = -1; - int32_t peer_cnt = 0; - dict_t *rsp_dict = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - struct syncargs args = {0}; - uuid_t peer_uuid = {0}; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req_dict); - GF_ASSERT (op_errstr); - - rsp_dict = dict_new (); - if (!rsp_dict) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to create response dictionary"); - goto out; - } - - /* Pre Validation on local node */ - ret = gd_mgmt_v3_pre_validate_fn (op, req_dict, op_errstr, - rsp_dict); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Pre Validation failed for " - "operation %s on local node", - gd_op_list[op]); - - if (*op_errstr == NULL) { - ret = gf_asprintf (op_errstr, - "Pre-validation failed " - "on localhost. Please " - "check log file for details"); - if (ret == -1) - *op_errstr = NULL; - - ret = -1; - } - goto out; - } - - ret = glusterd_pre_validate_aggr_rsp_dict (op, req_dict, - rsp_dict); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s", - "Failed to aggregate response from " - " node/brick"); - goto out; - } - - dict_unref (rsp_dict); - rsp_dict = NULL; - - if (!npeers) { - ret = 0; - goto out; - } - - /* Sending Pre Validation req to other nodes in the cluster */ - gd_syncargs_init (&args, req_dict); - synctask_barrier_init((&args)); - peer_cnt = 0; - list_for_each_local_xaction_peers (peerinfo, peers) { - gd_mgmt_v3_pre_validate_req (op, req_dict, peerinfo, &args, - MY_UUID, peer_uuid); - peer_cnt++; - } - gd_synctask_barrier_wait((&args), peer_cnt); - - if (args.op_ret) { - gf_log (this->name, GF_LOG_ERROR, - "Pre Validation failed on peers"); - - if (args.errstr) - *op_errstr = gf_strdup (args.errstr); - } - - ret = args.op_ret; - - gf_log (this->name, GF_LOG_DEBUG, "Sent pre valaidation req for %s " - "to %d peers. Returning %d", gd_op_list[op], peer_cnt, ret); -out: - return ret; -} - -int -glusterd_mgmt_v3_build_payload (dict_t **req, char **op_errstr, dict_t *dict, - glusterd_op_t op) -{ - int32_t ret = -1; - dict_t *req_dict = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (op_errstr); - GF_ASSERT (dict); - - req_dict = dict_new (); - if (!req_dict) - goto out; - - switch (op) { - case GD_OP_SNAP: - dict_copy (dict, req_dict); - break; - default: - break; - } - - *req = req_dict; - ret = 0; -out: - return ret; -} - -int32_t -gd_mgmt_v3_brick_op_cbk_fn (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - int32_t ret = -1; - struct syncargs *args = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - gd1_mgmt_v3_brick_op_rsp rsp = {{0},}; - call_frame_t *frame = NULL; - int32_t op_ret = -1; - int32_t op_errno = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (myframe); - - frame = myframe; - args = frame->local; - peerinfo = frame->cookie; - frame->local = NULL; - frame->cookie = NULL; - - /* If the operation failed, then iov can be NULL. So better check the - status of the operation and then worry about iov (if the status of - the command is success) - */ - if (-1 == req->rpc_status) { - op_errno = ENOTCONN; - goto out; - } - - if (!iov) { - gf_log (this->name, GF_LOG_ERROR, "iov is NULL"); - op_errno = EINVAL; - goto out; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gd1_mgmt_v3_brick_op_rsp); - if (ret < 0) - goto out; - - uuid_copy (args->uuid, rsp.uuid); - - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - -out: - gd_mgmt_v3_collate_errors (args, op_ret, op_errno, rsp.op_errstr, - GLUSTERD_MGMT_V3_BRICK_OP, - peerinfo, rsp.uuid); - - if (rsp.op_errstr) - free (rsp.op_errstr); - - if (rsp.dict.dict_val) - free (rsp.dict.dict_val); - - STACK_DESTROY (frame->root); - synctask_barrier_wake(args); - return 0; -} - -int32_t -gd_mgmt_v3_brick_op_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - return glusterd_big_locked_cbk (req, iov, count, myframe, - gd_mgmt_v3_brick_op_cbk_fn); -} - -int -gd_mgmt_v3_brick_op_req (glusterd_op_t op, dict_t *op_ctx, - glusterd_peerinfo_t *peerinfo, - struct syncargs *args, uuid_t my_uuid, - uuid_t recv_uuid) -{ - int32_t ret = -1; - gd1_mgmt_v3_brick_op_req req = {{0},}; - glusterd_conf_t *conf = THIS->private; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (op_ctx); - GF_ASSERT (peerinfo); - GF_ASSERT (args); - - ret = dict_allocate_and_serialize (op_ctx, - &req.dict.dict_val, - &req.dict.dict_len); - if (ret) - goto out; - - uuid_copy (req.uuid, my_uuid); - req.op = op; - synclock_unlock (&conf->big_lock); - ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, peerinfo, - &gd_mgmt_v3_prog, - GLUSTERD_MGMT_V3_BRICK_OP, - gd_mgmt_v3_brick_op_cbk, - (xdrproc_t) xdr_gd1_mgmt_v3_brick_op_req); - synclock_lock (&conf->big_lock); -out: - GF_FREE (req.dict.dict_val); - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int -glusterd_mgmt_v3_brick_op (glusterd_op_t op, dict_t *req_dict, - char **op_errstr, int npeers, - struct list_head *peers) -{ - int32_t ret = -1; - int32_t peer_cnt = 0; - dict_t *rsp_dict = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - struct syncargs args = {0}; - uuid_t peer_uuid = {0}; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req_dict); - GF_ASSERT (op_errstr); - - rsp_dict = dict_new (); - if (!rsp_dict) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to create response dictionary"); - goto out; - } - - /* Perform brick op on local node */ - ret = gd_mgmt_v3_brick_op_fn (op, req_dict, op_errstr, - rsp_dict); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Brick ops failed for " - "operation %s on local node", - gd_op_list[op]); - - if (*op_errstr == NULL) { - ret = gf_asprintf (op_errstr, - "Brick ops failed " - "on localhost. Please " - "check log file for details"); - if (ret == -1) - *op_errstr = NULL; - - ret = -1; - } - goto out; - } - - dict_unref (rsp_dict); - rsp_dict = NULL; - - if (!npeers) { - ret = 0; - goto out; - } - - /* Sending brick op req to other nodes in the cluster */ - gd_syncargs_init (&args, NULL); - synctask_barrier_init((&args)); - peer_cnt = 0; - list_for_each_local_xaction_peers (peerinfo, peers) { - gd_mgmt_v3_brick_op_req (op, req_dict, peerinfo, &args, - MY_UUID, peer_uuid); - peer_cnt++; - } - gd_synctask_barrier_wait((&args), peer_cnt); - - if (args.op_ret) { - gf_log (this->name, GF_LOG_ERROR, - "Brick ops failed on peers"); - - if (args.errstr) - *op_errstr = gf_strdup (args.errstr); - } - - ret = args.op_ret; - - gf_log (this->name, GF_LOG_DEBUG, "Sent brick op req for %s " - "to %d peers. Returning %d", gd_op_list[op], peer_cnt, ret); -out: - return ret; -} - -int32_t -gd_mgmt_v3_commit_cbk_fn (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - int32_t ret = -1; - struct syncargs *args = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - gd1_mgmt_v3_commit_rsp rsp = {{0},}; - call_frame_t *frame = NULL; - int32_t op_ret = -1; - int32_t op_errno = -1; - dict_t *rsp_dict = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (myframe); - - frame = myframe; - args = frame->local; - peerinfo = frame->cookie; - frame->local = NULL; - frame->cookie = NULL; - - if (-1 == req->rpc_status) { - op_errno = ENOTCONN; - goto out; - } - - if (!iov) { - gf_log (this->name, GF_LOG_ERROR, "iov is NULL"); - op_errno = EINVAL; - goto out; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gd1_mgmt_v3_commit_rsp); - if (ret < 0) - goto out; - - if (rsp.dict.dict_len) { - /* Unserialize the dictionary */ - rsp_dict = dict_new (); - - ret = dict_unserialize (rsp.dict.dict_val, - rsp.dict.dict_len, - &rsp_dict); - if (ret < 0) { - free (rsp.dict.dict_val); - goto out; - } else { - rsp_dict->extra_stdfree = rsp.dict.dict_val; - } - } - - uuid_copy (args->uuid, rsp.uuid); - pthread_mutex_lock (&args->lock_dict); - { - ret = glusterd_syncop_aggr_rsp_dict (rsp.op, args->dict, - rsp_dict); - } - pthread_mutex_unlock (&args->lock_dict); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s", - "Failed to aggregate response from " - " node/brick"); - if (!rsp.op_ret) - op_ret = ret; - else { - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - } - } else { - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - } - -out: - if (rsp_dict) - dict_unref (rsp_dict); - - gd_mgmt_v3_collate_errors (args, op_ret, op_errno, rsp.op_errstr, - GLUSTERD_MGMT_V3_COMMIT, - peerinfo, rsp.uuid); - - STACK_DESTROY (frame->root); - synctask_barrier_wake(args); - return 0; -} - -int32_t -gd_mgmt_v3_commit_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - return glusterd_big_locked_cbk (req, iov, count, myframe, - gd_mgmt_v3_commit_cbk_fn); -} - -int -gd_mgmt_v3_commit_req (glusterd_op_t op, dict_t *op_ctx, - glusterd_peerinfo_t *peerinfo, - struct syncargs *args, uuid_t my_uuid, - uuid_t recv_uuid) -{ - int32_t ret = -1; - gd1_mgmt_v3_commit_req req = {{0},}; - glusterd_conf_t *conf = THIS->private; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (op_ctx); - GF_ASSERT (peerinfo); - GF_ASSERT (args); - - ret = dict_allocate_and_serialize (op_ctx, - &req.dict.dict_val, - &req.dict.dict_len); - if (ret) - goto out; - - uuid_copy (req.uuid, my_uuid); - req.op = op; - synclock_unlock (&conf->big_lock); - ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, peerinfo, - &gd_mgmt_v3_prog, - GLUSTERD_MGMT_V3_COMMIT, - gd_mgmt_v3_commit_cbk, - (xdrproc_t) xdr_gd1_mgmt_v3_commit_req); - synclock_lock (&conf->big_lock); -out: - GF_FREE (req.dict.dict_val); - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int -glusterd_mgmt_v3_commit (glusterd_op_t op, dict_t *op_ctx, - dict_t *req_dict, char **op_errstr, - int npeers, struct list_head *peers) -{ - int32_t ret = -1; - int32_t peer_cnt = 0; - dict_t *rsp_dict = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - struct syncargs args = {0}; - uuid_t peer_uuid = {0}; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (op_ctx); - GF_ASSERT (req_dict); - GF_ASSERT (op_errstr); - - rsp_dict = dict_new (); - if (!rsp_dict) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to create response dictionary"); - goto out; - } - - /* Commit on local node */ - ret = gd_mgmt_v3_commit_fn (op, req_dict, op_errstr, - rsp_dict); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Commit failed for " - "operation %s on local node", - gd_op_list[op]); - - if (*op_errstr == NULL) { - ret = gf_asprintf (op_errstr, - "Commit failed " - "on localhost. Please " - "check log file for details."); - if (ret == -1) - *op_errstr = NULL; - - ret = -1; - } - goto out; - } - - ret = glusterd_syncop_aggr_rsp_dict (op, op_ctx, - rsp_dict); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s", - "Failed to aggregate response from " - " node/brick"); - goto out; - } - - dict_unref (rsp_dict); - rsp_dict = NULL; - - if (!npeers) { - ret = 0; - goto out; - } - - /* Sending commit req to other nodes in the cluster */ - gd_syncargs_init (&args, op_ctx); - synctask_barrier_init((&args)); - peer_cnt = 0; - list_for_each_local_xaction_peers (peerinfo, peers) { - gd_mgmt_v3_commit_req (op, req_dict, peerinfo, &args, - MY_UUID, peer_uuid); - peer_cnt++; - } - gd_synctask_barrier_wait((&args), peer_cnt); - - if (args.op_ret) { - gf_log (this->name, GF_LOG_ERROR, - "Commit failed on peers"); - - if (args.errstr) - *op_errstr = gf_strdup (args.errstr); - } - - ret = args.op_ret; - - gf_log (this->name, GF_LOG_DEBUG, "Sent commit req for %s to %d " - "peers. Returning %d", gd_op_list[op], peer_cnt, ret); -out: - return ret; -} - -int32_t -gd_mgmt_v3_post_validate_cbk_fn (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - int32_t ret = -1; - struct syncargs *args = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - gd1_mgmt_v3_post_val_rsp rsp = {{0},}; - call_frame_t *frame = NULL; - int32_t op_ret = -1; - int32_t op_errno = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (myframe); - - frame = myframe; - args = frame->local; - peerinfo = frame->cookie; - frame->local = NULL; - frame->cookie = NULL; - - if (-1 == req->rpc_status) { - op_errno = ENOTCONN; - goto out; - } - - if (!iov) { - gf_log (this->name, GF_LOG_ERROR, "iov is NULL"); - op_errno = EINVAL; - goto out; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gd1_mgmt_v3_post_val_rsp); - if (ret < 0) - goto out; - - uuid_copy (args->uuid, rsp.uuid); - - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - -out: - gd_mgmt_v3_collate_errors (args, op_ret, op_errno, rsp.op_errstr, - GLUSTERD_MGMT_V3_POST_VALIDATE, - peerinfo, rsp.uuid); - if (rsp.op_errstr) - free (rsp.op_errstr); - - if (rsp.dict.dict_val) - free (rsp.dict.dict_val); - STACK_DESTROY (frame->root); - synctask_barrier_wake(args); - return 0; -} - -int32_t -gd_mgmt_v3_post_validate_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - return glusterd_big_locked_cbk (req, iov, count, myframe, - gd_mgmt_v3_post_validate_cbk_fn); -} - -int -gd_mgmt_v3_post_validate_req (glusterd_op_t op, int32_t op_ret, dict_t *op_ctx, - glusterd_peerinfo_t *peerinfo, - struct syncargs *args, uuid_t my_uuid, - uuid_t recv_uuid) -{ - int32_t ret = -1; - gd1_mgmt_v3_post_val_req req = {{0},}; - glusterd_conf_t *conf = THIS->private; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (op_ctx); - GF_ASSERT (peerinfo); - GF_ASSERT (args); - - ret = dict_allocate_and_serialize (op_ctx, - &req.dict.dict_val, - &req.dict.dict_len); - if (ret) - goto out; - - uuid_copy (req.uuid, my_uuid); - req.op = op; - req.op_ret = op_ret; - synclock_unlock (&conf->big_lock); - ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, peerinfo, - &gd_mgmt_v3_prog, - GLUSTERD_MGMT_V3_POST_VALIDATE, - gd_mgmt_v3_post_validate_cbk, - (xdrproc_t) xdr_gd1_mgmt_v3_post_val_req); - synclock_lock (&conf->big_lock); -out: - GF_FREE (req.dict.dict_val); - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int -glusterd_mgmt_v3_post_validate (glusterd_op_t op, int32_t op_ret, dict_t *dict, - dict_t *req_dict, char **op_errstr, int npeers, - struct list_head *peers) -{ - int32_t ret = -1; - int32_t peer_cnt = 0; - dict_t *rsp_dict = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - struct syncargs args = {0}; - uuid_t peer_uuid = {0}; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_VALIDATE_OR_GOTO (this->name, req_dict, out); - GF_ASSERT (op_errstr); - - rsp_dict = dict_new (); - if (!rsp_dict) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to create response dictionary"); - goto out; - } - - /* Copy the contents of dict like missed snaps info to req_dict */ - dict_copy (dict, req_dict); - - /* Post Validation on local node */ - ret = gd_mgmt_v3_post_validate_fn (op, op_ret, req_dict, op_errstr, - rsp_dict); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Post Validation failed for " - "operation %s on local node", - gd_op_list[op]); - - if (*op_errstr == NULL) { - ret = gf_asprintf (op_errstr, - "Post-validation failed " - "on localhost. Please check " - "log file for details"); - if (ret == -1) - *op_errstr = NULL; - - ret = -1; - } - goto out; - } - - dict_unref (rsp_dict); - rsp_dict = NULL; - - if (!npeers) { - ret = 0; - goto out; - } - - /* Sending Post Validation req to other nodes in the cluster */ - gd_syncargs_init (&args, req_dict); - synctask_barrier_init((&args)); - peer_cnt = 0; - list_for_each_local_xaction_peers (peerinfo, peers) { - gd_mgmt_v3_post_validate_req (op, op_ret, req_dict, peerinfo, - &args, MY_UUID, peer_uuid); - peer_cnt++; - } - gd_synctask_barrier_wait((&args), peer_cnt); - - if (args.op_ret) { - gf_log (this->name, GF_LOG_ERROR, - "Post Validation failed on peers"); - - if (args.errstr) - *op_errstr = gf_strdup (args.errstr); - } - - ret = args.op_ret; - - gf_log (this->name, GF_LOG_DEBUG, "Sent post valaidation req for %s " - "to %d peers. Returning %d", gd_op_list[op], peer_cnt, ret); -out: - return ret; -} - -int32_t -gd_mgmt_v3_unlock_cbk_fn (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - int32_t ret = -1; - struct syncargs *args = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - gd1_mgmt_v3_unlock_rsp rsp = {{0},}; - call_frame_t *frame = NULL; - int32_t op_ret = -1; - int32_t op_errno = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (myframe); - - frame = myframe; - args = frame->local; - peerinfo = frame->cookie; - frame->local = NULL; - frame->cookie = NULL; - - if (-1 == req->rpc_status) { - op_errno = ENOTCONN; - goto out; - } - - if (!iov) { - gf_log (this->name, GF_LOG_ERROR, "iov is NULL"); - op_errno = EINVAL; - goto out; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gd1_mgmt_v3_unlock_rsp); - if (ret < 0) - goto out; - - uuid_copy (args->uuid, rsp.uuid); - - op_ret = rsp.op_ret; - op_errno = rsp.op_errno; - -out: - gd_mgmt_v3_collate_errors (args, op_ret, op_errno, NULL, - GLUSTERD_MGMT_V3_UNLOCK, - peerinfo, rsp.uuid); - if (rsp.dict.dict_val) - free (rsp.dict.dict_val); - STACK_DESTROY (frame->root); - synctask_barrier_wake(args); - return 0; -} - -int32_t -gd_mgmt_v3_unlock_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - return glusterd_big_locked_cbk (req, iov, count, myframe, - gd_mgmt_v3_unlock_cbk_fn); -} - -int -gd_mgmt_v3_unlock (glusterd_op_t op, dict_t *op_ctx, - glusterd_peerinfo_t *peerinfo, - struct syncargs *args, uuid_t my_uuid, - uuid_t recv_uuid) -{ - int32_t ret = -1; - gd1_mgmt_v3_unlock_req req = {{0},}; - glusterd_conf_t *conf = THIS->private; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (op_ctx); - GF_ASSERT (peerinfo); - GF_ASSERT (args); - - ret = dict_allocate_and_serialize (op_ctx, - &req.dict.dict_val, - &req.dict.dict_len); - if (ret) - goto out; - - uuid_copy (req.uuid, my_uuid); - req.op = op; - synclock_unlock (&conf->big_lock); - ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, peerinfo, - &gd_mgmt_v3_prog, - GLUSTERD_MGMT_V3_UNLOCK, - gd_mgmt_v3_unlock_cbk, - (xdrproc_t) xdr_gd1_mgmt_v3_unlock_req); - synclock_lock (&conf->big_lock); -out: - GF_FREE (req.dict.dict_val); - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int -glusterd_mgmt_v3_release_peer_locks (glusterd_op_t op, - dict_t *dict, int32_t op_ret, - char **op_errstr, int npeers, - gf_boolean_t is_acquired, - struct list_head *peers) -{ - int32_t ret = -1; - int32_t peer_cnt = 0; - uuid_t peer_uuid = {0}; - xlator_t *this = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - struct syncargs args = {0}; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (op_errstr); - - /* If the lock has not been held during this - * transaction, do not send unlock requests */ - if (!is_acquired) - goto out; - - if (!npeers) { - ret = 0; - goto out; - } - - /* Sending mgmt_v3 unlock req to other nodes in the cluster */ - gd_syncargs_init (&args, NULL); - synctask_barrier_init((&args)); - peer_cnt = 0; - list_for_each_local_xaction_peers (peerinfo, peers) { - gd_mgmt_v3_unlock (op, dict, peerinfo, &args, - MY_UUID, peer_uuid); - peer_cnt++; - } - gd_synctask_barrier_wait((&args), peer_cnt); - - if (args.op_ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unlock failed on peers"); - - if (!op_ret && args.errstr) - *op_errstr = gf_strdup (args.errstr); - } - - ret = args.op_ret; - - gf_log (this->name, GF_LOG_DEBUG, "Sent unlock op req for %s " - "to %d peers. Returning %d", gd_op_list[op], peer_cnt, ret); - -out: - return ret; -} - -int32_t -glusterd_mgmt_v3_initiate_all_phases (rpcsvc_request_t *req, glusterd_op_t op, - dict_t *dict) -{ - int32_t ret = -1; - int32_t op_ret = -1; - int32_t npeers = 0; - dict_t *req_dict = NULL; - dict_t *tmp_dict = NULL; - glusterd_conf_t *conf = NULL; - char *op_errstr = NULL; - xlator_t *this = NULL; - gf_boolean_t is_acquired = _gf_false; - uuid_t *originator_uuid = NULL; - struct list_head xaction_peers = {0,}; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (dict); - conf = this->private; - GF_ASSERT (conf); - - INIT_LIST_HEAD (&xaction_peers); - npeers = gd_build_local_xaction_peers_list (&conf->peers, - &xaction_peers, op); - if (npeers == -1) { - gf_log (this->name, GF_LOG_ERROR, "building local peers list " - "failed"); - goto rsp; - } - - /* Save the MY_UUID as the originator_uuid. This originator_uuid - * will be used by is_origin_glusterd() to determine if a node - * is the originator node for a command. */ - originator_uuid = GF_CALLOC (1, sizeof(uuid_t), - gf_common_mt_uuid_t); - if (!originator_uuid) { - ret = -1; - goto out; - } - - uuid_copy (*originator_uuid, MY_UUID); - ret = dict_set_bin (dict, "originator_uuid", - originator_uuid, sizeof (uuid_t)); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set originator_uuid."); - goto out; - } - - /* Marking the operation as complete synctasked */ - ret = dict_set_int32 (dict, "is_synctasked", _gf_true); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set synctasked flag."); - goto out; - } - - /* Use a copy at local unlock as cli response will be sent before - * the unlock and the volname in the dict might be removed */ - tmp_dict = dict_new(); - if (!tmp_dict) { - gf_log (this->name, GF_LOG_ERROR, "Unable to create dict"); - goto out; - } - dict_copy (dict, tmp_dict); - - /* LOCKDOWN PHASE - Acquire mgmt_v3 locks */ - ret = glusterd_mgmt_v3_initiate_lockdown (op, dict, &op_errstr, - npeers, &is_acquired, - &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "mgmt_v3 lockdown failed."); - goto out; - } - - /* BUILD PAYLOAD */ - ret = glusterd_mgmt_v3_build_payload (&req_dict, &op_errstr, dict, op); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, LOGSTR_BUILD_PAYLOAD, - gd_op_list[op]); - if (op_errstr == NULL) - gf_asprintf (&op_errstr, OPERRSTR_BUILD_PAYLOAD); - goto out; - } - - /* PRE-COMMIT VALIDATE PHASE */ - ret = glusterd_mgmt_v3_pre_validate (op, req_dict, - &op_errstr, npeers, - &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Pre Validation Failed"); - goto out; - } - - /* COMMIT OP PHASE */ - ret = glusterd_mgmt_v3_commit (op, dict, req_dict, - &op_errstr, npeers, &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Commit Op Failed"); - goto out; - } - - /* POST-COMMIT VALIDATE PHASE */ - /* As of now, post_validate is not handling any other - commands other than snapshot. So as of now, I am - sending 0 (op_ret as 0). - */ - ret = glusterd_mgmt_v3_post_validate (op, 0, dict, req_dict, - &op_errstr, npeers, - &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Post Validation Failed"); - goto out; - } - - ret = 0; -out: - op_ret = ret; - /* UNLOCK PHASE FOR PEERS*/ - (void) glusterd_mgmt_v3_release_peer_locks (op, dict, - op_ret, &op_errstr, - npeers, is_acquired, - &xaction_peers); - - /* LOCAL VOLUME(S) UNLOCK */ - if (is_acquired) { - /* Trying to release multiple mgmt_v3 locks */ - ret = glusterd_multiple_mgmt_v3_unlock (tmp_dict, MY_UUID); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to release mgmt_v3 locks on localhost"); - op_ret = ret; - } - } -rsp: - /* SEND CLI RESPONSE */ - glusterd_op_send_cli_response (op, op_ret, 0, req, dict, op_errstr); - - gd_cleanup_local_xaction_peers_list (&xaction_peers); - - if (req_dict) - dict_unref (req_dict); - - if (tmp_dict) - dict_unref (tmp_dict); - - if (op_errstr) { - GF_FREE (op_errstr); - op_errstr = NULL; - } - - return 0; -} - -int32_t -glusterd_set_barrier_value (dict_t *dict, char *option) -{ - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_volinfo_t *vol = NULL; - char *volname = NULL; - - this = THIS; - GF_ASSERT (this); - - GF_ASSERT (dict); - GF_ASSERT (option); - - /* TODO : Change this when we support multiple volume. - * As of now only snapshot of single volume is supported, - * Hence volname1 is directly fetched - */ - ret = dict_get_str (dict, "volname1", &volname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Volname not present in " - "dict"); - goto out; - } - - ret = glusterd_volinfo_find (volname, &vol); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Volume %s not found ", - volname); - goto out; - } - - ret = dict_set_dynstr_with_alloc (dict, "barrier", option); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to set barrier op " - "in request dictionary"); - goto out; - } - - ret = dict_set_dynstr_with_alloc (vol->dict, "features.barrier", - option); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to set barrier op " - "in volume option dict"); - goto out; - } - - gd_update_volume_op_versions (vol); - - ret = glusterd_create_volfiles (vol); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to create volfiles"); - goto out; - } - - ret = glusterd_store_volinfo (vol, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - -out: - gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -int32_t -glusterd_mgmt_v3_initiate_snap_phases (rpcsvc_request_t *req, glusterd_op_t op, - dict_t *dict) -{ - int32_t ret = -1; - int32_t op_ret = -1; - int32_t npeers = 0; - dict_t *req_dict = NULL; - dict_t *tmp_dict = NULL; - glusterd_conf_t *conf = NULL; - char *op_errstr = NULL; - xlator_t *this = NULL; - gf_boolean_t is_acquired = _gf_false; - uuid_t *originator_uuid = NULL; - gf_boolean_t success = _gf_false; - char *cli_errstr = NULL; - struct list_head xaction_peers = {0,}; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (req); - GF_ASSERT (dict); - conf = this->private; - GF_ASSERT (conf); - - INIT_LIST_HEAD (&xaction_peers); - npeers = gd_build_local_xaction_peers_list (&conf->peers, - &xaction_peers, op); - if (npeers == -1) { - gf_log (this->name, GF_LOG_ERROR, "building local peers list " - "failed"); - goto rsp; - } - - /* Save the MY_UUID as the originator_uuid. This originator_uuid - * will be used by is_origin_glusterd() to determine if a node - * is the originator node for a command. */ - originator_uuid = GF_CALLOC (1, sizeof(uuid_t), - gf_common_mt_uuid_t); - if (!originator_uuid) { - ret = -1; - goto out; - } - - uuid_copy (*originator_uuid, MY_UUID); - ret = dict_set_bin (dict, "originator_uuid", - originator_uuid, sizeof (uuid_t)); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set originator_uuid."); - goto out; - } - - /* Marking the operation as complete synctasked */ - ret = dict_set_int32 (dict, "is_synctasked", _gf_true); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set synctasked flag."); - goto out; - } - - /* Use a copy at local unlock as cli response will be sent before - * the unlock and the volname in the dict might be removed */ - tmp_dict = dict_new(); - if (!tmp_dict) { - gf_log (this->name, GF_LOG_ERROR, "Unable to create dict"); - goto out; - } - dict_copy (dict, tmp_dict); - - /* LOCKDOWN PHASE - Acquire mgmt_v3 locks */ - ret = glusterd_mgmt_v3_initiate_lockdown (op, dict, &op_errstr, - npeers, &is_acquired, - &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "mgmt_v3 lockdown failed."); - goto out; - } - - /* BUILD PAYLOAD */ - ret = glusterd_mgmt_v3_build_payload (&req_dict, &op_errstr, dict, op); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, LOGSTR_BUILD_PAYLOAD, - gd_op_list[op]); - if (op_errstr == NULL) - gf_asprintf (&op_errstr, OPERRSTR_BUILD_PAYLOAD); - goto out; - } - - /* PRE-COMMIT VALIDATE PHASE */ - ret = glusterd_mgmt_v3_pre_validate (op, req_dict, - &op_errstr, npeers, &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Pre Validation Failed"); - goto out; - } - - /* quorum check of the volume is done here */ - ret = glusterd_snap_quorum_check (req_dict, _gf_false, &op_errstr, - &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, - "Volume quorum check failed"); - goto out; - } - - /* Set the operation type as pre, so that differentiation can be - * made whether the brickop is sent during pre-commit or post-commit - */ - ret = dict_set_dynstr_with_alloc (req_dict, "operation-type", "pre"); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to set " - "operation-type in dictionary"); - goto out; - } - - ret = glusterd_mgmt_v3_brick_op (op, req_dict, - &op_errstr, npeers, &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Brick Ops Failed"); - goto unbarrier; - } - - /* COMMIT OP PHASE */ - /* TODO: As of now, the plan is to do quorum check before sending the - commit fop and if the quorum succeeds, then commit is sent to all - the other glusterds. - snap create functionality now creates the in memory and on disk - objects for the snapshot (marking them as incomplete), takes the lvm - snapshot and then updates the status of the in memory and on disk - snap objects as complete. Suppose one of the glusterds goes down - after taking the lvm snapshot, but before updating the snap object, - then treat it as a snapshot create failure and trigger cleanup. - i.e the number of commit responses received by the originator - glusterd shold be the same as the number of peers it has sent the - request to (i.e npeers variable). If not, then originator glusterd - will initiate cleanup in post-validate fop. - Question: What if one of the other glusterds goes down as explained - above and along with it the originator glusterd also goes down? - Who will initiate the cleanup? - */ - ret = dict_set_int32 (req_dict, "cleanup", 1); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to set dict"); - goto unbarrier; - } - - ret = glusterd_mgmt_v3_commit (op, dict, req_dict, - &op_errstr, npeers, &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Commit Op Failed"); - /* If the main op fails, we should save the error string. - Because, op_errstr will be used for unbarrier and - unlock ops also. We might lose the actual error that - caused the failure. - */ - cli_errstr = op_errstr; - op_errstr = NULL; - goto unbarrier; - } - - success = _gf_true; -unbarrier: - /* Set the operation type as post, so that differentiation can be - * made whether the brickop is sent during pre-commit or post-commit - */ - ret = dict_set_dynstr_with_alloc (req_dict, "operation-type", "post"); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to set " - "operation-type in dictionary"); - goto out; - } - - ret = glusterd_mgmt_v3_brick_op (op, req_dict, - &op_errstr, npeers, &xaction_peers); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Brick Ops Failed"); - goto out; - } - - /*Do a quorum check if the commit phase is successful*/ - if (success) { - //quorum check of the snapshot volume - ret = glusterd_snap_quorum_check (dict, _gf_true, &op_errstr, - &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, - "Snapshot Volume quorum check failed"); - goto out; - } - } - - ret = 0; - -out: - op_ret = ret; - - if (success == _gf_false) - op_ret = -1; - - /* POST-COMMIT VALIDATE PHASE */ - ret = glusterd_mgmt_v3_post_validate (op, op_ret, dict, req_dict, - &op_errstr, npeers, - &xaction_peers); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Post Validation Failed"); - op_ret = -1; - } - - /* UNLOCK PHASE FOR PEERS*/ - (void) glusterd_mgmt_v3_release_peer_locks (op, dict, - op_ret, &op_errstr, - npeers, is_acquired, - &xaction_peers); - - /* If the commit op (snapshot taking) failed, then the error is stored - in cli_errstr and unbarrier is called. Suppose, if unbarrier also - fails, then the error happened in unbarrier is logged and freed. - The error happened in commit op, which is stored in cli_errstr - is sent to cli. - */ - if (cli_errstr) { - GF_FREE (op_errstr); - op_errstr = NULL; - op_errstr = cli_errstr; - } - - /* LOCAL VOLUME(S) UNLOCK */ - if (is_acquired) { - /* Trying to release multiple mgmt_v3 locks */ - ret = glusterd_multiple_mgmt_v3_unlock (tmp_dict, MY_UUID); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to release mgmt_v3 locks on localhost"); - op_ret = ret; - } - } -rsp: - /* SEND CLI RESPONSE */ - glusterd_op_send_cli_response (op, op_ret, 0, req, dict, op_errstr); - - gd_cleanup_local_xaction_peers_list (&xaction_peers); - - if (req_dict) - dict_unref (req_dict); - - if (tmp_dict) - dict_unref (tmp_dict); - - if (op_errstr) { - GF_FREE (op_errstr); - op_errstr = NULL; - } - - return 0; -} |
