diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-replace-brick.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-replace-brick.c | 1470 |
1 files changed, 760 insertions, 710 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c index 48db4ab3c..54b830870 100644 --- a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c +++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2011 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 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 - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ + Copyright (c) 2011-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" @@ -25,6 +15,7 @@ #include "common-utils.h" #include "cli1-xdr.h" #include "xdr-generic.h" +#include "glusterfs.h" #include "glusterd.h" #include "glusterd-op-sm.h" #include "glusterd-store.h" @@ -35,8 +26,52 @@ #include <signal.h> +#define GLUSTERD_GET_RB_MNTPT(path, len, volinfo) \ + snprintf (path, len, \ + DEFAULT_VAR_RUN_DIRECTORY"/%s-"RB_CLIENT_MOUNTPOINT, \ + volinfo->volname); + +extern uuid_t global_txn_id; + int -glusterd_handle_replace_brick (rpcsvc_request_t *req) +glusterd_get_replace_op_str (gf1_cli_replace_op op, char *op_str) +{ + int ret = -1; + + if (!op_str) + goto out; + + switch (op) { + case GF_REPLACE_OP_START: + strcpy (op_str, "start"); + break; + case GF_REPLACE_OP_COMMIT: + strcpy (op_str, "commit"); + break; + case GF_REPLACE_OP_PAUSE: + strcpy (op_str, "pause"); + break; + case GF_REPLACE_OP_ABORT: + strcpy (op_str, "abort"); + break; + case GF_REPLACE_OP_STATUS: + strcpy (op_str, "status"); + break; + case GF_REPLACE_OP_COMMIT_FORCE: + strcpy (op_str, "commit-force"); + break; + default: + strcpy (op_str, "unknown"); + break; + } + + ret = 0; +out: + return ret; +} + +int +__glusterd_handle_replace_brick (rpcsvc_request_t *req) { int32_t ret = -1; gf_cli_req cli_req = {{0,}}; @@ -47,17 +82,21 @@ glusterd_handle_replace_brick (rpcsvc_request_t *req) char operation[256]; glusterd_op_t cli_op = GD_OP_REPLACE_BRICK; char *volname = NULL; + char msg[2048] = {0,}; + xlator_t *this = NULL; GF_ASSERT (req); + this = THIS; + GF_ASSERT (this); - if (!xdr_to_generic (req->msg[0], &cli_req, - (xdrproc_t)xdr_gf_cli_req)) { + ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req); + if (ret < 0) { //failed to decode msg; req->rpc_err = GARBAGE_ARGS; goto out; } - gf_log ("glusterd", GF_LOG_INFO, "Received replace brick req"); + gf_log (this->name, GF_LOG_INFO, "Received replace brick req"); if (cli_req.dict.dict_len) { /* Unserialize the dictionary */ @@ -67,144 +106,77 @@ glusterd_handle_replace_brick (rpcsvc_request_t *req) cli_req.dict.dict_len, &dict); if (ret < 0) { - gf_log ("glusterd", GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"); + snprintf (msg, sizeof (msg), "Unable to decode the " + "command"); goto out; } } ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, "could not get volname"); + snprintf (msg, sizeof (msg), "Could not get volume name"); + gf_log (this->name, GF_LOG_ERROR, "%s", msg); goto out; } ret = dict_get_int32 (dict, "operation", &op); if (ret) { - gf_log ("", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "dict_get on operation failed"); + snprintf (msg, sizeof (msg), "Could not get operation"); goto out; } ret = dict_get_str (dict, "src-brick", &src_brick); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); + snprintf (msg, sizeof (msg), "Failed to get src brick"); + gf_log (this->name, GF_LOG_ERROR, "%s", msg); goto out; } - gf_log ("", GF_LOG_DEBUG, + 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 dest brick"); + snprintf (msg, sizeof (msg), "Failed to get dest brick"); + gf_log (this->name, GF_LOG_ERROR, "%s", msg); goto out; } - gf_log ("", GF_LOG_DEBUG, - "dst brick=%s", dst_brick); - - switch (op) { - case GF_REPLACE_OP_START: strcpy (operation, "start"); - break; - case GF_REPLACE_OP_COMMIT: strcpy (operation, "commit"); - break; - case GF_REPLACE_OP_PAUSE: strcpy (operation, "pause"); - break; - case GF_REPLACE_OP_ABORT: strcpy (operation, "abort"); - break; - case GF_REPLACE_OP_STATUS: strcpy (operation, "status"); - break; - case GF_REPLACE_OP_COMMIT_FORCE: strcpy (operation, "commit-force"); - break; - default:strcpy (operation, "unknown"); - break; - } - - gf_log ("glusterd", GF_LOG_INFO, "Received replace brick %s request", operation); - gf_cmd_log ("Volume replace-brick","volname: %s src_brick:%s" - " dst_brick:%s op:%s", volname, src_brick, dst_brick - ,operation); + (void) glusterd_get_replace_op_str (op, operation); + gf_log (this->name, GF_LOG_DEBUG, "dst brick=%s", dst_brick); + gf_log (this->name, GF_LOG_INFO, "Received replace brick %s request", + operation); - ret = glusterd_op_begin (req, GD_OP_REPLACE_BRICK, dict); - gf_cmd_log ("Volume replace-brick","on volname: %s %s", volname, - (ret) ? "FAILED" : "SUCCESS"); + ret = glusterd_op_begin (req, GD_OP_REPLACE_BRICK, dict, + msg, sizeof (msg)); out: - if (ret && dict) - dict_unref (dict); - if (cli_req.dict.dict_val) - free (cli_req.dict.dict_val);//malloced by xdr + free (cli_req.dict.dict_val);//malloced by xdr glusterd_friend_sm (); glusterd_op_sm (); - if (ret) + if (ret) { + if (msg[0] == '\0') + snprintf (msg, sizeof (msg), "Operation failed"); ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, - NULL, "operation failed"); + dict, msg); + } return ret; } - -char * -glusterd_check_brick_rb_part (char *bricks, int count, glusterd_volinfo_t *volinfo) +int +glusterd_handle_replace_brick (rpcsvc_request_t *req) { - 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; - } - - if (count) - brick = strtok_r (brick_list+1, " \n", &saveptr); - - - while ( i < count) { - ret = glusterd_brickinfo_from_brick (brick, &brickinfo); - if (ret) { - snprintf (msg, sizeof(msg), "Unable to" - " get brickinfo"); - gf_log ("", GF_LOG_ERROR, "%s", msg); - ret = -1; - 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; - } - - glusterd_brickinfo_delete (brickinfo); - brickinfo = NULL; - brick = strtok_r (NULL, " \n", &saveptr); - i++; - } - -out: - if (brick_list) - GF_FREE(brick_list); - if (brickinfo) - glusterd_brickinfo_delete (brickinfo); - if (ret) - str = gf_strdup (msg); - return str; + return glusterd_big_locked_handler (req, + __glusterd_handle_replace_brick); } static int @@ -216,7 +188,7 @@ glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo, if (!volinfo || !brickinfo) goto out; - *brickinfo = volinfo->dst_brick; + *brickinfo = volinfo->rep_brick.dst_brick; ret = 0; @@ -229,6 +201,7 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { int ret = 0; + int32_t port = 0; char *src_brick = NULL; char *dst_brick = NULL; char *volname = NULL; @@ -237,47 +210,53 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, glusterd_brickinfo_t *src_brickinfo = NULL; char *host = NULL; char *path = NULL; - char msg[2048] = {0}; + 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; + gf_boolean_t is_run = _gf_false; dict_t *ctx = NULL; glusterd_conf_t *priv = NULL; - char voldir[PATH_MAX] = {0}; - char pidfile[PATH_MAX] = {0}; + char *savetok = NULL; + char pidfile[PATH_MAX] = {0}; + char *task_id_str = NULL; + xlator_t *this = NULL; + gf_boolean_t is_force = _gf_false; - priv = THIS->private; + 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"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get src brick"); goto out; } - gf_log ("", GF_LOG_DEBUG, "src brick=%s", src_brick); + 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 dest brick"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get dest brick"); goto out; } - gf_log ("", GF_LOG_DEBUG, "dst brick=%s", dst_brick); + 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"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name"); goto out; } ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); if (ret) { - gf_log ("", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "dict get on replace-brick operation failed"); goto out; } @@ -302,7 +281,7 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, !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); + gf_log (this->name, GF_LOG_ERROR, "%s", msg); *op_errstr = gf_strdup (msg); ret = -1; @@ -311,13 +290,13 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, ret = glusterd_check_gsync_running (volinfo, &is_run); if (ret && (is_run == _gf_false)) - gf_log ("", GF_LOG_WARNING, "Unable to get the status" + gf_log (this->name, GF_LOG_WARNING, "Unable to get the status" " of active "GEOREP" session"); if (is_run) { - gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" + gf_log (this->name, 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 " + "for the volume %s.\nStop "GEOREP " sessions " "involved in this volume. Use 'volume "GEOREP " status' command for more info.", volname); @@ -329,29 +308,61 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, 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); + gf_log (this->name, GF_LOG_ERROR, "%s", msg); *op_errstr = gf_strdup (msg); ret = -1; goto out; } + ctx = glusterd_op_get_ctx(); + 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 "); + snprintf (msg, sizeof (msg), "Replace brick is already " + "started for volume"); + gf_log (this->name, GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); ret = -1; goto out; } + if (is_origin_glusterd (dict)) { + if (!ctx) { + ret = -1; + gf_log (this->name, GF_LOG_ERROR, + "Failed to get op_ctx"); + goto out; + } + + ret = glusterd_generate_and_set_task_id + (ctx, GF_REPLACE_BRICK_TID_KEY); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to generate task-id"); + goto out; + } + + } else { + ret = dict_get_str (dict, GF_REPLACE_BRICK_TID_KEY, + &task_id_str); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "Missing replace-brick-id"); + ret = 0; + } + } + is_force = dict_get_str_boolean (dict, "force", _gf_false); + break; + case GF_REPLACE_OP_PAUSE: if (glusterd_is_rb_paused (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is already " - "paused for volume "); + gf_log (this->name, 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" + gf_log (this->name, GF_LOG_ERROR, "Replace brick is not" " started for volume "); ret = -1; goto out; @@ -359,9 +370,8 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, 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" + if (!glusterd_is_rb_ongoing (volinfo)) { + gf_log (this->name, GF_LOG_ERROR, "Replace brick is not" " started or paused for volume "); ret = -1; goto out; @@ -369,25 +379,42 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, break; case GF_REPLACE_OP_COMMIT: - if (!glusterd_is_rb_started (volinfo)) { - gf_log ("", GF_LOG_ERROR, "Replace brick is not " + if (!glusterd_is_rb_ongoing (volinfo)) { + gf_log (this->name, 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_COMMIT_FORCE: + is_force = _gf_true; + break; + case GF_REPLACE_OP_STATUS: + + if (glusterd_is_rb_ongoing (volinfo) == _gf_false) { + ret = gf_asprintf (op_errstr, "replace-brick not" + " started on volume %s", + volinfo->volname); + if (ret < 0) { + *op_errstr = NULL; + goto out; + } + + gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr); + ret = -1; + goto out; + } break; + default: ret = -1; goto out; } ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, - &src_brickinfo, - GF_PATH_COMPLETE); + &src_brickinfo); if (ret) { snprintf (msg, sizeof (msg), "brick: %s does not exist in " "volume: %s", src_brick, volname); @@ -395,10 +422,9 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, goto out; } - ctx = glusterd_op_get_ctx(); if (ctx) { if (!glusterd_is_fuse_available ()) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to open /dev/" + gf_log (this->name, GF_LOG_ERROR, "Unable to open /dev/" "fuse (%s), replace-brick command failed", strerror (errno)); snprintf (msg, sizeof(msg), "Fuse unavailable\n " @@ -409,8 +435,8 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, } } - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - gf_log ("", GF_LOG_DEBUG, + if (gf_is_local_addr (src_brickinfo->hostname)) { + gf_log (this->name, GF_LOG_DEBUG, "I AM THE SOURCE HOST"); if (src_brickinfo->port && rsp_dict) { ret = dict_set_int32 (rsp_dict, "src-brick-port", @@ -422,11 +448,10 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, } } - GLUSTERD_GET_VOLUME_DIR (voldir, volinfo, priv); - GLUSTERD_GET_BRICK_PIDFILE (pidfile, voldir, - src_brickinfo->hostname, - src_brickinfo->path); - if (!glusterd_is_service_running (pidfile, NULL)) { + GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, src_brickinfo, + priv); + if ((replace_op != GF_REPLACE_OP_COMMIT_FORCE) && + !glusterd_is_service_running (pidfile, NULL)) { snprintf(msg, sizeof(msg), "Source brick %s:%s " "is not online.", src_brickinfo->hostname, src_brickinfo->path); @@ -441,49 +466,61 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, dup_dstbrick = gf_strdup (dst_brick); if (!dup_dstbrick) { ret = -1; - gf_log ("", GF_LOG_ERROR, "Memory allocation failed"); + gf_log (this->name, GF_LOG_ERROR, "Memory allocation failed"); goto out; } - host = strtok (dup_dstbrick, ":"); - path = strtok (NULL, ":"); + host = strtok_r (dup_dstbrick, ":", &savetok); + path = strtok_r (NULL, ":", &savetok); if (!host || !path) { - gf_log ("", GF_LOG_ERROR, + gf_log (this->name, 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); + + ret = glusterd_brickinfo_new_from_brick (dst_brick, &dst_brickinfo); + if (ret) + goto out; + + ret = glusterd_new_brick_validate (dst_brick, dst_brickinfo, + msg, sizeof (msg)); + if (ret) { *op_errstr = gf_strdup (msg); ret = -1; + gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr); goto out; } - if ((volinfo->rb_status ==GF_RB_STATUS_NONE) && - (replace_op == GF_REPLACE_OP_START)) { - ret = glusterd_brickinfo_from_brick (dst_brick, &dst_brickinfo); - volinfo->src_brick = src_brickinfo; - volinfo->dst_brick = dst_brickinfo; - } else { - ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); + if (!glusterd_is_rb_ongoing (volinfo) && + (replace_op == GF_REPLACE_OP_START || + replace_op == GF_REPLACE_OP_COMMIT_FORCE)) { + + volinfo->rep_brick.src_brick = src_brickinfo; + volinfo->rep_brick.dst_brick = dst_brickinfo; } if (glusterd_rb_check_bricks (volinfo, src_brickinfo, dst_brickinfo)) { - gf_log ("", GF_LOG_ERROR, "replace brick: incorrect source or" - " destination bricks specified"); + ret = -1; + *op_errstr = gf_strdup ("Incorrect source or " + "destination brick"); + if (*op_errstr) + gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr); goto out; } - if (!glusterd_is_local_addr (host)) { - ret = glusterd_brick_create_path (host, path, - volinfo->volume_id, 0777, - op_errstr); + + if (!glusterd_is_rb_ongoing (volinfo) && + gf_is_local_addr (host)) { + ret = glusterd_validate_and_create_brickpath (dst_brickinfo, + volinfo->volume_id, + op_errstr, is_force); if (ret) goto out; - } else { + } + + if (!gf_is_local_addr (host)) { ret = glusterd_friend_find (NULL, host, &peerinfo); if (ret) { snprintf (msg, sizeof (msg), "%s, is not a friend", @@ -508,17 +545,76 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, goto out; } } + + if (replace_op == GF_REPLACE_OP_START && + gf_is_local_addr (volinfo->rep_brick.dst_brick->hostname)) { + port = pmap_registry_alloc (THIS); + if (!port) { + gf_log (THIS->name, GF_LOG_CRITICAL, + "No free ports available"); + ret = -1; + goto out; + } + + ctx = glusterd_op_get_ctx(); + ret = dict_set_int32 ((ctx)?ctx:rsp_dict, "dst-brick-port", + port); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to set dst " + "brick port"); + goto out; + } + volinfo->rep_brick.dst_brick->port = port; + } + ret = 0; out: - if (dup_dstbrick) - GF_FREE (dup_dstbrick); - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + GF_FREE (dup_dstbrick); + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } static int +rb_set_mntfd (int mntfd) +{ + int ret = -1; + dict_t *ctx = NULL; + + ctx = glusterd_op_get_ctx (); + if (!ctx) { + gf_log (THIS->name, GF_LOG_CRITICAL, "Failed to get op ctx"); + goto out; + } + ret = dict_set_int32 (ctx, "mntfd", mntfd); + if (ret) + gf_log (THIS->name, GF_LOG_DEBUG, "Failed to set mnt fd " + "in op ctx"); +out: + return ret; +} + +static int +rb_get_mntfd (int *mntfd) +{ + int ret = -1; + dict_t *ctx = NULL; + + ctx = glusterd_op_get_ctx (); + if (!ctx) { + gf_log (THIS->name, GF_LOG_CRITICAL, "Failed to get op ctx"); + goto out; + } + ret = dict_get_int32 (ctx, "mntfd", mntfd); + if (ret) + gf_log (THIS->name, GF_LOG_DEBUG, "Failed to get mnt fd " + "from op ctx"); +out: + return ret; +} + +static int rb_regenerate_volfiles (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, int32_t pump_needed) @@ -540,6 +636,8 @@ rb_regenerate_volfiles (glusterd_volinfo_t *volinfo, ret = glusterd_create_rb_volfiles (volinfo, brickinfo); + dict_del (dict, "enable-pump"); + out: return ret; } @@ -561,7 +659,8 @@ rb_src_brick_restart (glusterd_volinfo_t *volinfo, ret); } - ret = glusterd_volume_stop_glusterfs (volinfo, src_brickinfo); + ret = glusterd_volume_stop_glusterfs (volinfo, src_brickinfo, + _gf_false); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to stop " "glusterfs, ret: %d", ret); @@ -588,7 +687,8 @@ rb_src_brick_restart (glusterd_volinfo_t *volinfo, } sleep (2); - ret = glusterd_volume_start_glusterfs (volinfo, src_brickinfo); + ret = glusterd_volume_start_glusterfs (volinfo, src_brickinfo, + _gf_false); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to start " "glusterfs, ret: %d", ret); @@ -608,40 +708,19 @@ 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) + 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; + int ret = -1; + int mntfd = -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"); + ret = rb_get_mntfd (&mntfd); + if (ret) goto out; - } - ret = 0; + ret = sys_fsetxattr (mntfd, xattr_key, value, strlen (value) + 1, 0); + if (ret) + gf_log (THIS->name, GF_LOG_DEBUG, "setxattr on key: " + "%s, reason: %s", xattr_key, strerror (errno)); out: return ret; @@ -658,9 +737,7 @@ rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, priv = THIS->private; - port = pmap_registry_alloc (THIS); - brickinfo->port = port; - + port = brickinfo->port; GF_ASSERT (port); runinit (&runner); @@ -671,9 +748,13 @@ rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, priv->workdir, volinfo->volname); runner_add_arg (&runner, "--xlator-option"); runner_argprintf (&runner, "src-server.listen-port=%d", port); + if (volinfo->memory_accounting) + runner_add_arg (&runner, "--mem-accounting"); - ret = runner_run (&runner); + ret = runner_run_nowait (&runner); if (ret) { + pmap_registry_remove (THIS, 0, brickinfo->path, + GF_PMAP_PORT_BRICKSERVER, NULL); gf_log ("", GF_LOG_DEBUG, "Could not start glusterfs"); goto out; @@ -693,51 +774,70 @@ 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; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + runner_t runner = {0,}; + struct stat buf = {0,}; + char mntpt[PATH_MAX] = {0,}; + int mntfd = -1; + int ret = -1; - priv = THIS->private; + this = THIS; + priv = this->private; + GLUSTERD_GET_RB_MNTPT (mntpt, sizeof (mntpt), volinfo); runinit (&runner); runner_add_arg (&runner, SBIN_DIR"/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); + runner_add_arg (&runner, mntpt); + if (volinfo->memory_accounting) + runner_add_arg (&runner, "--mem-accounting"); - ret = runner_run (&runner); + ret = runner_run_reuse (&runner); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not start glusterfs"); + runner_log (&runner, this->name, GF_LOG_DEBUG, + "Could not start glusterfs"); + runner_end (&runner); goto out; + } else { + runner_log (&runner, this->name, GF_LOG_DEBUG, + "Successfully started glusterfs"); + runner_end (&runner); } - gf_log ("", GF_LOG_DEBUG, - "Successfully started glusterfs: brick=%s:%s", - brickinfo->hostname, brickinfo->path); + ret = stat (mntpt, &buf); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, "stat on mount point %s " + "failed", mntpt); + goto out; + } - memset (cmd_str, 0, sizeof (cmd_str)); + mntfd = open (mntpt, O_DIRECTORY); + if (mntfd == -1) + goto out; - snprintf (cmd_str, 4096, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); + ret = rb_set_mntfd (mntfd); + if (ret) + goto out; - ret = stat (cmd_str, &buf); + runinit (&runner); + runner_add_args (&runner, "/bin/umount", "-l", mntpt, NULL); + ret = runner_run_reuse (&runner); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat on mountpoint failed"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "stat on mountpoint succeeded"); + runner_log (&runner, this->name, GF_LOG_DEBUG, + "Lazy unmount failed on maintenance client"); + runner_end (&runner); + goto out; + } else { + runner_log (&runner, this->name, GF_LOG_DEBUG, + "Successfully unmounted maintenance client"); + runner_end (&runner); + } - ret = 0; out: + return ret; } @@ -747,6 +847,8 @@ static const char *client_volfile_str = "volume mnt-client\n" " option remote-subvolume %s\n" " option remote-port %d\n" " option transport-type %s\n" + " option username %s\n" + " option password %s\n" "end-volume\n" "volume mnt-wb\n" " type performance/write-behind\n" @@ -758,23 +860,33 @@ rb_generate_client_volfile (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *src_brickinfo) { glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; FILE *file = NULL; char filename[PATH_MAX] = {0, }; int ret = -1; + int fd = -1; char *ttype = NULL; - priv = THIS->private; + this = THIS; + priv = this->private; - gf_log ("", GF_LOG_DEBUG, - "Creating volfile"); + gf_log (this->name, GF_LOG_DEBUG, "Creating volfile"); snprintf (filename, PATH_MAX, "%s/vols/%s/%s", priv->workdir, volinfo->volname, RB_CLIENTVOL_FILENAME); + fd = open (filename, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR); + if (fd < 0) { + gf_log (this->name, GF_LOG_ERROR, + "%s", strerror (errno)); + goto out; + } + close (fd); + file = fopen (filename, "w+"); if (!file) { - gf_log ("", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "Open of volfile failed"); ret = -1; goto out; @@ -789,7 +901,10 @@ rb_generate_client_volfile (glusterd_volinfo_t *volinfo, } fprintf (file, client_volfile_str, src_brickinfo->hostname, - src_brickinfo->path, src_brickinfo->port, ttype); + src_brickinfo->path, + src_brickinfo->port, ttype, + glusterd_auth_get_username (volinfo), + glusterd_auth_get_password (volinfo)); fclose (file); GF_FREE (ttype); @@ -803,6 +918,7 @@ out: static const char *dst_brick_volfile_str = "volume src-posix\n" " type storage/posix\n" " option directory %s\n" + " option volume-id %s\n" "end-volume\n" "volume %s\n" " type features/locks\n" @@ -810,6 +926,8 @@ static const char *dst_brick_volfile_str = "volume src-posix\n" "end-volume\n" "volume src-server\n" " type protocol/server\n" + " option auth.login.%s.allow %s\n" + " option auth.login.%s.password %s\n" " option auth.addr.%s.allow *\n" " option transport-type %s\n" " subvolumes %s\n" @@ -820,23 +938,34 @@ rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *dst_brickinfo) { glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; FILE *file = NULL; char filename[PATH_MAX] = {0, }; int ret = -1; + int fd = -1; char *trans_type = NULL; - priv = THIS->private; + this = THIS; + priv = this->private; - gf_log ("", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "Creating volfile"); snprintf (filename, PATH_MAX, "%s/vols/%s/%s", priv->workdir, volinfo->volname, RB_DSTBRICKVOL_FILENAME); + fd = creat (filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + gf_log (this->name, GF_LOG_ERROR, + "%s", strerror (errno)); + goto out; + } + close (fd); + file = fopen (filename, "w+"); if (!file) { - gf_log ("", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "Open of volfile failed"); ret = -1; goto out; @@ -848,9 +977,17 @@ rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, goto out; } - fprintf (file, dst_brick_volfile_str, dst_brickinfo->path, - dst_brickinfo->path, dst_brickinfo->path, - trans_type, dst_brickinfo->path); + fprintf (file, dst_brick_volfile_str, + dst_brickinfo->path, + uuid_utoa (volinfo->volume_id), + dst_brickinfo->path, + dst_brickinfo->path, + glusterd_auth_get_username (volinfo), + glusterd_auth_get_username (volinfo), + glusterd_auth_get_password (volinfo), + dst_brickinfo->path, + trans_type, + dst_brickinfo->path); GF_FREE (trans_type); @@ -867,20 +1004,14 @@ static int rb_mountpoint_mkdir (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *src_brickinfo) { - glusterd_conf_t *priv = NULL; - char mount_point_path[PATH_MAX] = {0,}; - int ret = -1; - - priv = THIS->private; + char mntpt[PATH_MAX] = {0,}; + int ret = -1; - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); - - ret = mkdir (mount_point_path, 0777); + GLUSTERD_GET_RB_MNTPT (mntpt, sizeof (mntpt), volinfo); + ret = mkdir (mntpt, 0777); if (ret && (errno != EEXIST)) { - gf_log ("", GF_LOG_DEBUG, "mkdir failed, errno: %d", - errno); + gf_log ("", GF_LOG_DEBUG, "mkdir failed, due to %s", + strerror (errno)); goto out; } @@ -894,19 +1025,14 @@ 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,}; + char mntpt[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); + GLUSTERD_GET_RB_MNTPT (mntpt, sizeof (mntpt), volinfo); + ret = rmdir (mntpt); if (ret) { - gf_log ("", GF_LOG_DEBUG, "rmdir failed"); + gf_log ("", GF_LOG_DEBUG, "rmdir failed, reason: %s", + strerror (errno)); goto out; } @@ -918,56 +1044,42 @@ out: static int rb_destroy_maintenance_client (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo) + glusterd_brickinfo_t *src_brickinfo) { + xlator_t *this = NULL; glusterd_conf_t *priv = NULL; - runner_t runner = {0,}; - char filename[PATH_MAX] = {0,}; - struct stat buf; - char mount_point_path[PATH_MAX] = {0,}; + char volfile[PATH_MAX] = {0,}; int ret = -1; + int mntfd = -1; - priv = THIS->private; - - snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENT_MOUNTPOINT); + this = THIS; + priv = this->private; - ret = stat (mount_point_path, &buf); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "stat failed. Cannot destroy maintenance " - "client"); + ret = rb_get_mntfd (&mntfd); + if (ret) goto out; - } - runinit (&runner); - runner_add_args (&runner, "/bin/umount", "-f", NULL); - runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, - priv->workdir, volinfo->volname); - - ret = runner_run (&runner); + ret = close (mntfd); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "umount failed on maintenance client"); + gf_log (this->name, GF_LOG_DEBUG, "Failed to close mount " + "point directory"); goto out; } ret = rb_mountpoint_rmdir (volinfo, src_brickinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "rmdir of mountpoint failed"); + gf_log (this->name, GF_LOG_DEBUG, "rmdir of mountpoint " + "failed"); goto out; } - snprintf (filename, PATH_MAX, "%s/vols/%s/%s", - priv->workdir, volinfo->volname, - RB_CLIENTVOL_FILENAME); + snprintf (volfile, PATH_MAX, "%s/vols/%s/%s", priv->workdir, + volinfo->volname, RB_CLIENTVOL_FILENAME); - ret = unlink (filename); + ret = unlink (volfile); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "unlink failed"); + gf_log ("", GF_LOG_DEBUG, "unlink of %s failed, reason: %s", + volfile, strerror (errno)); goto out; } @@ -1034,115 +1146,6 @@ out: } static int -rb_do_operation_start (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - char start_value[8192] = {0,}; - int ret = -1; - - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending start xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - snprintf (start_value, 8192, "%s:%s:%d", - dst_brickinfo->hostname, - dst_brickinfo->path, - dst_brickinfo->port); - - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_START_CMD, - start_value); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - ret = 0; - -out: - return ret; -} - -static int -rb_do_operation_pause (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - - gf_log ("", GF_LOG_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 = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_PAUSE_CMD, - "jargon"); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; - -out: - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { - ret = rb_src_brick_restart (volinfo, src_brickinfo, - 0); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not restart src-brick"); - } - } - return ret; -} - -static int rb_kill_destination_brick (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *dst_brickinfo) { @@ -1159,220 +1162,231 @@ rb_kill_destination_brick (glusterd_volinfo_t *volinfo, } static int -rb_do_operation_commit (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - int cmd_ret = -1; - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending commit 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"); - - 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 = 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; -} - -static int -rb_do_operation_abort (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) -{ - int ret = -1; - - gf_log ("", GF_LOG_DEBUG, - "replace-brick sending abort xattr"); - - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); - - ret = rb_send_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_ABORT_CMD, - "jargon"); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to send command to pump"); - } - - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } - - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); - - ret = 0; - -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); + int ret = -1; + int mntfd = -1; - 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 = rb_get_mntfd (&mntfd); + if (ret) + goto out; - ret = sys_lgetxattr (mount_point_path, xattr_key, value, 8192); + ret = sys_fgetxattr (mntfd, xattr_key, value, 8192); if (ret < 0) { - gf_log ("", GF_LOG_DEBUG, - "getxattr failed"); + gf_log (THIS->name, GF_LOG_DEBUG, "getxattr on key: %s " + "failed, reason: %s", xattr_key, strerror (errno)); goto out; } ret = 0; - out: return ret; } static int -rb_do_operation_status (glusterd_volinfo_t *volinfo, - glusterd_brickinfo_t *src_brickinfo, - glusterd_brickinfo_t *dst_brickinfo) +rb_send_cmd (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src, + glusterd_brickinfo_t *dst, + gf1_cli_replace_op op) { - 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 (); - if (!ctx) { - gf_log ("", GF_LOG_ERROR, - "Operation Context is not present"); - goto out; - } + char start_value[8192] = {0,}; + char status_str[8192] = {0,}; + char *status_reply = NULL; + char *tmp = NULL; + char *save_ptr = NULL; + char filename[PATH_MAX] = {0,}; + char *current_file = NULL; + uint64_t files = 0; + int status = 0; + dict_t *ctx = NULL; + int ret = 0; - origin = _gf_true; + GF_ASSERT (volinfo); + GF_ASSERT (src); + GF_ASSERT (dst); + GF_ASSERT ((op > GF_REPLACE_OP_NONE) + && (op <= GF_REPLACE_OP_COMMIT_FORCE)); - if (origin) { - ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Could not spawn maintenance " - "client"); - goto out; + switch (op) { + case GF_REPLACE_OP_START: + { + snprintf (start_value, sizeof (start_value), + "%s:%s:%d", dst->hostname, dst->path, + dst->port); + ret = rb_send_xattr_command (volinfo, src, dst, + RB_PUMP_CMD_START, + start_value); + } + break; + case GF_REPLACE_OP_PAUSE: + { + ret = rb_send_xattr_command (volinfo, src, dst, + RB_PUMP_CMD_PAUSE, + RB_PUMP_DEF_ARG); } + break; + case GF_REPLACE_OP_ABORT: + { + ret = rb_send_xattr_command (volinfo, src, dst, + RB_PUMP_CMD_ABORT, + RB_PUMP_DEF_ARG); + } + break; + case GF_REPLACE_OP_COMMIT: + { + ret = rb_send_xattr_command (volinfo, src, dst, + RB_PUMP_CMD_COMMIT, + RB_PUMP_DEF_ARG); + } + break; + case GF_REPLACE_OP_STATUS: + { + ret = rb_get_xattr_command (volinfo, src, dst, + RB_PUMP_CMD_STATUS, + status_str); + if (ret) + goto out; - gf_log ("", GF_LOG_DEBUG, - "mounted the replace brick client"); + ctx = glusterd_op_get_ctx (); + GF_ASSERT (ctx); + if (!ctx) { + ret = -1; + gf_log (THIS->name, GF_LOG_CRITICAL, + "ctx is not present."); + goto out; + } - ret = rb_get_xattr_command (volinfo, src_brickinfo, - dst_brickinfo, RB_PUMP_STATUS_CMD, - status); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to get status from pump"); - goto umount; - } + /* Split status reply into different parts */ + tmp = strtok_r (status_str, ":", &save_ptr); + if (!tmp) { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, + "Couldn't tokenize status string"); + goto out; + } + sscanf (tmp, "status=%d", &status); + ret = dict_set_int32 (ctx, "status", status); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Couldn't " + "set rb status in context"); + goto out; + } - gf_log ("", GF_LOG_DEBUG, - "pump status is %s", status); + tmp = NULL; + tmp = strtok_r (NULL, ":", &save_ptr); + if (!tmp) { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, + "Couldn't tokenize status string"); + goto out; + } + sscanf (tmp, "no_of_files=%"SCNu64, &files); + ret = dict_set_uint64 (ctx, "files", files); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Couldn't " + "set rb files in context"); + goto out; + } - status_reply = gf_strdup (status); - if (!status_reply) { - gf_log ("", GF_LOG_ERROR, "Out of memory"); + if (status == 0) { + tmp = NULL; + tmp = strtok_r (NULL, ":", &save_ptr); + if (!tmp) { + ret = -1; + gf_log (THIS->name, GF_LOG_ERROR, + "Couldn't tokenize status " + "string"); + goto out; + } + sscanf (tmp, "current_file=%s", filename); + current_file = gf_strdup (filename); + ret = dict_set_dynstr (ctx, "current_file", + current_file); + if (ret) { + GF_FREE (current_file); + gf_log (THIS->name, GF_LOG_ERROR, + "Couldn't set rb current file " + "in context"); + goto out; + } + } + if (status) { + ret = gf_asprintf (&status_reply, + "Number of files migrated = %" + PRIu64"\tMigration complete", + files); + } else { + ret = gf_asprintf (&status_reply, + "Number of files migrated = %" + PRIu64"\tCurrent file = %s", + files, filename); + } + if (ret == -1) { + gf_log (THIS->name, GF_LOG_ERROR, + "Failed to create status_reply string"); + goto out; + } + ret = dict_set_dynstr (ctx, "status-reply", + status_reply); + if (ret) { + GF_FREE (status_reply); + gf_log (THIS->name, GF_LOG_ERROR, "Couldn't " + "set rb status response in context."); + goto out; + } + } + break; + default: + { + GF_ASSERT (0); ret = -1; - goto umount; + gf_log (THIS->name, GF_LOG_CRITICAL, "Invalid replace" + " brick subcommand."); } + break; + } +out: + return ret; +} - ret = dict_set_dynstr (ctx, "status-reply", - status_reply); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "failed to set pump status in ctx"); +static int +rb_do_operation (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *src_brickinfo, + glusterd_brickinfo_t *dst_brickinfo, + gf1_cli_replace_op op) +{ - } + int ret = -1; + char op_str[256] = {0, }; + xlator_t *this = NULL; - umount: - ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); - if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to destroy maintenance " - "client"); - goto out; - } + this = THIS; + + ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, "Could not spawn " + "maintenance client"); + goto umount; } - gf_log ("", GF_LOG_DEBUG, - "unmounted the replace brick client"); -out: - return ret; + ret = rb_send_cmd (volinfo, src_brickinfo, dst_brickinfo, op); + if (ret) { + (void) glusterd_get_replace_op_str (op, op_str); + gf_log (this->name, GF_LOG_DEBUG, "Sending replace-brick " + "sub-command %s failed.", op_str); + } + +umount: + if (rb_destroy_maintenance_client (volinfo, src_brickinfo)) + gf_log (this->name, GF_LOG_DEBUG, "Failed to destroy " + "maintenance client"); + + return ret; } /* Set src-brick's port number to be used in the maintenance mount @@ -1390,14 +1404,11 @@ rb_update_srcbrick_port (glusterd_brickinfo_t *src_brickinfo, dict_t *rsp_dict, this = THIS; - ctx = glusterd_op_get_ctx (); - if (ctx) { - dict_ret = dict_get_int32 (req_dict, "src-brick-port", &src_port); - if (src_port) - src_brickinfo->port = src_port; - } + 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)) { + if (gf_is_local_addr (src_brickinfo->hostname)) { gf_log ("", GF_LOG_INFO, "adding src-brick port no"); @@ -1446,15 +1457,12 @@ rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict, int dict_ret = 0; int dst_port = 0; - ctx = glusterd_op_get_ctx (); - if (ctx) { - dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port); - if (dst_port) - dst_brickinfo->port = dst_port; + dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port); + if (!dict_ret) + dst_brickinfo->port = dst_port; - } - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { + if (gf_is_local_addr (dst_brickinfo->hostname)) { gf_log ("", GF_LOG_INFO, "adding dst-brick port no"); @@ -1493,18 +1501,18 @@ glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo, GF_ASSERT (volinfo); - ret = glusterd_brickinfo_from_brick (new_brick, - &new_brickinfo); + ret = glusterd_brickinfo_new_from_brick (new_brick, + &new_brickinfo); if (ret) goto out; - ret = glusterd_volume_brickinfo_get_by_brick (old_brick, volinfo, - &old_brickinfo, - GF_PATH_COMPLETE); + ret = glusterd_resolve_brick (new_brickinfo); + if (ret) goto out; - ret = glusterd_resolve_brick (new_brickinfo); + ret = glusterd_volume_brickinfo_get_by_brick (old_brick, + volinfo, &old_brickinfo); if (ret) goto out; @@ -1522,13 +1530,13 @@ glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo, goto out; if (GLUSTERD_STATUS_STARTED == volinfo->status) { - ret = glusterd_brick_start (volinfo, new_brickinfo); + ret = glusterd_brick_start (volinfo, new_brickinfo, _gf_false); if (ret) goto out; } - out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -1547,6 +1555,7 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) char *dst_brick = NULL; glusterd_brickinfo_t *src_brickinfo = NULL; glusterd_brickinfo_t *dst_brickinfo = NULL; + char *task_id_str = NULL; this = THIS; GF_ASSERT (this); @@ -1556,26 +1565,23 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) ret = dict_get_str (dict, "src-brick", &src_brick); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get src brick"); goto out; } - gf_log (this->name, GF_LOG_DEBUG, - "src brick=%s", src_brick); + 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"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get dst brick"); goto out; } - gf_log (this->name, GF_LOG_DEBUG, - "dst brick=%s", dst_brick); + 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"); + gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name"); goto out; } @@ -1588,29 +1594,30 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) ret = glusterd_volinfo_find (volname, &volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); + gf_log (this->name, GF_LOG_ERROR, "Unable to allocate memory"); goto out; } ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, - &src_brickinfo, - GF_PATH_COMPLETE); + &src_brickinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); + gf_log (this->name, 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 " + gf_log (this->name, 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"); + gf_log (this->name, GF_LOG_DEBUG, + "Unable to resolve dst-brickinfo"); goto out; } @@ -1619,45 +1626,82 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) 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; + + /* Set task-id, if available, in op_ctx dict for operations + * other than start + */ + if (is_origin_glusterd (dict)) { + ctx = glusterd_op_get_ctx(); + if (!ctx) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + "get op_ctx"); + ret = -1; + goto out; + } + if (!uuid_is_null (volinfo->rep_brick.rb_id)) { + ret = glusterd_copy_uuid_to_dict + (volinfo->rep_brick.rb_id, ctx, + GF_REPLACE_BRICK_TID_KEY); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set " + "replace-brick-id"); + goto out; + } + } + } } + 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, + ret = dict_get_str (dict, GF_REPLACE_BRICK_TID_KEY, &task_id_str); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Missing replace-brick-id"); + ret = 0; + } else { + uuid_parse (task_id_str, volinfo->rep_brick.rb_id); + } + + if (gf_is_local_addr (dst_brickinfo->hostname)) { + gf_log (this->name, GF_LOG_INFO, "I AM THE DESTINATION HOST"); if (!glusterd_is_rb_paused (volinfo)) { - ret = rb_spawn_destination_brick (volinfo, dst_brickinfo); + ret = rb_spawn_destination_brick + (volinfo, dst_brickinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to spawn destination brick"); + gf_log (this->name, 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 "); + gf_log (this->name, GF_LOG_ERROR, + "Replace brick is already started=> no " + "need to restart dst brick "); } } - if (!glusterd_is_local_addr (src_brickinfo->hostname)) { + if (gf_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"); + gf_log (this->name, GF_LOG_DEBUG, + "Could not restart src-brick"); goto out; } } - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log ("", GF_LOG_INFO, + if (gf_is_local_addr (dst_brickinfo->hostname)) { + gf_log (this->name, GF_LOG_INFO, "adding dst-brick port no"); ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, @@ -1671,84 +1715,79 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) } case GF_REPLACE_OP_COMMIT: - case GF_REPLACE_OP_COMMIT_FORCE: { ctx = glusterd_op_get_ctx (); if (ctx) { - ret = rb_do_operation_commit (volinfo, src_brickinfo, dst_brickinfo); + ret = rb_do_operation (volinfo, src_brickinfo, + dst_brickinfo, + GF_REPLACE_OP_COMMIT); if (ret) { - gf_log ("", GF_LOG_ERROR, + gf_log (this->name, 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, + } + /* fall through */ + case GF_REPLACE_OP_COMMIT_FORCE: + { + if (gf_is_local_addr (dst_brickinfo->hostname)) { + gf_log (this->name, GF_LOG_DEBUG, "I AM THE DESTINATION HOST"); - ret = rb_kill_destination_brick (volinfo, dst_brickinfo); + ret = rb_kill_destination_brick (volinfo, + dst_brickinfo); if (ret) { - gf_log ("", GF_LOG_DEBUG, - "Failed to kill destination brick"); + gf_log (this->name, GF_LOG_CRITICAL, + "Unable to cleanup dst brick"); goto out; } } - if (ret) { - gf_log ("", GF_LOG_CRITICAL, - "Unable to cleanup dst brick"); - goto out; - } - - ret = glusterd_nodesvcs_stop (volinfo); if (ret) { - gf_log ("", GF_LOG_ERROR, + gf_log (this->name, 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); + gf_log (this->name, GF_LOG_CRITICAL, "Unable to add " + "dst-brick: %s to volume: %s", dst_brick, + volinfo->volname); (void) glusterd_nodesvcs_handle_graph_change (volinfo); goto out; } - volinfo->defrag_status = 0; + volinfo->rebal.defrag_status = 0; ret = glusterd_nodesvcs_handle_graph_change (volinfo); if (ret) { - gf_log ("", GF_LOG_CRITICAL, + gf_log (this->name, GF_LOG_CRITICAL, "Failed to generate nfs volume file"); } 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; + glusterd_brickinfo_delete (volinfo->rep_brick.dst_brick); + volinfo->rep_brick.src_brick = NULL; + volinfo->rep_brick.dst_brick = NULL; + uuid_clear (volinfo->rep_brick.rb_id); } break; case GF_REPLACE_OP_PAUSE: { - gf_log ("", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "Received pause - doing nothing"); ctx = glusterd_op_get_ctx (); if (ctx) { - ret = rb_do_operation_pause (volinfo, src_brickinfo, - dst_brickinfo); + ret = rb_do_operation (volinfo, src_brickinfo, + dst_brickinfo, + GF_REPLACE_OP_PAUSE); if (ret) { - gf_log ("", GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "Pause operation failed"); goto out; } @@ -1763,22 +1802,29 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) ctx = glusterd_op_get_ctx (); if (ctx) { - ret = rb_do_operation_abort (volinfo, src_brickinfo, dst_brickinfo); + ret = rb_do_operation (volinfo, src_brickinfo, + dst_brickinfo, + GF_REPLACE_OP_ABORT); if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, + 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"); - } - + if (gf_is_local_addr (src_brickinfo->hostname)) { + ret = rb_src_brick_restart (volinfo, src_brickinfo, + 0); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Couldn't restart src brick " + "with pump xlator disabled."); + goto out; + } + } - if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { - gf_log (THIS->name, GF_LOG_INFO, + if (gf_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) { @@ -1788,14 +1834,15 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) } } glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); - glusterd_brickinfo_delete (volinfo->dst_brick); - volinfo->src_brick = volinfo->dst_brick = NULL; + glusterd_brickinfo_delete (volinfo->rep_brick.dst_brick); + volinfo->rep_brick.src_brick = NULL; + volinfo->rep_brick.dst_brick = NULL; } break; case GF_REPLACE_OP_STATUS: { - gf_log ("", GF_LOG_DEBUG, + gf_log (this->name, GF_LOG_DEBUG, "received status - doing nothing"); ctx = glusterd_op_get_ctx (); if (ctx) { @@ -1803,14 +1850,15 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) ret = dict_set_str (ctx, "status-reply", "replace brick has been paused"); if (ret) - gf_log (THIS->name, GF_LOG_ERROR, + gf_log (this->name, GF_LOG_ERROR, "failed to set pump status" - "in ctx"); + " in ctx"); goto out; } - ret = rb_do_operation_status (volinfo, src_brickinfo, - dst_brickinfo); + ret = rb_do_operation (volinfo, src_brickinfo, + dst_brickinfo, + GF_REPLACE_OP_STATUS); if (ret) goto out; } @@ -1826,7 +1874,7 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) - gf_log (THIS->name, GF_LOG_ERROR, "Couldn't store" + gf_log (this->name, GF_LOG_ERROR, "Couldn't store" " replace brick operation's state"); out: @@ -1847,6 +1895,7 @@ glusterd_do_replace_brick (void *data) glusterd_brickinfo_t *src_brickinfo = NULL; glusterd_brickinfo_t *dst_brickinfo = NULL; glusterd_conf_t *priv = NULL; + uuid_t *txn_id = &global_txn_id; int ret = 0; @@ -1866,6 +1915,10 @@ glusterd_do_replace_brick (void *data) gf_log ("", GF_LOG_DEBUG, "Replace brick operation detected"); + ret = dict_get_bin (dict, "transaction_id", (void **)&txn_id); + + gf_log ("", GF_LOG_DEBUG, "transaction ID = %s", uuid_utoa (*txn_id)); + ret = dict_get_int32 (dict, "operation", &op); if (ret) { gf_log ("", GF_LOG_DEBUG, @@ -1904,8 +1957,7 @@ glusterd_do_replace_brick (void *data) } ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, - &src_brickinfo, - GF_PATH_COMPLETE); + &src_brickinfo); if (ret) { gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); goto out; @@ -1944,11 +1996,10 @@ glusterd_do_replace_brick (void *data) goto out; } - ret = rb_do_operation_start (volinfo, src_brickinfo, dst_brickinfo); - if (ret) { - glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); + ret = rb_do_operation (volinfo, src_brickinfo, dst_brickinfo, + GF_REPLACE_OP_START); + if (ret) goto out; - } break; case GF_REPLACE_OP_PAUSE: case GF_REPLACE_OP_ABORT: @@ -1963,12 +2014,11 @@ glusterd_do_replace_brick (void *data) out: if (ret) - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, + txn_id, NULL); else - ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, NULL); - - if (dict) - dict_unref (dict); + ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, + txn_id, NULL); glusterd_op_sm (); } |
