diff options
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 207 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 3 |
2 files changed, 200 insertions, 10 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index ad6731e626c..15c40f3e468 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -36,6 +36,7 @@ #include "glusterd-volgen.h" #include "glusterd-pmap.h" #include "glusterfs-acl.h" +#include "glusterd-syncop.h" #include "xdr-generic.h" #include <sys/resource.h> @@ -587,6 +588,8 @@ glusterd_volinfo_delete (glusterd_volinfo_t *volinfo) if (volinfo->gsync_slaves) dict_unref (volinfo->gsync_slaves); GF_FREE (volinfo->logdir); + if (volinfo->rebal.dict) + dict_unref (volinfo->rebal.dict); gf_store_handle_destroy (volinfo->quota_conf_shandle); @@ -3322,6 +3325,50 @@ glusterd_delete_stale_volume (glusterd_volinfo_t *stale_volinfo, return 0; } +/* This function updates the rebalance information of the new volinfo using the + * information from the old volinfo. + */ +int +gd_check_and_update_rebalance_info (glusterd_volinfo_t *old_volinfo, + glusterd_volinfo_t *new_volinfo) +{ + int ret = -1; + glusterd_rebalance_t *old = NULL; + glusterd_rebalance_t *new = NULL; + + GF_ASSERT (old_volinfo); + GF_ASSERT (new_volinfo); + + old = &(old_volinfo->rebal); + new = &(new_volinfo->rebal); + /* If the task-id's don't match, the old volinfo task is stale and + * should be cleaned up + */ + if (uuid_compare (old->rebalance_id, new->rebalance_id)) { + (void)gd_stop_rebalance_process (old_volinfo); + goto out; + } + + /* If the tasks match, copy the status and other information of the + * rebalance process from old_volinfo to new_volinfo + */ + new->defrag_status = old->defrag_status; + new->rebalance_files = old->rebalance_files; + new->rebalance_data = old->rebalance_data; + new->lookedup_files = old->lookedup_files; + new->skipped_files = old->skipped_files; + new->rebalance_failures = old->rebalance_failures; + new->rebalance_time = old->rebalance_time; + new->defrag = old->defrag; + new->dict = (old->dict ? dict_ref (old->dict) : NULL); + + /* glusterd_rebalance_t.{op, id, defrag_cmd} are copied during volume + * import + */ +out: + return ret; +} + int32_t glusterd_import_friend_volume (dict_t *vols, size_t count) { @@ -3344,6 +3391,8 @@ glusterd_import_friend_volume (dict_t *vols, size_t count) ret = glusterd_volinfo_find (new_volinfo->volname, &old_volinfo); if (0 == ret) { + (void) gd_check_and_update_rebalance_info (old_volinfo, + new_volinfo); (void) glusterd_delete_stale_volume (old_volinfo, new_volinfo); } @@ -6693,22 +6742,44 @@ int glusterd_volume_defrag_restart (glusterd_volinfo_t *volinfo, char *op_errstr, size_t len, int cmd, defrag_cbk_fn_t cbk) { - glusterd_conf_t *priv = NULL; - char pidfile[PATH_MAX]; - int ret = -1; - pid_t pid; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + char pidfile[PATH_MAX] = {0,}; + int ret = -1; + pid_t pid = 0; - priv = THIS->private; + this = THIS; + GF_ASSERT (this); + + priv = this->private; if (!priv) return ret; - GLUSTERD_GET_DEFRAG_PID_FILE(pidfile, volinfo, priv); - - if (!gf_is_service_running (pidfile, &pid)) { + /* Don't start the rebalance process if the stautus is already + * completed, stopped or failed. If the status is started, check if + * there is an existing process already and connect to it. If not, then + * start the rebalance process + */ + switch (volinfo->rebal.defrag_status) { + case GF_DEFRAG_STATUS_COMPLETE: + case GF_DEFRAG_STATUS_STOPPED: + case GF_DEFRAG_STATUS_FAILED: + break; + case GF_DEFRAG_STATUS_STARTED: + GLUSTERD_GET_DEFRAG_PID_FILE(pidfile, volinfo, priv); + if (gf_is_service_running (pidfile, &pid)) { + glusterd_rebalance_rpc_create (volinfo); + break; + } + case GF_DEFRAG_STATUS_NOT_STARTED: glusterd_handle_defrag_start (volinfo, op_errstr, len, cmd, cbk, volinfo->rebal.op); - } else { - glusterd_rebalance_rpc_create (volinfo); + break; + default: + gf_log (this->name, GF_LOG_ERROR, "Unknown defrag status (%d)." + "Not starting rebalance process for %s.", + volinfo->rebal.defrag_status, volinfo->volname); + break; } return ret; @@ -9071,3 +9142,119 @@ glusterd_remove_auxiliary_mount (char *volname) rmdir (mountdir); return ret; } + +/* Just a minimal callback function to which logs if the request was successfull + * or not + */ +int +_gd_stop_rebalance_process_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *call_frame) +{ + xlator_t *this = NULL; + struct syncargs *args = NULL; + gd1_mgmt_brick_op_rsp rsp = {0,}; + int ret = -1; + call_frame_t *frame = NULL; + + this = THIS; + GF_ASSERT (this); + + frame = call_frame; + args = frame->local; + frame->local = NULL; + + if (-1 == req->rpc_status) { + gf_log (this->name, GF_LOG_WARNING, "Failed to stop rebalance " + "process."); + goto out; + } + + ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gd1_mgmt_brick_op_rsp); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, "Failed to decode stop " + "rebalance process response."); + goto out; + } + + gf_log (this->name, GF_LOG_INFO, "Stopping rebalance process was %s.", + (rsp.op_ret ? "unsuccessful" : "successful")); + +out: + if ((rsp.op_errstr) && (strcmp (rsp.op_errstr, "") != 0)) + free (rsp.op_errstr); + free (rsp.output.output_val); + + STACK_DESTROY (frame->root); + __wake (args); + + return 0; +} + +int +gd_stop_rebalance_process_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *call_frame) +{ + return glusterd_big_locked_cbk (req, iov, count, call_frame, + _gd_stop_rebalance_process_cbk); +} +/* Stops the rebalance process of the given volume, gracefully + */ +int +gd_stop_rebalance_process (glusterd_volinfo_t *volinfo) +{ + int ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + gd1_mgmt_brick_op_req *req = NULL; + dict_t *req_dict = NULL; + char *name = NULL; + struct syncargs args = {0,}; + + GF_ASSERT (volinfo); + + this = THIS; + GF_ASSERT (this); + + conf = this->private; + GF_ASSERT (conf); + + req = GF_CALLOC (1, sizeof (*req), gf_gld_mt_mop_brick_req_t); + if (!req) { + ret = -1; + goto out; + } + + req->op = GLUSTERD_BRICK_XLATOR_DEFRAG; + + ret = gf_asprintf(&name, "%s-dht", volinfo->volname); + if (ret < 0) + goto out; + req->name = name; + + req_dict = dict_new(); + if (!req_dict) { + ret = -1; + goto out; + } + + ret = dict_set_int32 (req_dict, "rebalance-command", + GF_DEFRAG_CMD_STOP); + if (ret) + goto out; + + ret = dict_allocate_and_serialize (req_dict, &req->input.input_val, + &req->input.input_len); + if (ret) + goto out; + + GD_SYNCOP (volinfo->rebal.defrag->rpc, (&args), NULL, + gd_stop_rebalance_process_cbk, req, conf->gfs_mgmt, req->op, + (xdrproc_t)xdr_gd1_mgmt_brick_op_req); +out: + + GF_FREE (name); + GF_FREE (req); + dict_unref (req_dict); + + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 7917fba197e..970b1f8a638 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -621,4 +621,7 @@ glusterd_remove_auxiliary_mount (char *volname); gf_boolean_t glusterd_status_has_tasks (int cmd); + +int +gd_stop_rebalance_process (glusterd_volinfo_t *volinfo); #endif |